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

时间:2014-06-05 19:26:48

标签: c file-io compiler-errors fread

我是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;
    }

3 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:1)

我看到的问题:

  1. 以下行不正确。

    scanf("%s",&t_name);
    

    您需要使用:

    scanf("%29s",t_name);
    
  2. 鉴于文件格式,
  3. fread不是正确的解决方案。当文件是二进制格式时,fread可以正常工作。

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

     scanf("%29s %d", log_in.uname, &log_in.u_pin); 
    
  4. 使用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';
    
  5. 使用goto start循环函数的方式不正确。您还没有从输入文件中读取所有用户ID和引脚并进行比较。你拥有它的方式,你最终会做:

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

    • 再次阅读用户名和密码。

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

    你想要:

    • 阅读用户名和密码

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

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

答案 2 :(得分:0)

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

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

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

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

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