Я пытаюсь создать систему входа в систему на языке C, которая скрывает пароль с помощью '*' при вводе и возвращается назад, когда пользователь вводит неверную информацию

Однако с моим кодом есть две проблемы:

  1. Backspace считается вводом.
  2. Когда он возвращается после первой неудачной попытки, он показывает «Неверное имя пользователя или пароль!» хотя данные для входа верны.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <ctype.h>


...

do{
        system("cls");
        printf("\nEnter username: ");
        gets(username);
        printf("\nEnter password: ");
    
        do{
            password[i] = getch();
            if (password[i] != '\r')
            printf("*");
            i++;
        }while(password[i-1] != '\r');
        password[i-1] = '\0';
        
        if (strcmp(username, "dlsuuser1") == 0 & strcmp(password, "dlsuuser") == 0)
            indicator = 0;

        else if (strcmp(username, "dlsuuser2") == 0 && strcmp(password, "dlsuusers") == 0)
            indicator = 0;
        
        else{
            printf("\nInvalid username or password!");
            memset(password, '\0', sizeof(password));
            memset(username, '\0', sizeof(username));
            getch();
            i=0;
            indicator = 1;
            }
    }while(indicator != 0);

    printf("\nLogged in successfully!");

Я пытался следить за источниками в Интернете, но, похоже, не смог этого получить. Я тоже новичок в C. Также у меня есть теория по поводу второй проблемы; где программа продолжает создавать массив для имени пользователя и пароля (например, добавляется сам к себе, как работает strcat). Спасибо тем, кто ответит!

Кроме того, если кто-нибудь покажет мне, как сократить и сделать код более эффективным, я буду очень признателен! (Примечание. Это действие, в котором нам разрешено выполнять только базовый ввод-вывод, лестничный if-else, операторы переключения, функции, за исключением функций, передаваемых по ссылке, любые операторы цикла, массивы и строки. В этом случае возможности могут быть ограничены. Прошу прощения.)

Я пробовал memset, strcpy (пароль, "") и пароль[0]=\0, но ничего не помогло.

1) не вводите getch() непосредственно в массив password. Сохраните введенные данные во временной переменной, проверьте эту временную переменную на наличие '\r' и возврата (и других проблемных входных данных), прежде чем решить, что делать дальше.

pmg 18.07.2024 12:43

Кроме того: gets() устарел и больше не является частью стандартной библиотеки C. Пожалуйста, прочитайте Почему функция Gets настолько опасна, что ее нельзя использовать?

Weather Vane 18.07.2024 12:53

Не сбрасывайте i после использования. Сделайте это прямо перед этим. То же самое и с indicator.

Weather Vane 18.07.2024 12:56

Кроме того, ваш первый вызов strcmp() использует побитовое И (&) вместо логического И (&&). Нет предупреждений компилятора?

Paul Lynch 18.07.2024 13:37

Публикуйте программу, а не фрагмент.

Allan Wind 18.07.2024 15:49

Вам следует пометить эти окна, поскольку вы используете специальные заголовки Windows и внешние команды.

Allan Wind 18.07.2024 15:51
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
6
66
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий
  1. Чтобы исключить backspace, вы можете попробовать:
        for(int i = 0;;) {
            password[i] = getch();
            if (strchr(password[i], "\b\n\r")) {
                 if (password[i] == '\r')
                     break;
                 continue;
            }
            i++;
       }
  1. Опечатка: использование двоичного и & вместо логического и &&. Поскольку у вас одно и то же действие, можно объединить два теста:
        if (
            (!strcmp(username, "dlsuuser1") && !strcmp(password, "dlsuuser")) ||
            (!strcmp(username, "dlsuuser2") && !strcmp(password, "dlsuusers"))
        )

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

Другие вопросы по теме