【问题标题】:After I print from the struct using a file it doesn't work [closed]在我使用文件从结构打印后,它不起作用[关闭]
【发布时间】:2020-11-08 08:09:14
【问题描述】:

a- 从“detyra_day.dat”文件中读取并打印数据

b- 当您知道 IDNR 是唯一的时添加另一个公民

c- 在不更改 IDNR 的情况下更改公民的信息

d- 为每个家庭每天仅 1 人创建“外出许可”申请 (申请人可以申请其他家庭成员,申请人必须年满18周岁) 8:00至17:00发放“外出许可”,持续2小时。

e- 检查公民是否有权外出(打印 IDNR、日期和时间)。

f- 保存

g- 为所有公民和家庭打印所有“外出许可”。

h- 打印请求许可最多的 10 个公民和请求最少的 10 个公民的列表(不包括根本没有请求的公民)

#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <dos.h> 
#include <windows.h>
int permission;
int hour;
int minute;
int nr_people;

struct citizen{
    char idnr[10];
    char name[50];
    char lname[50];
    long int birthday;
    int id_family;
};


struct birthday{
    int year;
    int month;
    int day;
};


char fname[]={"detyra_day.dat"};



void readPeopleInfo(){
nr_people=0;
struct citizen s;
FILE *f;
f=fopen(fname,"r");
printf("\n========================================================\n\n");
printf("\t\t Details of all citizen \n\n");
printf("========================================================\n\n");

printf("IDNR\tname\tlname\tbirthday\tid_family\n\n");


if(f == NULL)
    {
        printf("Error opening file\n");
        exit(1);
    }
    while(fread(&s,sizeof(struct citizen),1,f))
    {
        printf("%s\t",s.idnr);
        printf("%s\t",s.name);
        printf("%s\t",s.lname);
        printf("%ld\t",s.birthday);
        printf("%d\t\n\n",s.id_family);
        nr_people++;
    }

fclose(f);
printf("========================================================\n\n");
printf("Number of citizen = %d",nr_people);
}




void add(){
struct citizen s,s1;
int nr_people=5;
int found=0;

printf("\n Give the unique IDNR: ");
scanf("%s",&s1.idnr);
for(int i=0;i<nr_people;i++){
    if(s1.idnr==s.idnr){
        printf("The citizen with this IDNR exist");
        found=1;
        return;
    }
}
if(found==0){
    printf("The citizen with this IDNR doesn't 'exist");
    strcpy(s.idnr,s1.idnr);
  printf("\nGive the name of the citizen: ");   
  scanf("%s",s.name);
  printf("\n Give the lname of the citizen: "); 
  scanf("%s",s.lname);
  printf("\n Give the birthday of the citizen in the format YYYYMMDD: ");
  scanf("%ld",&s.birthday); 
  printf("\n Give the ID of the family of the citizen: ");
  scanf("%d",&s.id_family);
  nr_people++;
}
}




void change(){
    struct citizen s[50];
  char *idnr;
  printf("\n IDNR of citizen: ");
  scanf("%s",&idnr);
  for(int i=0;i<nr_people; i++){
    if (strcmp(s[i].idnr,idnr)==0){
    printf("\nGive the name of the citizen: ");   
    scanf("%s",s[i].name);
    printf("\n Give the lname of the citizen: "); 
    scanf("%s",s[i].lname); 
    printf("\n Give the birthday of the citizen in the format YYYYMMDD: ");
    scanf("%ld",&s[i].birthday);
    printf("\n Give the ID of the family of the citizen: ");
    scanf("%d",&s[i].id_family);             
    printf("\n Changed succesfully.");
    return; }
    printf("\n The change didn't happened.");
   }    
}




void permit(){
    int permission;
    struct birthday bday;
    struct citizen s[50];
    int age[nr_people];
    SYSTEMTIME d;
    GetLocalTime(&d);
    for(int i=0;i<nr_people;i++){
        if(bday.month>d.wMonth||(bday.month==d.wMonth&&bday.day>=d.wDay)){
        age[i]=d.wYear-bday.year;
    }
    else{
        age[i]=d.wYear-bday.year-1;
    }
    }
    char *name;
    char *lname;
    char *chosenperson;
    int id_family;
    int i;
    int apply=0;
    int familymembers=0;
    printf("Put your name: ");
    scanf("%s",&name);
    printf("Put your lname: ");
    scanf("%s",&lname);
    for (i=0;i<nr_people;i++){
    if((strstr(name,s[i].name)==0&&strstr(lname,s[i].lname)==0&&age[i]>=18)){
        printf("Your name is on the list and you are in the age to apply");
        id_family=s[i].id_family;
        apply=1;
    }
}
    if(apply==0){
        printf("Your name is not on the list or you are not in the age to apply");
        return;
    }
    struct citizen tmp;
    for(i=0;i<nr_people;i++){
        if(id_family==s[i].id_family){
            tmp=s[50];
            familymembers++;
        }
    }
    for(i=0;i<familymembers;i++){
        printf("%d. name: %10s",i+1,tmp.name);
    }
    apply=0;
    printf("Give the name of the person from your family that you want to apply: ");
    scanf("%s",chosenperson);
    printf("\nYou chose: ");
    for(i=0;i<familymembers;i++){
    if(strstr(chosenperson,tmp.name)==0){
        printf("%s",tmp.name);
        apply=1;
    }
}
    if(apply==0){
        printf("\nThe selected name is not on the list");
        return;
    }
    printf("\nChose a time between 8:00 and 17:00: ");
    float timez;
    int hour;
    int minute;
    scanf("%f",&timez);
    if(timez>=8.00&&timez<=17.00){
        hour=timez;
        minute=(timez-hour)*100;
        if(minute>59){
            printf("Minutes are placed wrong");
            return;
        }
        printf("\nYour application to go out from %f to %f is accepted!",timez,timez+2);
        permission=1;
    }
    else{
        printf("You have chosen the wrong time");
        return;
    }
}




void control(){
    permit();
    struct citizen s[50];
    SYSTEMTIME d;
    GetLocalTime(&d);
    int g=permission;
    for(int i=0;i<nr_people;i++){
        if(g==1){
            printf("\n The citizen with IDNR: %s   Date: %d/%d/%d  Time: %d.%d has applied to go outside",s[nr_people].idnr,d.wYear,d.wMonth,d.wDay,hour,minute);
        }
    }
}




void save(){
    struct citizen s[50];
 FILE *f;
 f=fopen("detyra_day.dat","w");
 if (f==NULL){
   printf("\n Error on the file");
   return;
   } 
 for(int i=0;i<nr_people; i++){
  fwrite(&s[i],sizeof(struct citizen),1,f);
  }
}




int main(){
  char selection;
  do{   
  printf("\n=============================");
  printf("\n 1 - Read and print the data from the file detyra_day.dat");
  printf("\n 2 - Add a citizen");
  printf("\n 3 - Change a citizen");
  printf("\n 4 - Create a Permit to go outside");
  printf("\n 5 - Control the permission");
  printf("\n 6 - Save");
  printf("\n 7 - Print all Permissions to go outside for all citizens and families");
  printf("\n 8 - Print the list of 10 citizens that asked for the permission the most and 10 that asked the least (exclude the ones that didn't asked at all)");
  printf("\n 9 - Exit");
  printf("\n-----------------------------");
  printf("\n Zgjedhja : ");
selection=getch();
switch(selection){
case '1':
   readPeopleInfo();
   break;
case '2':
   add();
   break;
case '3':
    change();
    break;
case '4':
    permit();
    break;
case '5':
    control();
    break;
case '6':
    save();
    break;
case '9':
    exit(0);
}
getch();
} while(selection!='9');
return 0;
}

在我按下 Run 并尝试读取并打印数字 1 后,它会将每个人打印为 1,而不是像结构所说的那样。例如我想这样打印:

IDNR: H65328040Q
Name: Azbie
Lname: Gockaj
Birthday (YYYYMMDD format):19760328
ID_Family: 1

相反,我得到:

INDR: Name: Lname: Birthday: ID_Family:

然后每个人都订购了

This is the detyra_day.dat file

H65328040Q Azbie Gockaj 19760328 1

J70507042S Ledion Celaj 19970507 1

G70312202S Pellumb Osmani 19670312 2

H45827189P Albina Osmani 19740827 2

【问题讨论】:

  • 欢迎来到 Stack Overflow。请阅读the help pages,接受SO tour,阅读How to Ask,以及this question checklist。还请学习如何创建minimal reproducible example,重点放在minimal 部分。最后请学习如何使用调试器。
  • 请将data.dat 作为 text 发布在此处的代码块中 [vs.链接到图像]。这样,响应者可以下载您的程序数据文件,并在他们选择时运行它。否则,任何希望这样做的人都必须手动输入数据[这是他们不太可能想要做的事情]。
  • 它在哪个部分崩溃了,开始调试它并找到它崩溃的行...不要从发布整个作业开始,期望 stackOverflow 为您调试它以获得调试器...
  • 错误是你的数据文件是文本,但是你的代码在做二进制I/O。
  • OT:为了便于阅读和理解:请始终缩进代码。在每个左大括号“{”之后缩进,在每个右大括号“}”之前取消缩进。建议每个缩进级别为 4 个空格。

标签: c file struct printf


【解决方案1】:

有很多错误。

首先,您需要一个由struct citizen 组成的全局 数组,而不是在每个函数中都有一个作用域为struct citizen 的函数。

struct citizen 中,idNr 太小而无法包含 10 位 ID 号。它必须 [至少] 多一个才能说明字符串末尾的 EOS 字符。

使用freadfwrite 访问数据文件。它们适用于 binary 文件,但您有一个 text 文件。您需要分别使用fscanffprintf

使用(例如)[函数范围]char *name;。这是一个指向char [array/string] 的指针,它是未初始化的。将此更改为char name[100];

使用strstr 代替strcmp

scanffscanf 的使用不一致。如果您使用 -Wall -Wextra 编译以启用警告 [gcc],它们就会变得明显。

在同一个流中混用 getch [fgetc] 和 scanf 是不好的做法。

为了保持一致性,我添加了一个prompt 函数而不是各种printf(...); scanf(...); 序列来提示用户。

您并没有真正在代码中使用您的struct birthday


这是清理后的代码。一些基础知识已经过测试,但仍有一些我无法解决的问题。在大多数地方,我使用#if 0 来表示您的旧代码 [vs.我的新代码]

#include <stdio.h>
#include <string.h>
#ifndef __linux__
#include <conio.h>
#include <dos.h>
#endif
#include <windows.h>

#ifdef __linux__
#include <time.h>

int
getch(void)
{
    char buf[1000];
    int chr;

    if (fgets(buf,sizeof(buf),stdin) != 0)
        chr = buf[0];
    else
        chr = -1;

    return chr;
}

WINBASEAPI VOID WINAPI
GetLocalTime(LPSYSTEMTIME lps)
{
    time_t tod;
    struct tm *tm;

    tod = time(NULL);
    tm = localtime(&tod);

    lps->wYear = tm->tm_year + 1900;
    lps->wMonth = tm->tm_mon + 1;
    lps->wDayOfWeek = tm->tm_wday;
    lps->wDay = tm->tm_mday;
    lps->wHour = tm->tm_hour;
    lps->wMinute = tm->tm_min;
    lps->wSecond = tm->tm_sec;
    lps->wMilliseconds = 0;
}
#endif

int permission;
int hour;
int minute;
int nr_people;

struct birthday {
    int year;
    int month;
    int day;
};

struct citizen {
#if 0
    char idnr[10];
#else
    char idnr[10 + 1];
#endif
    char name[50];
    char lname[50];
    struct birthday birthday;
    int id_family;
};

#define CITMAX      50
struct citizen citlist[CITMAX];

char fname[] = { "detyra_day.dat" };

void
prompt(const char *str,char *buf)
{

    printf("%s: ",str);
    fflush(stdout);

    fgets(buf,100,stdin);
    char *cp = strchr(buf,'\n');
    if (cp != NULL)
        *cp = 0;
}

void
getbday(const char *buf,struct birthday *bday)
{
    sscanf(buf,"%4d%2d%2d",&bday->year,&bday->month,&bday->day);
}

void
loadPeopleInfo()
{
    struct citizen *s;
    char birthday[100];
    FILE *f;

    nr_people = 0;

    f = fopen(fname, "r");
    if (f == NULL) {
        printf("Error opening file\n");
        exit(1);
    }

    while (1) {
        s = &citlist[nr_people];

        if (fscanf(f," %s %s %s %s %d\n",
            s->idnr,s->name,s->lname,birthday,&s->id_family) != 5)
            break;

        getbday(birthday,&s->birthday);

        nr_people++;
        if (nr_people >= CITMAX)
            break;
    }

    fclose(f);
}

void
printPeopleInfo()
{
    struct citizen *s;

    printf("\n========================================================\n\n");
    printf("\t\t Details of all citizen \n\n");
    printf("========================================================\n\n");

    printf("IDNR\t\tname\tlname\tbirthday\tid_family\n\n");

    for (int i = 0;  i < nr_people;  ++i) {
        s = &citlist[i];

        printf("%s\t", s->idnr);
        printf("%s\t", s->name);
        printf("%s\t", s->lname);

        struct birthday *bday = &s->birthday;
        printf("%4.4d%2.2d%2.2d\t",bday->year,bday->month,bday->day);

        printf("%d\t\n", s->id_family);
    }
    printf("========================================================\n\n");
    printf("Number of citizen = %d\n", nr_people);
}

void
add()
{
#if 0
    struct citizen s, s1;
#else
    struct citizen *s;
    struct citizen s1;
#endif
#if 0
    int nr_people = 5;
#endif
    int found = 0;
    char buf[100];

#if 0
    printf("\n Give the unique IDNR: ");
    scanf("%s\n", &s1.idnr);
#else
    prompt("Give the unique IDNR",s1.idnr);
#endif

    for (int i = 0; i < nr_people; i++) {
        s = &citlist[i];

#if 0
        if (s1.idnr == s->idnr) {
#else
        if (strcmp(s1.idnr,s->idnr) == 0) {
            printf("The citizen with this IDNR exist\n");
            found = 1;
            return;
        }
#endif
    }

    if (found == 0) {
        s = &citlist[nr_people];

        printf("The citizen with this IDNR doesn't 'exist\n");
        strcpy(s->idnr, s1.idnr);

#if 0
        printf("\nGive the name of the citizen: ");
        scanf("%s\n", s->name);
#else
        prompt("Give the name of the citizen",s->name);
#endif

#if 0
        printf("\n Give the lname of the citizen: ");
        scanf("%s\n", s->lname);
#else
        prompt("Give the lname of the citizen",s->lname);
#endif

#if 0
        printf("\n Give the birthday of the citizen in the format YYYYMMDD: ");
        scanf("%s\n",buf);
#else
        prompt("Give the birthday of the citizen in the format YYYYMMDD",buf);
#endif
        getbday(buf,&s->birthday);

#if 0
        printf("\n Give the ID of the family of the citizen: ");
        scanf("%d\n", &s->id_family);
#else
        prompt("Give the ID of the family of the citizen",buf);
        sscanf(buf,"%d", &s->id_family);
#endif

        nr_people++;
    }
}

void
change()
{
    struct citizen *s;
    char birthday[100];
#if 0
    char *idnr;
#else
    char idnr[100];
#endif

    printf("\n IDNR of citizen: ");
#if 0
    scanf("%s", &idnr);
#else
    scanf("%s\n",idnr);
#endif
    for (int i = 0; i < nr_people; i++) {
        s = &citlist[i];
        if (strcmp(s->idnr, idnr) == 0) {
            printf("\nGive the name of the citizen: ");
            scanf("%s\n", s->name);

            printf("\n Give the lname of the citizen: ");
            scanf("%s\n", s->lname);

            printf("\n Give the birthday of the citizen in the format YYYYMMDD: ");
            scanf("%s\n", birthday);
            getbday(birthday,&s->birthday);

            printf("\n Give the ID of the family of the citizen: ");
            scanf("%d\n", &s->id_family);

            printf("\n Changed succesfully.");
            return;
        }
#if 0
        printf("\n The change didn't happened.");
#endif
    }
#if 1
    printf("\n The change didn't happened.");
#endif
}

void
permit()
{
#if 0
    struct birthday bday;
#else
    struct birthday *bday;
#endif
    struct citizen *s;
    int age[nr_people];
    SYSTEMTIME d;

    GetLocalTime(&d);
    for (int i = 0; i < nr_people; i++) {
        s = &citlist[i];
        bday = &s->birthday;

        if (bday->month > d.wMonth ||
            (bday->month == d.wMonth && bday->day >= d.wDay)) {
            age[i] = d.wYear - bday->year;
        }
        else {
            age[i] = d.wYear - bday->year - 1;
        }
    }

#if 0
    char *name;
    char *lname;
    char *chosenperson;
#else
    char name[100];
    char lname[100];
    char chosenperson[100];
#endif
    int id_family;
    int i;
    int apply = 0;
    int familymembers = 0;

#if 0
    printf("Put your name: ");
    scanf("%s", &name);
#else
    prompt("Put your name",name);
#endif
#if 0
    printf("Put your lname: ");
    scanf("%s", &lname);
#else
    prompt("Put your lname",lname);
#endif

// NOTE/BUG: use strcmp instead of strstr
    for (i = 0; i < nr_people; i++) {
        s = &citlist[i];
        if ((strcmp(name, s->name) == 0 && strcmp(lname, s->lname) == 0 &&
            age[i] >= 18)) {
            printf("Your name is on the list and you are in the age to apply [%d]\n",age[i]);
            id_family = s->id_family;
            apply = 1;
        }
    }
    if (apply == 0) {
        printf("Your name is not on the list or you are not in the age to apply");
        return;
    }

    struct citizen tmp[nr_people];

    for (i = 0; i < nr_people; i++) {
        s = &citlist[i];
        if (id_family == s->id_family) {
            tmp[familymembers++] = *s;
        }
    }

    for (i = 0; i < familymembers; i++) {
        printf("%d. name: %10s\n", i + 1, tmp[i].name);
    }

    apply = 0;

    prompt("Give the name of the person from your family that you want to apply ",chosenperson);

    printf("\nYou chose: ");
    for (i = 0; i < familymembers; i++) {
        if (strcmp(chosenperson, tmp[i].name) == 0) {
            printf("%s", tmp[i].name);
            apply = 1;
        }
    }
    if (apply == 0) {
        printf("\nThe selected name is not on the list");
        return;
    }
    printf("\nChose a time between 8:00 and 17:00: ");
    float timez;
    int hour;
    int minute;

    scanf("%f", &timez);
    if (timez >= 8.00 && timez <= 17.00) {
        hour = timez;
        minute = (timez - hour) * 100;
        if (minute > 59) {
            printf("Minutes are placed wrong");
            return;
        }
        printf("\nYour application to go out from %f to %f is accepted!",
            timez, timez + 2);
        permission = 1;
    }
    else {
        printf("You have chosen the wrong time");
        return;
    }
}

void
control()
{
    permit();
    SYSTEMTIME d;
    struct citizen *s;

    GetLocalTime(&d);
    int g = permission;

    for (int i = 0; i < nr_people; i++) {
        s = &citlist[i];
        if (g == 1) {
            printf("\n The citizen with IDNR: %s   Date: %d/%d/%d  Time: %d.%d has applied to go outside",
                s->idnr, d.wYear, d.wMonth, d.wDay, hour, minute);
        }
    }
}

void
save()
{
    struct citizen *s;
    struct birthday *bday;
    FILE *f;

    f = fopen("detyra_day.dat", "w");
    if (f == NULL) {
        printf("\n Error on the file");
        return;
    }

    for (int i = 0; i < nr_people; i++) {
        s = &citlist[i];

        fprintf(f,"%s ", s->idnr);
        fprintf(f,"%s ", s->name);
        fprintf(f,"%s ", s->lname);

        bday = &s->birthday;
        fprintf(f,"%4.4d%2.2d%2.2d ",bday->year,bday->month,bday->day);

        fprintf(f,"%d\n", s->id_family);
    }

#if 1
    fclose(f);
#endif
}

int
main()
{
    char buf[100];
    int selection = 0;

    loadPeopleInfo();

    do {
        printf("\n=============================");
        printf("\n 1 - Read and print the data from the file detyra_day.dat");
        printf("\n 2 - Add a citizen");
        printf("\n 3 - Change a citizen");
        printf("\n 4 - Create a Permit to go outside");
        printf("\n 5 - Control the permission");
        printf("\n 6 - Save");
        printf("\n 7 - Print all Permissions to go outside for all citizens and families");
        printf("\n 8 - Print the list of 10 citizens that asked for the permission the most and 10 that asked the least (exclude the ones that didn't asked at all)");
        printf("\n 9 - Exit");
        printf("\n-----------------------------\n");

        prompt("Zgjedhja",buf);
        selection = buf[0];

        switch (selection) {
        case '1':
            printPeopleInfo();
            break;
        case '2':
            add();
            break;
        case '3':
            change();
            break;
        case '4':
            permit();
            break;
        case '5':
            control();
            break;
        case '6':
            save();
            break;
#if 0
        case '9':
            exit(0);
#endif
        }
#if 0
        getch();
#endif
    } while (selection != '9');

    return 0;
}

【讨论】:

  • 关于:#endif #include &lt;windows.h&gt; 头文件:windows.h 是 microsoft windows 头文件,而不是 C 库标准文件。所以这两行需要交换
  • 关于:WINBASEAPI VOID WINAPI 这不会在 'linux' 下编译,建议只为 microsoft windows 编写整个答案
  • 关于; sscanf(buf,"%4d%2d%2d",&amp;bday-&gt;year,&amp;bday-&gt;month,&amp;bday-&gt;day); 这表明 OP 不检查 C 库函数的返回值,这不是告知 OP 正确编码方式的方法
  • 关于:char *cp = strchr(buf,'\n'); if (cp != NULL) *cp = 0; 最好使用一个简单的函数调用,例如:buf[ strcspn( buf, "\n" ) ] = '\0';,当使用语句:#include &lt;string.h&gt; 时会暴露出来
  • @CraigEstey 非常感谢你我真的不明白一些命令因为我是编程新手,但我会尝试在谷歌上搜索它们并尝试理解它们。大多数代码都有效(不是全部,但我只想要第一部分太棒了)。再次感谢您对我的帮助,我真的很感激。
猜你喜欢
  • 1970-01-01
  • 2016-01-07
  • 1970-01-01
  • 2013-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-13
  • 1970-01-01
相关资源
最近更新 更多