Система входа в систему с использованием текстового файла в C - PullRequest
0 голосов
/ 15 мая 2019

Итак, мое задание - создать систему входа в систему.Имя пользователя и пароли будут проверяться с содержимым в файле «account.txt».Содержимое этого файла имеет следующую структуру:

Идентификатор учетной записи: 1Имя: Джон ЛиПропуск: 7 мкФРоль: студентИдентификатор аккаунта: 2Имя: Парк ЛиПроход: 42чРоль: Лектор

Вот что я получил до сих пор:

struct Account {
    char name[20];
    char pass[20];
};

void Login (char name[], char pass[]){

    FILE *sc;
    struct Account acc;

    sc = fopen("Account.txt","r");

    fscanf(sc,"\nName: %s",acc.name);
    fscanf(sc,"\nPass: %s",acc.pass);



    if(strcmp(name,acc.name) == 0 && strcmp(pass,acc.pass)) {
        printf("Login successful");
    }
    else {
        printf("Name or Pass incorrect");
    }

    fclose(sc);
}


 int main () {

    struct Account log[20];

        fflush(stdin);
        printf("\n\t\tEnter your name: ");
        gets(log[20].name);

        printf("\t\tEnter your password: ");
        gets(log[20].pass);

        Login(log[20].name,log[20].pass);   
    }

    return 0; }

Что вы, ребята, думаете, я должен сделать?

1 Ответ

0 голосов
/ 15 мая 2019

в функции: login() код должен проверять каждую запись в файле перед объявлением ошибки. В конце концов, первая запись может не относиться к человеку, пытающемуся войти

относительно:

sc = fopen("Account.txt","r"); 
fscanf(sc,"\nName: %s",acc.name); 

1) всегда проверять (! = NULL) возвращаемое значение из fopen(), чтобы убедиться, что операция прошла успешно.

2) нужно передвигаться за первую строку каждой записи во входном файле, прежде чем пытаться прочитать имя

3) при использовании спецификаторов формата ввода "% s" и / или "% [...]" всегда включайте модификатор MAX CHARACTERS, который на 1 меньше длины входного буфера, потому что эти спецификаторы всегда добавляют NUL байт на вход. Это позволяет избежать переполнения буфера и результирующего неопределенного поведения.

т.е.

if( !sc ) 
{ 
    perror( "fopen failed" ); 
    exit( EXIT_FAILURE ); 
} 

{input first line of acct and discard} 

if( fscanf(sc,"\nName: %19s",acc.name) != 1 ) 
{ 
    // handle error 
} 

Однако, если эти строки во входном файле содержат эти метки, например Name:, тогда код должен также вводить и отбрасывать эти метки, как в приведенном выше примере.

Кажется, это домашнее задание, поэтому я очень не хочу просто «дать» вам соответствующий код. Я ожидаю, что ваш инструктор или ТА смогут помочь вам с подробностями того, что код должен делать.

относительно утверждений типа:

gets(log[20].name);

1) gets() больше не является частью языка C, ваш компилятор должен был сказать вам это.

2) допустимый индекс в массиве имеет диапазон: 0 ... (количество записей в массиве -1). Таким образом, индекс 20 находится за пределами диапазона. Предложите просто использовать указатель на массив.

3) Предложите использовать `fgets () для ввода каждой строки из файла.

4) объявленная вами структура не будет хорошо работать с фактическими данными из входного файла.

Предложить использование:

#define MAX_LOG_ENTRIES 20

int main( void )
{
    struct Account acc[ MAX_LOG_ENTRIES ] = { "","" };
    char dummy[128];
    size_t i;
    for( i = 0; i<MAX_LOG_ENTRIES; i++ )
    {
        if( i< MAX_LOG_ENTRIES && fgets( dummy, sizeof( dummy ), sc ) )
        {  // then successfully read 'account' line
            if( fgets( dummy, sizeof( dummy ), sc ) )
            {  // then successfully read 'Name:` line
                // remove trailing newline
                dummy[ strcspn( dummy, "\n" )] = '\0';
                // skip past Name: ' label
                char * namePtr = strchr( dummy, ':' );
                if( namePtr )
                { // then found the ':'
                     // step by ': '
                     namePtr += 2;
                }
                // extract name
                strcpy( log[i].name, namePtr );

            if( fgets( dummy, sizeof( dummy ), sc ) )
            {  // then successfully read 'Pswd:` line
                // remove trailing newline
                dummy[ strcspn( dummy, "\n" )] = '\0';
                // skip past Pswd: ' label
                char * pswdPtr = strchr( dummy, ':' );
                if( pswdPtr )
                { // then found the ':'
                     // step by ': '
                     pswdPtr += 2;
                }
                // extract password
                strcpy( log[i].pswd, pswdPtr );

                // read/discard unused data line
                fgets( dummy, sizeof( dummy ), sc );
                // read/discard unused blank line
                fgets( dummy, sizeof( dummy ), sc );          
         }

Когда вышеприведенный цикл for() выходит, все записи считываются в массив с именем log[], а переменная 'i' содержит количество записей в массиве 'log []', которые фактически используются

теперь код должен ввести два поля от пользователя (name и pswd)

Затем переберите массив log[], чтобы увидеть, есть ли совпадение name + pswd.

если fgets (dummy, sizeof (dummy), sc); совпадение найдено, то успех, в противном случае пользователь не смог ввести действительные данные.

Примечание. Приведенный выше код не может проверить наличие ошибок и подобных проблем, в том числе если входной файл содержит менее 20 записей. Вы должны быть в состоянии добавить ошибку (и EOF), проверяя

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...