URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 2072
[ Назад ]

Исходное сообщение
"добавление к (char *) в конец (char)"

Отправлено NetKnight , 15-Сен-03 17:10 
Что-то после паскаля у меня проблемы со строками в сях :)
Вообщем нужно к строке добавить символ, правильно ли я делаю?

char* chrcat(char *str, char chr)
{
char *res=strdup(str);
res=(char *)realloc(res,sizeof(str)+1);
res[strlen(str)]=chr;
return res;
}

Или я опять велосипед изобретаю и уже что-то сущевствует для этого? :)

Ещё вопрос, как из строки вытащить нужную подстроку с определённой позиции по другую определённую позицию? Перебирать как массив?


Содержание

Сообщения в этом обсуждении
"добавление к (char *) в конец (char)"
Отправлено bogerm , 15-Сен-03 20:46 
>Что-то после паскаля у меня проблемы со строками в сях :)
>Вообщем нужно к строке добавить символ, правильно ли я делаю?
>
>char* chrcat(char *str, char chr)
>{
> char *res=strdup(str);
> res=(char *)realloc(res,sizeof(str)+1);
> res[strlen(str)]=chr;
> return res;
>}
>
>Или я опять велосипед изобретаю и уже что-то сущевствует для этого? :)
>
Идея верная, но есть два замечания
1) Функция strdup создает копию строки, поэтому chrcat нельзя будет использовать для изменения исходной строки. Например
str = strcat( str, 'a' );
вызовет утечку памяти, т.к. указатель на исходный str будет утерян.
2) В C/C++ принято соглашение, что все строки оканчиватся нулем:
res[strlen(str)+1] = 0;

Я бы написал эту функцию так:

char* chrcat( char* str, char chr )
{
  register char *tmp=str;
  int len = strlen( str )+1;

  if ((tmp=(char*)realloc(tmp, len + 1) == NULL)
     return NULL;

  tmp[len-1] = chr;
  tmp[len] = 0;

  return tmp;
}


>
>Ещё вопрос, как из строки вытащить нужную подстроку с определённой позиции по
>другую определённую позицию? Перебирать как массив?

Например так:

char *substr = (char*)malloc( end - begin + 1 );
strncpy( substr, str+begin, end-begin+1 );


"добавление к (char *) в конец (char)"
Отправлено XMan , 16-Сен-03 02:47 
> char *substr = (char*)malloc( end - begin + 1 );
> strncpy( substr, str+begin, end-begin+1 );

Доработка:

substr[end - begin]=0;

Ибо после "malloc" в буфере будет неизвестно что (она же не очищает буфер), а функция "strncpy" не добавляет в конец строки 0, если такового не встречалось в исходной строке.

Вопрошающему - при работе со строками уделяй большое внимание выделяемому под них буферу. Связано с тем, что формат строки в Паскале и в Си отличатеся в принципе.

Паскаль: [1 байт - длина][до 255 байт - данные...]
Си: [сколько хочешь байт - данные][1 байт - ограничитель строки '\0']

Дабы не попадать в "чужую" память и не вызывать "Segmentation fault" или не ловить в программе уязвимости, основанные на переполнении буфера (подавляющее большинство), всегда выделяй буфер на 1 байт больше нужного и заполняй этот байт (а лучше всю строку, ибо можно глюки ловить на ровном месте, если хитро с ней работать) нулями.
Например, если ты ожидаешь получить максимум 1024 байт, выдели буфер длиной 1025 байт.

PS. Под выражением "чужая память" я подразумевал память, которую система тебе не выделяла. Это совсем не означает, что ты залезешь в память соседней программы :)


"добавление к (char *) в конец (char)"
Отправлено NetKnight , 16-Сен-03 03:13 
>Вопрошающему - при работе со строками уделяй большое внимание выделяемому под них
>буферу. Связано с тем, что формат строки в Паскале и в
>Си отличатеся в принципе.
>Паскаль: [1 байт - длина][до 255 байт - данные...]
>Си: [сколько хочешь байт - данные][1 байт - ограничитель строки '\0']

Уже понял, здесь наверно строка роднится с Дельфийским PChar. Там тоже надо выделять память и она кончается символом '\0'. Жаль, что на паскале не пишут под юникса, там простые вещи делаются просто. :)

>Дабы не попадать в "чужую" память и не вызывать "Segmentation fault" или
>не ловить в программе уязвимости, основанные на переполнении буфера (подавляющее большинство),
>всегда выделяй буфер на 1 байт больше нужного и заполняй этот
>байт (а лучше всю строку, ибо можно глюки ловить на ровном
>месте, если хитро с ней работать) нулями.

Учту это. Насколько помню теорию - строка кончается, когда встречается первый символ "\0", а остальное игнорируется. Так? А когда вызывается strlen() и sizeof() - это правило тоже действует?


"добавление к (char *) в конец (char)"
Отправлено XMan , 16-Сен-03 05:56 
> А когда вызывается strlen() и sizeof() - это правило тоже действует?

Это правило действует для любой строковой функции.

sizeof - это не совсем функция. Ей фиолетово, что подсовывать. Она заменяется на нужное значение на этапе компиляции.


"добавление к (char *) в конец (char)"
Отправлено messer , 16-Сен-03 08:56 
>Дабы не попадать в "чужую" память и не вызывать "Segmentation fault" или
>не ловить в программе уязвимости, основанные на переполнении буфера (подавляющее большинство),
>всегда выделяй буфер на 1 байт больше нужного и заполняй этот
>байт (а лучше всю строку, ибо можно глюки ловить на ровном
>месте, если хитро с ней работать) нулями.
>Например, если ты ожидаешь получить максимум 1024 байт, выдели буфер длиной 1025
>байт.

хех, если программа узявима к переполнению буфера то добавляй ты хоть один, хотя два байта - это тебя не спасет (просто увеличишь переполняемый буыер). тем более если ты захочешь статически выделить 1025 байт (char str[1025]) gcc выделит не 1025 байт, а число кратное 32, т.е. в этом случае 1056 байт.


"добавление к (char *) в конец (char)"
Отправлено NetKnight , 16-Сен-03 03:04 
>  register char *tmp=str;
А что в этой строке обозначает register? Никогда не встречал.

Вообще странно, что такие функции не написаны в стандартных библиотеках как раз для того, чтоб избежать ошибок :(


"добавление к (char *) в конец (char)"
Отправлено bogerm , 16-Сен-03 04:58 
>>  register char *tmp=str;
>А что в этой строке обозначает register? Никогда не встречал.

Дает указание компилятору по возможности размещать переменную в регистре.
В принципе совсем не обязательно, так как современные компиляторы часто сами размещают локальные переменные в регистрах при включенной оптимизации. Я это указываю чисто машинально по привычке.

>
>Вообще странно, что такие функции не написаны в стандартных библиотеках как раз
>для того, чтоб избежать ошибок :(

Для C++ есть много замечательных библиотек, таких как STL или Qt. Писать программы с их помощью не сложнее чем на паскале или перле.