这个程序中的恐惧错误了吗?

我是C的中级学生。我正在尝试制作银行管理程序,但首先我需要制作一个登录程序,所以我创建了以下其中一项。 我最近在C中了解了文件I / O,并且对fread和fwrite知之甚少。 我有一个文件(data.txt)格式如下,如下。

user1 1124

user2 3215

user3 5431

在下面的程序中,我要求用户输入用户名和密码(4位密码)并将文件数据复制到结构中,然后将这两者进行比较以validation信息。

我的程序有什么问题以及如何使fread正常工作。 是在data.txt文件中格式化还是我应该更改它。

提前致谢…

#include #include #include struct user_account { char u_name[30]; int u_pin; } log_in; int login() { int start; int i, n; int t_pin[4]; // TEMPORARY INT PIN for storing pin inputed by user char t_name[30]; // TEMPORARY STRING for storing name inputed by user FILE *fp; fp = fopen("data.txt","rb"); // Opening record file if(fp == NULL) { puts("Unable to open file!"); return 1; } start : { printf("User Name : "); scanf("%s",&t_name); printf("Pin Code : "); for(i = 0; i < 4; i++) { // This loop is for hiding input pin n = getch(); if(isdigit(n)) { t_pin[i] = n; printf("*"); } else { printf("\b"); i--; } } fread(&log_in,sizeof(log_in),1,fp); // Comparing user name and pin with info in the structure copied from the file if(strcmp(log_in.u_name, t_name) == 0 && log_in.u_pin == t_pin) puts("Login successful! Welcome User"); else { printf("\nIncorrect Information!\n"); printf("Press any key to log in again..."); getch(); system("cls"); goto start; } } } int main() { int login(); return 0; } 

问题是你有一个ASCII /文本文件但是你试图使用fread直接读入一个结构; 这需要二进制格式的文件。 fread无法进行格式转换。 请改用fscanf

 fscanf(fp, "%s %d", &log_in.u_name, &log_in.u_pin); 

我看到的问题:

  1. 以下行不正确。

     scanf("%s",&t_name); 

    你需要使用:

     scanf("%29s",t_name); 
  2. 给定文件格式, fread不是正确的解决方案。 当文件是二进制格式时, fread有效。

    根据输入文件的格式,您需要使用:

      scanf("%29s %d", log_in.uname, &log_in.u_pin); 
  3. 使用log_in.u_pin == t_pin比较引脚应该会产生编译器错误。 log_in.u_pin的类型是intlog_in.u_pin的类型是int [4] 。 您将不得不更改从t_pin获取整数值的t_pin

    您可以使用以下内容:

     int pin = 0; for (i = 0; i < 4; ++i ) { pin = 10*pin + t_pin[i]; } 

    但是,要使其正常工作,您必须在t_pin存储正确的整数值。 当您阅读的字符为'1' ,您必须存储1 。 要么是这样,要么你必须将上面的for循环更改为:

      pin = 10*pin + t_pin[i]-'0'; 
  4. 在你的函数中使用goto start循环的方式是不正确的。 您还没有从输入文件中读取所有用户ID和引脚并进行比较。 你拥有它的方式,你将最终做到:

    • 阅读用户名和密码
    • 检查文件中的第一个条目。 如果他们不匹配......

    • 再次读取用户名和引脚。

    • 检查文件中的下一个条目。 如果他们不匹配......

    等等

    你想要:

    • 阅读用户名和密码

    • 检查文件中的第一个条目。 如果他们不匹配......

    • 检查文件中的下一个条目。 如果他们不匹配......
    • 检查文件中的下一个条目。 如果他们不匹配......

    等等

a)fread用于读取固定大小(以字节为单位)的记录。 虽然这是一个选项,但您可能会发现fscanf更适合您的用例。

b)goto有其用途,可以说,但在你的特定情况下,while循环更合适,因为它使意图更清晰,更不容易被误用。

c)您的问题的关键是阅读文件。 您只需读入并检查每个传递文件中的单个记录,一旦读取所有记录,您将获得EOF而不是其他记录。

你有几个选择。 您可以在登录循环之前将整个用户表读入列表。 当用户登录时,您必须遍历列表,直到找到匹配或列表结尾。 或者,您可以在每次尝试查找匹配项的用户尝试时遍历整个文件,并在完成后查找返回文件的开头。 在任何一种情况下,您都必须检查并处理读取错误。

d)最后,当输入非数字时,你可能会发现退格不是你想到的。 您也可以考虑允许用户在输入引脚时按退格键。