我是C的中级学生。我正在尝试制作银行管理程序,但首先我需要制作一个登录程序,所以我创建了以下其中一项。我最近在C中了解了文件I / O,并且对fread和fwrite了解不多。我有一个文件(data.txt)格式如下。
user1 1124
user2 3215
user3 5431
在以下程序中,我已要求用户输入用户名和密码(4位密码)并将文件数据复制到结构中,然后将这两者进行比较以验证信息。
我的程序有什么问题,以及如何让fread正常工作。并且可以在data.txt文件中格式化,或者我应该更改它。
提前致谢...
#include<stdio.h>
#include<ctype.h>
#include<string.h>
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;
}
答案 0 :(得分:3)
问题是你有一个ASCII /文本文件但是你试图使用fread
直接读入一个结构;这需要二进制格式的文件。 fread
无法进行格式转换。请改用fscanf
:
fscanf(fp, "%s %d", &log_in.u_name, &log_in.u_pin);
答案 1 :(得分:1)
我看到的问题:
以下行不正确。
scanf("%s",&t_name);
您需要使用:
scanf("%29s",t_name);
fread
不是正确的解决方案。当文件是二进制格式时,fread
可以正常工作。
根据输入文件的格式,您需要使用:
scanf("%29s %d", log_in.uname, &log_in.u_pin);
使用log_in.u_pin == t_pin
比较引脚会产生编译错误。 log_in.u_pin
的类型为int
,而t_pin
的类型为int [4]
。您必须更改从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';
使用goto start
循环函数的方式不正确。您还没有从输入文件中读取所有用户ID和引脚并进行比较。你拥有它的方式,你最终会做:
检查文件中的第一个条目。如果他们不匹配......
再次阅读用户名和密码。
等
你想要:
阅读用户名和密码
检查文件中的第一个条目。如果他们不匹配......
等
答案 2 :(得分:0)
a)fread用于读取固定大小(以字节为单位)的记录。虽然这是一个选项,但您可能会发现fscanf更适合您的用例。
b)goto有其用途,可以说,但在你的特定情况下,while循环更合适,因为它使意图更清晰,不易被误用。c)问题的症结在于阅读文件。您只需读入并检查每个传递文件中的单个记录,一旦读取所有记录,您将获得EOF而不是其他记录。
您有几个选择。您可以在登录循环之前将整个用户表读入列表。当用户登录时,您必须遍历列表,直到找到匹配或列表结尾。或者,您可以在每次尝试查找匹配项的用户尝试时循环遍历整个文件,并在完成后查找返回文件的开头。在任何一种情况下,您都必须检查并处理读取错误。
d)最后,当输入非数字时,你可能会发现退格不是你的想法。您也可以考虑允许用户在输入引脚时按退格键。