29 Нояб., 2021, 13:37

Уметь выносить одиночество и получать от него удовольствие -- великий дар.

Бернард Шоу


Изучаю Си (функция 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 означает конец строки и всегда вносится в массив. При задании размера массива это следует учитывать.
[свернуть]