Logo Море(!) аналитической информации!
IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware
Архив форумов ЦИТФорума
Море(!) вопросов - Море(!) ответов
 
 FAQFAQ   ПоискПоиск   ПользователиПользователи   ГруппыГруппы   РегистрацияРегистрация 
 ПрофильПрофиль   Войти и проверить личные сообщенияВойти и проверить личные сообщения   ВходВход 
Как правильно задавать вопросы

Как из char-строки удалить все пробелы?

 
Перейти:  
Этот форум закрыт, вы не можете писать новые сообщения и редактировать старые.   Эта тема закрыта, вы не можете писать ответы и редактировать сообщения.    Список форумов Архив форумов ЦИТФорума -> Программирование
Предыдущая тема :: Следующая тема  
Автор Сообщение
Tahir
Гость





СообщениеДобавлено: Вт Апр 01 2003 16:05    Заголовок сообщения: Как из char-строки удалить все пробелы? Ответить с цитатой

Как из char-строки удалить все пробелы? Приложение на VC++.
Вернуться к началу
GREA



Зарегистрирован: 14.05.2003
Сообщения: 758
Откуда: Новосибирск

СообщениеДобавлено: Ср Апр 02 2003 13:30    Заголовок сообщения: Re: Как из char-строки удалить все пробелы? Ответить с цитатой

Строка есть массив.
Создай второй массив и копируй туда посимвольно из первого массива (на нужные места), проверяя на пробелы. Стандартной функции вроде нет.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
Tahir
Гость





СообщениеДобавлено: Ср Апр 02 2003 14:03    Заголовок сообщения: Re: Как из char-строки удалить все пробелы? Ответить с цитатой

Это банально и некрасиво. Уже есть решение без посимвольного копирования.
Вернуться к началу
Petr
Гость





СообщениеДобавлено: Ср Апр 02 2003 15:18    Заголовок сообщения: Re: Как из char-строки удалить все пробелы? Ответить с цитатой

Оно реализовано в твоем верхнем вопросе?
Вернуться к началу
Tahir
Гость





СообщениеДобавлено: Ср Апр 02 2003 15:20    Заголовок сообщения: В каком верхнем? Ответить с цитатой

В каком верхнем? Есть char-массив с пробелами где угодно, по сколько угодно. После работы маленькой функции нет ни одного пробела. Указатель остается.
Вернуться к началу
GREA



Зарегистрирован: 14.05.2003
Сообщения: 758
Откуда: Новосибирск

СообщениеДобавлено: Чт Апр 03 2003 07:13    Заголовок сообщения: Re: В каком верхнем? Ответить с цитатой

В string.h есть функция (забыл название), которая определяет адрес первого заданного символа (в нашем случае пробела). Возвращает указатель на этот пробел. Потом используешь strcat со смещение на следующий после пробела символ.
Вернуться к началу
Посмотреть профиль Отправить личное сообщение
_DM
Гость





СообщениеДобавлено: Пн Апр 07 2003 18:37    Заголовок сообщения: Re: Это Ответ !!!! Ответить с цитатой

Написать можно все в двух циклах один меньше другого и при этом без всяких дополнительных или встроенных функций. Ниже приведена реализация кода на VС++.

str -строка, указатель типа char или массив из символов. Строка обязательно должна кончатся нулем.
int iGo=0;// индекс строки, от куда копируем символ.
int iStr=0;// индекс строки, куда копируем символ.
while(str[iStr])
{
while(str[iGo]==' ')iGo++;//пропуск пробелов
str[iStr]=str[iGo];//копирование символов
iStr++;
iGo++;
}
Вернуться к началу
Tahir
Гость





СообщениеДобавлено: Вт Апр 08 2003 09:10    Заголовок сообщения: Есть и попроще вариант :) Ответить с цитатой

char* alltrim(char* A, ) {
for (register int i=start; (int)strlen(A);i++)
if (isspace(A[i])){
strcpy(A+i,A+i+1);
i--;
}
return A;
}

Кто проще придумает???
Вернуться к началу
Борис
Гость





СообщениеДобавлено: Вт Апр 08 2003 19:38    Заголовок сообщения: Попробую :) Ответить с цитатой

char* alltrim(char* A, ) {
char *B=A, *C=A;
while(*B) if(!isspace(*C++)) *B++=C[-1];
return A;
}
Вернуться к началу
Борис
Гость





СообщениеДобавлено: Вт Апр 08 2003 20:37    Заголовок сообщения: Маленькое уточнение :) Ответить с цитатой

char* alltrim(char* A) {
char *B=A, *C=A;
while(*B) if(!isspace(*C++)) if(*B=C[-1]) B++;
return A;
}
Вернуться к началу
Борис
Гость





СообщениеДобавлено: Вт Апр 08 2003 20:44    Заголовок сообщения: Это ошибка !!!! Ответить с цитатой

>>int iGo=0;// индекс строки, от куда копируем символ.
>>int iStr=0;// индекс строки, куда копируем символ.
>>while(str[iStr])
>>{
>> while (str[iGo]==' ')iGo++;//пропуск пробелов
>> str[iStr]=str[iGo];//копирование символов
>> iStr++;
>> iGo++;

После этого оператора str[iStr] может быть не нулевым и цикл продолжится

>>}
Вернуться к началу
Sclis
Гость





СообщениеДобавлено: Чт Апр 10 2003 12:05    Заголовок сообщения: Re: Маленькое уточнение :) Ответить с цитатой

void deltrim(char* s1){
for(char * s=s1;*s;s++)
if (*s!=' ') *s1++=*s;
*s1='\0';
}
1. если меняешь аргумент - возвращай его, а не функцию. если функция возвращает ссылку не меняй аргумент. не ошибка. просто мнение. чтобы не путаться с lvalue потом.
2. формальный параметр - ссылка, а не значение, но сама переменная-ссылка не та же, что в программе=> ее можно попользовать Smileраз уж меняем аргумент, а не создаем новую строку.
3. последним штрихом - закрыть строку Smile

а если надо возвращать строку и принимать аргументами даже константы:
char * deltrim1(char* s1){
char *s=s1;
int n=0;
while(*s)if(*s++!=' ') n++;

char* s2=new(char[n+1]);

for(s=s2;*s1;s1++)
if (*s1!=' ') *s2++=*s1;
*s2='\0';
return s;
}
Вернуться к началу
Борис
Гость





СообщениеДобавлено: Пн Апр 14 2003 14:09    Заголовок сообщения: Маленькое уточнение с маленькой неточностью :) Ответить с цитатой

В решении есть маленькая неточность, которая может оказаться критичной, если в строке нет пробелов:

>>if (*s!=' ') *s1++=*s;
когда при исполнении этой строки достигнут конец строки (то есть *s=='\0'), *s1 получает значение '\0' и перемещается на следующий символ, поэтому следующее присваивание
>>*s1='\0';
_может_ заменить символ за пределами строки.

В подавляющем большинстве случаев это не важно, так как при наличии пробелов в исходной строке эта замена произойдет в пределах старой строки, а в отсутствии пробелов этот символ из-за выравнивания по блокам (параграфам) вероятнее всего окажется в хвостовой, неиспользуемой области, тем не менее полной гарантии этого нет. Поэтому возможно разрушение данных.
Аналогичная неточность в варианте с возвращаемым указателем:
>>if (*s1!=' ') *s2++=*s1;
>>*s2='\0';

Эта неточность присутствует также в вариантах _DM 07-04-2003 19:37 и Борис 08-04-2003 20:38

Исправить неточность следует так:
for (char *s=s1; *s; s++) if (*s!=' ') if (*s1=*s) s1++;

и получаем вариант, аналогичный варианту Борис 08-04-2003 21:37. Разница в моменте увеличения s (в конце или в середине цикла) и связанного с этим разыименования при занесении непробела (*s или s[-1])
Вернуться к началу
Sclis
Гость





СообщениеДобавлено: Вт Апр 15 2003 04:40    Заголовок сообщения: Re: Маленькое уточнение с маленькой неточностью :) Ответить с цитатой

Smile))
*s++=*s1 - "выполнить присваивание и ПОСЛЕ добавить единицу к s"
для случая, когда инкремент надо выполнить ДО существует операция *(++s) .
так, что логически испоняться код *s++=*s; будет абсолютно так же как
if(*s=*s1)s++; просто он в записи короче и лишняя операция проверки условия отсутствует.
Цикл не проходит при *s='/0'. поэтому и приходится закрывать строку дополнительной операцией в конце функции. Вобще, загони в компилятор и попробуй Smile)
Вернуться к началу
Борис
Гость





СообщениеДобавлено: Вт Апр 15 2003 09:43    Заголовок сообщения: А вот как раз и нет! :) (+) Ответить с цитатой

>>логически исполняться код *s++=*s1; будет абсолютно так же как
>>if(*s=*s1)s++; просто он в записи короче и лишняя операция проверки условия отсутствует.

Как раз не абсолютно: при *s++=*s1; s увеличивается ВСЕГДА, а при if(*s=*s1)s++; s увеличивается только при *s1!='\0'. И операция проверки совсем нелишняя, просто в твоем варианте она вставлена в for(...;*s1;...). За счет этого ты действительно можешь внутри цикла обойтись без проверки, так как у тебя внутри цикла *s1!='\0'. Тут я не прав, говоря, что это неточность. А вообще, для самого короткого (ассемблерного) варианта лучше написать в точке проверки
if(*s=*s1)s++; else return;
правда будет ли это считаться короче?

>> Цикл не проходит при *s='\0'. поэтому и приходится закрывать строку дополнительной операцией в конце функции.

Именно поэтому выгодней использовать while() вместо for(), также как в классическом примере копирования строки: while(*dest++=*src++);

>>Вобще, загони в компилятор и попробуй

Нехорошо отсылать к компилятору в теоретических вопросах Smile

А теперь сравни 3 варианта: первый вариант твой, второй и третий мои. Даже при использовании более динного слова (while) мой короче на 1 символ. Smile

for(s=s1;*s1;s++)if(*s1!=' ')*s++=*s1;*s='\0';
s=s1;while(*s)if(*s1++!=' ')if(*s=s1[-1])s++;
for(s=s1;*s;)if(*s1++!=' ')if(*s=s1[-1])s++;

Мои варианты работают и с возвращаемым указателем, и без него, а в твоем сообщении вариант с возвращаемым указателем гораздо длиннее. Smile
Вернуться к началу
Sclis
Гость





СообщениеДобавлено: Вт Апр 15 2003 14:28    Заголовок сообщения: Re: А вот как раз и нет! :) (+) Ответить с цитатой

ну хорошо, согласен на вариант
for(s=s1;*s;s1++)if(*s1!=' ')*s++=*s1;
Smile согласен, что он упрощает немного код, но не s[-1]... тогда уж к индексам и Паскалю... указатели тут метод избавится от возьни с индексаи (код не эффективный будет) не стоит смешивать их. Вся ценность работы с указателями - более простой вид адресации в ассемблерном коде, а ты заставляешь машину и ту и другую адресацию использовать. Получается хуже чем любой из двух "чистых" методов
эээ... "код короче на 1 символ" - Smile аргумент не из первого десятка. "код короче вдвое" - еще можно рассматривать... Smile "код проще и элегантней" - маячит где-то на первых позициях Smile
возвращаемый указатель должен быть не на аргумент. иначе провоцируешь на код вида if(f(s)!=s)... где-то в программе (с твоей функцией f) так не делают. просто не принято Smile выделяй новую память под новыую переменную указатель на которую возвращаешь (вот потому второй мой вариант и получился длинее. а не из-за того, что переменные экономил)
компилятор.. хм.. что же тут теоретического в споре? голимая практика Smile мы же не "парадигмы ментальности алгоритмического подхода к восприятию" наматываем Smile попробуй свой вариант со строковой константой Smile.
ну и ЗЫ: спор становится битвой за авторитет, а не за истину. считаю правильным остановиться на достигнутом Smile твой ответ почитаю (если напишешь) но сам писать больше не буду Smile
Вернуться к началу
Борис
Гость





СообщениеДобавлено: Вт Апр 15 2003 15:45    Заголовок сообщения: Ok. Дискуссия хорошо раскрасила будничный рабочий день :) (-) Ответить с цитатой

-
Вернуться к началу
Показать сообщения:   
Этот форум закрыт, вы не можете писать новые сообщения и редактировать старые.   Эта тема закрыта, вы не можете писать ответы и редактировать сообщения.    Список форумов Архив форумов ЦИТФорума -> Программирование Часовой пояс: GMT + 3
Страница 1 из 1

 
Перейти:  
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах


Powered by phpBB © 2001, 2002 phpBB Group
Русская поддержка phpBB

 

IT-консалтинг Software Engineering Программирование СУБД Безопасность Internet Сети Операционные системы Hardware

Информация для рекламодателей PR-акции, размещение рекламы — adv@citforum.ru,
тел. +7 495 6608306, ICQ 232284597
Пресс-релизы — pr@citforum.ru
Послать комментарий
Информация для авторов
This Web server launched on February 24, 1997
Copyright © 1997-2000 CIT, © 2001-2006 CIT Forum
Внимание! Любой из материалов, опубликованных на этом сервере, не может быть воспроизведен в какой бы то ни было форме и какими бы то ни было средствами без письменного разрешения владельцев авторских прав. Подробнее...