Язык Си - руководство для начинающих.

Функция strcmp( ).

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

/* Будет ли это работать? */

#include <stdio.h>

#define ANSWER  " Грант".

Main( ).

{

Char try [40];

Puts(" Кто похоронен в могиле Гранта?" );

Gets(try);

While(try != ANSWER).

Puts(" Нет, неверно. Попытайтесь еще раз." );

Gets(try);

} puts(" Правильно.");

}

     Хотя эта программа и смотрится неплохо, она не будет работать правильно, try и ANSWER на самом деле являются указателями, поэтому сравнение (try != ANSWER) спрашивает не о том, одинаковы ли эти две строки, а одинаковы ли два адреса, на которые ссылаются try и ANSWER. Так как ANSWER и try запоминаются в разных ячейках, эти два указателя никогда не могут быть одним и тем же, и пользователю всегда сообщается, что программа неверна. Такие программы обескураживают людей.

     Нам нужна функция, которая сравнивает содержимое строк, а не их адреса. Можно было бы придумать ее, но это уже сделала за нас функция strcmp( ) (string comparision).

Теперь исправим нашу программу:

/* это будет работать */

#inсludе <stdio.h>

#define ANSWER " Грант".

Main( ).

{

Char try [40];

Puts(" Кто похоронен в могиле Гранта?" );

Gets(try);

While(strcmp(try, ANSWER) != 0).

{ puts(" Нет, неверно. Попытайтесь еще раз.");

Gets(try);

} puts(" Правильно!");

}

     Так как ненулевые значения интерпретируются всегда как "true", мы можем сократить оператор while do while(strcmp(try, ANSWER)).

     Из этого примера можно сделать вывод, что strcmp( ) использует два указателя строк в качестве аргументов и возвращает значение 0, если эти две строки одинаковы. Прекрасно, если вы придете к такому выводу.

     Хорошо, что Strcmp( ) сравнивает строки, а не массивы. Поэтому, хотя массив try занимает 40 ячеек памяти, а " Грант" - только 6 (не забывайте, что одна нужна для нуль-символа), сравнение выполняется только с частью try, до его первого нуль-символа. Такую функцию strcmp( ) можно использовать для сравнения строк, находящихся в массивах разной длины.

     А что если пользователь ответил " ГРАНТ" или " грант" или "Улиссес С. Грант" ? Хорошо, если пользователю сказали, что он ошибся? Чтобы сделать программу гибкой, вы должны предусмотреть несколько допустимых правильных ответов. Здесь есть некоторые тонкости. Вы могли бы в операторе #define определить в качестве ответа " ГРАНТ" и написать функцию, которая превращает любой ответ только в это слово. Это устраняет проблему накопления, но остаются другие поводы для беспокойства.

     Между прочим, какое значение возвращает strcmp( ), если строки не одинаковы? Вот пример:

/* возвраты функции strcmp */

#include <a: stdio.h>

Main( ).

{

Printf(" %d \n" , strcmp( "A" , " A" ));

Printf(" %d \n" , strcmp( "A" , " B" ));

Printf(" %d \n" , strcmp( "B" , " A" ));

Printf(" %d \n" , strcmp( "C" , "A" ));

Printf(" %d \n" , strcmp(" apples", " apple"));

}

В результате получаем.

0 -1.

1.

2 115.

Как мы и предполагали, сравнение "А" с самим собой возвращает 0. Сравнение "А" с "В" дает -1, а "В" с "А" дает 1. Это наводит на мысль, что strcmp( ) возвращает отрицательное число, если первая строка предшествует второй в алфавитном порядке, или положительное число, если порядок иной. Кроме того, сравнение "С" с "А" дает 2 вместо 1. Картина проясняется: функция возвращает разницу между двумя символами в коде ASCII. В более общем смысле strcmp() передвигается вдоль строк до тех пор, пока не находит первую пару не совпадающих символов; затем она возвращает разницу в кодах ASCII. Например, в самом последнем примере "apples" и "apple" совпадают, кроме последнего символа 's', в первой строке. Он сопоставляется с шестым символом в "apple", который является нуль-символом (0 в ASCII).

Возвращается значение.

's' - '\0' = 115 - 0 = 115,

Где 115 является кодом буквы 's' в ASCII.

Обычно вам не нужно точно знать возвращаемое значение. Чаще всего вы только хотите знать, нуль это или нет, т. е. было ли совпадение. Или, может быть, вы пытаетесь отсортировать строки в алфавитном порядке и хотите узнать, в каком случае сравнение дает положительный, отрицательный или нулевой результат.

Можно использовать эту функцию, чтобы проверить, остановится ли программа, читая вводимую информацию:

/* Начало какой-то программы */

#include &stdio.h&

#define SIZE 81.

#define LIM 100.

#define STOP   "  "  /* нулевая строка */

Main( ).

{

Static char input[LIM][SIZE];

Int ct = 0;

While(gets(input[ct]) != NUL  && strcmp(input[ct].STOP) !=0.

                                && ct++ < LIM).

...

}

     Программа прекращает чтение вводимой строки, если встречает символ EOF [в этом случае gets( ) возвращает NULL], или если вы нажимаете клавишу [ввод] в начале строки (т.e. введете пустую строку), или если вы достигли предела LIM. Чтение пустой строки дает пользователю простой способ прекращения ввода.

Давайте перейдем к последней из обсуждаемых нами функций, работающих со строками.