в функции: 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), проверяя