Что-то после паскаля у меня проблемы со строками в сях :)
Вообщем нужно к строке добавить символ, правильно ли я делаю?char* chrcat(char *str, char chr)
{
char *res=strdup(str);
res=(char *)realloc(res,sizeof(str)+1);
res[strlen(str)]=chr;
return res;
}Или я опять велосипед изобретаю и уже что-то сущевствует для этого? :)
Ещё вопрос, как из строки вытащить нужную подстроку с определённой позиции по другую определённую позицию? Перебирать как массив?
>Что-то после паскаля у меня проблемы со строками в сях :)
>Вообщем нужно к строке добавить символ, правильно ли я делаю?
>
>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 *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. Под выражением "чужая память" я подразумевал память, которую система тебе не выделяла. Это совсем не означает, что ты залезешь в память соседней программы :)
>Вопрошающему - при работе со строками уделяй большое внимание выделяемому под них
>буферу. Связано с тем, что формат строки в Паскале и в
>Си отличатеся в принципе.
>Паскаль: [1 байт - длина][до 255 байт - данные...]
>Си: [сколько хочешь байт - данные][1 байт - ограничитель строки '\0']Уже понял, здесь наверно строка роднится с Дельфийским PChar. Там тоже надо выделять память и она кончается символом '\0'. Жаль, что на паскале не пишут под юникса, там простые вещи делаются просто. :)
>Дабы не попадать в "чужую" память и не вызывать "Segmentation fault" или
>не ловить в программе уязвимости, основанные на переполнении буфера (подавляющее большинство),
>всегда выделяй буфер на 1 байт больше нужного и заполняй этот
>байт (а лучше всю строку, ибо можно глюки ловить на ровном
>месте, если хитро с ней работать) нулями.Учту это. Насколько помню теорию - строка кончается, когда встречается первый символ "\0", а остальное игнорируется. Так? А когда вызывается strlen() и sizeof() - это правило тоже действует?
> А когда вызывается strlen() и sizeof() - это правило тоже действует?Это правило действует для любой строковой функции.
sizeof - это не совсем функция. Ей фиолетово, что подсовывать. Она заменяется на нужное значение на этапе компиляции.
>Дабы не попадать в "чужую" память и не вызывать "Segmentation fault" или
>не ловить в программе уязвимости, основанные на переполнении буфера (подавляющее большинство),
>всегда выделяй буфер на 1 байт больше нужного и заполняй этот
>байт (а лучше всю строку, ибо можно глюки ловить на ровном
>месте, если хитро с ней работать) нулями.
>Например, если ты ожидаешь получить максимум 1024 байт, выдели буфер длиной 1025
>байт.хех, если программа узявима к переполнению буфера то добавляй ты хоть один, хотя два байта - это тебя не спасет (просто увеличишь переполняемый буыер). тем более если ты захочешь статически выделить 1025 байт (char str[1025]) gcc выделит не 1025 байт, а число кратное 32, т.е. в этом случае 1056 байт.
> register char *tmp=str;
А что в этой строке обозначает register? Никогда не встречал.Вообще странно, что такие функции не написаны в стандартных библиотеках как раз для того, чтоб избежать ошибок :(
>> register char *tmp=str;
>А что в этой строке обозначает register? Никогда не встречал.Дает указание компилятору по возможности размещать переменную в регистре.
В принципе совсем не обязательно, так как современные компиляторы часто сами размещают локальные переменные в регистрах при включенной оптимизации. Я это указываю чисто машинально по привычке.>
>Вообще странно, что такие функции не написаны в стандартных библиотеках как раз
>для того, чтоб избежать ошибок :(Для C++ есть много замечательных библиотек, таких как STL или Qt. Писать программы с их помощью не сложнее чем на паскале или перле.