#c #pointers #character #strcmp #c-strings
#c #указатели #символ #strcmp #c-строки
Вопрос:
Я работаю над небольшим проектом, к которому у меня нет доступа ни к одной стандартной библиотеке C. ( создание микроядра в структуре ARM с нуля. Даже printf должен был быть реализован)
В этих обстоятельствах я реализовал strcmp, используя машинную методологию Даффа.
ниже приведен весь код.
int
strcmp ( const char *str1, const char *str2 )
{
while ( *str1 || *str2 )
if ( *(str1 ) != *(str2 ) ) return *str1 - *str2;
return 0;
}
Это имело смысл; и какое-то время это, казалось, работало на тестовых примерах, пока не произошел сбой конечной системы. Я проследил, и он пришел к этому strcmp.
Сначала я подумал, что сначала он увеличил str1, а затем сравнил с str2 ПЕРЕД увеличением str2. 1. Оказалось, что этого не было, но не мог бы кто-нибудь, пожалуйста, проверить, что это может произойти в некоторых случаях?
Затем я понял, что проблема была в *str1 — *str2, поэтому изменил его на return 1 . т. Е. результирующий код выглядит следующим образом:
while ( *str1 || *str2 )
if ( *(str1 ) != *(str2 ) ) return 1;
return 0;
хотя все, что я хотел, это проверка «равно», поэтому изменение на «1» не вызвало проблем, но я все еще удивляюсь, почему исходный код не удался. 2. Может ли кто-нибудь дать свет или предложение относительно того, как это могло привести к сбою?Я бы предпочел, чтобы strcmp следовал стандартному интерфейсу C, чтобы он возвращал ненулевое значение, которое больше рассказывает о str1 и str2.
тестовые примеры были:
code_t // a function pointer type
program_find ( char *program )
{
if (strcmp( program, "exit" ) == 0) return ....
else if (strcmp( program, "k1" ) == 0) return ....
else if (strcmp( program, "k3" ) == 0) return ....
else if (strcmp( program, "perf" ) == 0) return ....
else if (strcmp( program, "test_libc" ) == 0) return ....
}
когда * program была «k3», она возвращала «k1», а «test_libc» возвращал «perf».
Исходная проблема была решена путем присвоения ей «return 1», поэтому этот вопрос касается исключительно интересов C. Также приветствуется предложение или ссылка на документацию strcmp. Я видел интерфейс спецификации для IEEE
Комментарии:
1. Что происходит, когда строки имеют неодинаковую длину?
2. все строки имеют нулевое завершение по предположению, поэтому оно будет проверено, потому что вы сравниваете с нулевым символом в конце.
3. проверьте pdclib.rootdirectory.de , (неполная) реализация стандартной библиотеки C99 с нуля; реализации функций из
string.h
можно найти здесь: pdclib.rootdirectory.de/trac.fcgi/browser/trunk/functions /…
Ответ №1:
При выполнении сравнения вы используете приращение post для str1 и str2. Это приводит к их увеличению перед выполнением вычитания, поэтому вы вычитаете неправильные два символа.
Лучшей реализацией было бы
int
strcmp ( const char *str1, const char *str2 )
{
while ( *str1 || *str2 ) {
if ( *str1 != *str2 ) return *str1 - *str2;
str1;
str2;
}
return 0;
}
Ответ №2:
У вас две проблемы:
- Вы увеличиваете указатели перед выполнением вычитания для возвращаемого значения, поэтому возвращаемое значение неверно;
- Стандарт, специфичный для
strcmp()
, указывает, что элементы строк сравниваются какunsigned char
.
Устранение этих проблем:
int
strcmp ( const char *str1, const char *str2 )
{
const unsigned char *s1 = (const unsigned char *)str1;
const unsigned char *s2 = (const unsigned char *)str2;
while (*s1 amp;amp; *s1 == *s2) {
s1 ;
s2 ;
}
return *s1 - *s2;
}
Комментарии:
1. вам нужно только проверить либо
*s1
или*s2
на ноль, потому что в другом случае проверка равенства не пройдет; см. pdclib.rootdirectory.de/trac.fcgi/browser/trunk/functions /… для эталонной реализации DevSolar
Ответ №3:
Вычисление выражения:
*(str1 ) != *(str2 )
Разыменует указатели str1
и str2
, сравнив результаты, затем увеличит оба указателя. К тому моменту, что strcmp
возвращает, они теперь указывают на что-то отличное от того, что вы сравнивали.
Имейте в виду, что реализация strcmp
всегда возвращать 1 или 0 сделает его бесполезным для сортировки списка строк! Вам нужно вернуть -1/0/ 1 чтобы сделать его пригодным для этого.
Комментарии:
1. а, понятно. вот почему *(str1 ) != *( str2) попытка в конце концов не удалась.
Ответ №4:
int strcmp(const char* a, const char* b){
for(;; a, b){
if(*a == '' || *b == '')
return (*a == *b)? 0 : *a != '' ? 1 : -1;
if(*a != *b) return (unsigned char)(*a) > (unsigned char)(*b) ? 1 : -1;
}
}