Как работает strcmp()?
Я искал справедливый бит для ответа. Я собираюсь сделать ряд собственных строковых функций, таких как my_strcmp()
, my_strcat()
и т.д.
Работает ли strcmp()
каждый индекс из двух массивов символов, и если значение ASCII меньше при идентичном индексе двух строк, эта строка имеет более широкую букву и, следовательно, возвращается 0 или 1 или 2? Я предполагаю, что я спрашиваю, использует ли он значения ASCII символов для возврата этих результатов?
Любая помощь будет принята с благодарностью.
[REVISED]
ОК, поэтому я придумал это... он работает во всех случаях, кроме случаев, когда вторая строка больше первой.
Какие-нибудь советы?
int my_strcmp(char s1[], char s2[])
{
int i = 0;
while ( s1[i] != '\0' )
{
if( s2[i] == '\0' ) { return 1; }
else if( s1[i] < s2[i] ) { return -1; }
else if( s1[i] > s2[i] ) { return 1; }
i++;
}
return 0;
}
int main (int argc, char *argv[])
{
int result = my_strcmp(argv[1], argv[2]);
printf("Value: %d \n", result);
return 0;
}
Ответы
Ответ 1
"реализация" псевдокода strcmp
будет выглядеть примерно так:
define strcmp (s1, s2):
p1 = address of first character of str1
p2 = address of first character of str2
while contents of p1 not equal to null:
if contents of p2 equal to null:
return 1
if contents of p2 greater than contents of p1:
return -1
if contents of p1 greater than contents of p2:
return 1
advance p1
advance p2
if contents of p2 not equal to null:
return -1
return 0
Это в основном это. Каждый символ сравнивается, в свою очередь, принимается решение о том, больше ли первая или вторая строка на основе этого символа.
Только если символы идентичны, вы переходите к следующему символу, и, если все символы идентичны, возвращается ноль.
Обратите внимание, что вы можете не обязательно получать 1 и -1, спецификации говорят, что любое положительное или отрицательное значение будет достаточным, поэтому вы всегда должны проверять возвращаемое значение с помощью < 0
, > 0
или == 0
.
Включение этого в реальное С было бы относительно простым:
int myStrCmp (const char *s1, const char *s2) {
const unsigned char *p1 = (const unsigned char *)s1;
const unsigned char *p2 = (const unsigned char *)s2;
while (*p1 != '\0') {
if (*p2 == '\0') return 1;
if (*p2 > *p1) return -1;
if (*p1 > *p2) return 1;
p1++;
p2++;
}
if (*p2 != '\0') return -1;
return 0;
}
Также имейте в виду, что "больше" в контексте символов необязательно основывается на простом упорядочении ASCII для всех строковых функций.
C имеет понятие "локали", которое задает (помимо прочего) сортировку или упорядочивание базового набора символов, и вы можете, например, найти символы a
, á
, à
и ä
все считаются идентичными. Это произойдет для таких функций, как strcoll
.
Ответ 2
Вот BSD-реализация:
int
strcmp(s1, s2)
register const char *s1, *s2;
{
while (*s1 == *s2++)
if (*s1++ == 0)
return (0);
return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
}
После несоответствия между двумя символами он просто возвращает разницу между этими двумя символами.
Ответ 3
Он использует байтовые значения символов, возвращая отрицательное значение, если первая строка появляется перед вторым (упорядочена по байтовым значениям), ноль, если они равны, и положительное значение, если первое появляется после второго. Поскольку он работает с байтами, он не поддерживает кодирование.
Например:
strcmp("abc", "def") < 0
strcmp("abc", "abcd") < 0 // null character is less than 'd'
strcmp("abc", "ABC") > 0 // 'a' > 'A' in ASCII
strcmp("abc", "abc") == 0
Точнее, как описано в strcmp Open Group спецификации:
Знак ненулевого возвращаемого значения определяется значком разницы между значениями первой пары байтов (оба интерпретируются как тип unsigned char), которые различаются в сравнении строк.
Обратите внимание, что возвращаемое значение может не совпадать с этой разницей, но оно будет иметь один и тот же знак.
Ответ 4
Вот моя версия, написанная для небольших приложений микроконтроллеров, совместимая с MISRA-C.
Основная цель этого кода заключалась в том, чтобы написать читаемый код вместо однострочного goo, найденного в большинстве библиотек компилятора.
int8_t strcmp (const uint8_t* s1, const uint8_t* s2)
{
while ( (*s1 != '\0') && (*s1 == *s2) )
{
s1++;
s2++;
}
return (int8_t)( (int16_t)*s1 - (int16_t)*s2 );
}
Примечание: код предполагает 16-разрядный тип int
.
Ответ 5
Это из самих мастеров (K & R, 2nd ed., стр. 106):
// strcmp: return < 0 if s < t, 0 if s == t, > 0 if s > t
int strcmp(char *s, char *t)
{
int i;
for (i = 0; s[i] == t[i]; i++)
if (s[i] == '\0')
return 0;
return s[i] - t[i];
}
Ответ 6
Этот код эквивалентен, короче и читабельнее:
int8_t strcmp (const uint8_t* s1, const uint8_t* s2)
{
while( (*s1!='\0') && (*s1==*s2) ){
s1++;
s2++;
}
return (int8_t)*s1 - (int8_t)*s2;
}
Нам нужно только проверить конец s1, потому что, если мы дойдем до конца s2 до конца s1, цикл завершится (так как * s2!= * s1).
Возвращаемое выражение вычисляет правильное значение в каждом случае, если мы используем только 7-битные (чистые ASCII) символы. Тщательное мышление необходимо для создания правильного кода для 8-битных символов из-за риска переполнения целых чисел.
Ответ 7
Я нашел это в Интернете.
http://www.opensource.apple.com/source/Libc/Libc-262/ppc/gen/strcmp.c
int strcmp(const char *s1, const char *s2)
{
for ( ; *s1 == *s2; s1++, s2++)
if (*s1 == '\0')
return 0;
return ((*(unsigned char *)s1 < *(unsigned char *)s2) ? -1 : +1);
}
Ответ 8
Вот как я реализовал мой strcmp:
он работает следующим образом:
он сравнивает первую букву двух строк, если она идентична, она продолжает следующую букву. Если нет, он возвращает соответствующее значение. Это очень просто и легко понять: # include
//function declaration:
int strcmp(char string1[], char string2[]);
int main()
{
char string1[]=" The San Antonio spurs";
char string2[]=" will be champins again!";
//calling the function- strcmp
printf("\n number returned by the strcmp function: %d", strcmp(string1, string2));
getch();
return(0);
}
/**This function calculates the dictionary value of the string and compares it to another string.
it returns a number bigger than 0 if the first string is bigger than the second
it returns a number smaller than 0 if the second string is bigger than the first
input: string1, string2
output: value- can be 1, 0 or -1 according to the case*/
int strcmp(char string1[], char string2[])
{
int i=0;
int value=2; //this initialization value could be any number but the numbers that can be returned by the function
while(value==2)
{
if (string1[i]>string2[i])
{
value=1;
}
else if (string1[i]<string2[i])
{
value=-1;
}
else
{
i++;
}
}
return(value);
}
Ответ 9
Это только:
int strcmp(char *str1, char *str2){
while( (*str1 == *str2) && (*str1 != 0) ){
++*str1;
++*str2;
}
return (*str1-*str2);
}
если вы хотите быстрее, вы можете добавить "register" перед типом, например:
зарегистрировать char
то вот так:
int strcmp(register char *str1, register char *str2){
while( (*str1 == *str2) && (*str1 != 0) ){
++*str1;
++*str2;
}
return (*str1-*str2);
}
таким образом, если это возможно, используется регистр ALU.