Один человек имеет право смотреть на другого свысока только тогда, когда он помогает ему подняться.
Габриэль Гарсиа Маркес

Меню навигации для мобильных

Изучаю Си (функция strcmp)

Автор Nikopol, 11 Авг., 2020, 18:07

« предыдущая - следующая »

Nikopol

Функция strcmp предназначена для сравнения строковых массивов
Вот пример имеем код:
Код:  простая проверка пароля
#include <stdio.h>
#include <string.h>
int main()
{
    char password[] = "pass";
        char ps[20];
        do
        {
            fprintf(stdout, "Enter password here ");
            fscanf(stdin, "%s", ps);
        }
        while(strcmp(password, ps) != 0);
            printf("Password is OK.\n");
        return 0;
}
он работает и при вводе правильного пароля "pass" вывод в консоль:
Password is OK.
При неправильном бесконечно просит ввести пароль.

Но я подумал, что использование fscanf при вводе пароля не правильно т.к. может привести к переполнению буфера и краху программы.

Вот:
Enter password here klfjl;sjtfdaskfhakas;jlkl;s;jgkldfjkgjklhgjkqjklj
Enter password here pass
Password is OK.
*** stack smashing detected ***: <unknown> terminated
Аварийный останов (стек памяти сброшен на диск)
Сначала был введён неправильный пароль превышающий длину массива, а после правильный, но массив уже был расширен и при чтении сработала защита от переполнения буфера.
[свернуть]

Поэтому я взял функцию fgets которая проверяет размер массива. и код стал такой:
#include <stdio.h>
#include <string.h>
int main()
{
    char password[] = "pass";
        char ps[20];
        do
        {
            fprintf(stdout, "Enter password here ");
            fgets(ps, 20, stdin);
        }
        while(strcmp(password, ps) != 0);
            printf("Password is OK.\n");
        return 0;
}

Но почему то он перестал принимать пароль хотя если после ввода пароля вставить:
fprintf (stdout, "%s", ps);
то вывод показывает, что пароль записан в массив правильно:
Enter password here pass
pass
Enter password here 

Подскажите, что не так?


Shaman

Просто функция  "fgets" для записи в массив ожидает  символ переноса строки '\n' и записывает его в массив в месте с ранее введёнными символами, при условии, что введённая информация помещается в длину массива. В противном случае записывается максимально возможное количество символов.
Вот и получается, что в массив с предзаписанным паролем содержит 'pass', а с вводимым 'pass\n' и естественно они никогда не совпадут.
И это видно если внимательно проанализировать вывод и листинг программы:

В выводе мы видим, что после слова 'pass' происходит перенос строки
Enter password here pass
pass
Enter password here 
В противном случае вывод бы выглядел так:
Enter password here pass
passEnter password here 

А в коде перенос строки отсутствует
fprintf (stdout, "%s", ps);

Дополнение
Если уж быть совсем точным то на самом деле данные в массивах выглядят так:
'pass\0' и   'pass\n\0' соответственно. Символ \0 означает конец строки и всегда вносится в массив. При задании размера массива это следует учитывать.
[свернуть]