【问题标题】:Problems with arrays within structures and files in CC中结构和文件中的数组问题
【发布时间】:2018-02-18 21:54:52
【问题描述】:

我正在尝试使用 C 中的结构存储课程名称和我上该课程的日期的信息。存储名称不是问题。当我尝试将多天(工作日作为整数,即星期一 = 1)存储在数组中时,就会出现问题。

这就是我所拥有的:

#include<stdio.h>
#include<string.h>

struct lessons{

   char name[20];
   int day[3];

};

changelessons(){

    int i, k;
    struct lessons give[1], receive[1];

    FILE *fptr;

    fptr = fopen("lessons","wb");

    fflush(stdin);

    printf("\n\t ~ Change lessons ~");
    printf("\n\nWhat's the lesson called?: ");
    gets(give[0].name);

    printf("\nHow many days do you have it?\n");
    scanf("%d", &k);

    for(i = 0; i < k; i++); {  // Asks the weekday number for each day you have the lesson
        printf("What day is lesson %d?: ", i);
        scanf("%d", &give[0].day[i]);
    }

    fwrite(give, sizeof(give), 1, fptr);
    fclose(fptr);

    fptr = fopen("lessons", "rb");
    fread(receive, sizeof(receive), 1, fptr);

    printf("\n\t ~ Updated information: ~\n\nLesson name: %s\nDay: %d", receive[0].name, receive[0].day[1]);

    for(i = 1; i < k; i++); {  // Prints the extra weekdays if there are any
        printf(", day: %d", receive[0].day[i]);
    }

    printf("\n\n");

    fclose(fptr);
}

showlessons(){

    struct lessons give[1], receive[1];

    FILE *fptr;

    fptr = fopen("lessons", "rb");
    fread(receive, sizeof(receive), 1, fptr);

    printf("\t ~ Current information: ~ \n\nLesson name: %s\nDay: %d\n\n", receive[0].name, receive[0].day[0]);

}

int main(){

  showlessons();
  changelessons();

  return 0;
}

此外,在第一个 for 循环中,无论 k 等于多少,它只会循环一次。

提前感谢您的帮助!

【问题讨论】:

  • for(i = 0; i &lt; k; i++); { 在这里,您为 for 的主体使用了单语句。所以下面的{} body 会被执行一次。

标签: c arrays file structure


【解决方案1】:
for(i = 0; i < k; i++);

应该是

for(i = 0; i < k; i++)

多余的分号是个问题。您的循环代码不是循环的一部分。分号结束循环。

【讨论】:

    【解决方案2】:

    nicomp 指出了最明显的错误。

    但我还想指出您的代码存在的一些问题:

    1. fflush(stdin); 这是错误的、未定义的行为。 fflush 用于 Flusg 输出流,stdin 是输入流。见Using fflush(stdin)

      我知道在 Windows 中 fflush(stdin) 会清除输入缓冲区,但我强烈 建议不要使用它,因为在中继功能时会失去可移植性 仅在一个操作系统中可用。如果您不关心可移植性,请使用它。如果 您使用它是因为 scanf 在输入缓冲区中留下了东西,请改用它:

      int c;
      while((c = getchar()) != '\n' && c != EOF);
      

      这是便携式的。

    2. 永远不要在 2018 年使用 getsgets 是一个不安全、危险的函数,它 在 C99 中已被弃用,原因很充分:它不占用 考虑缓冲区,如果输入的文本比缓冲区长 存储,它将溢出缓冲区。这是一场等待发生的事故。所以, 永远不要再使用gets。请改用fgets,如果您不想拥有 换行符,你可以删除它:

      fgets(give[0].name, sizeof give[0].name, stdin);
      give[0].name[sizeof(give[0].name) - 1] = 0; // remove possible newline
      
    3. 为什么要声明一个维度为 1 的 struct lessons 数组?是什么 观点?你不需要一个数组。你可以这样写:

      struct lessons give, receive;
      ...
      
      printf("\n\nWhat's the lesson called?: ");
      fgets(give.name, sizeof give.name, stdin);
      give.name[strcspn(give.name, "\n")] = 0;
      
      ...
      
      fwrite(&give, sizeof give, 1, fptr);
      fclose(fptr);
      
      ...
      
      fptr = fopen("lessons", "rb");
      fread(&receive, sizeof receive, 1, fptr);
      

      别忘了检查fwritefread的返回值。

    4. 查看fopen的返回值,如果返回NULL,则不能使用 freadfwrite。打印错误值并返回/退出。

    5. stdout 被缓冲,当你用printf 写入它时,它不会 必须立即在屏幕上打印字符。一个例外是当 stdout 连接到终端,换行符用printf 写入。为了 用户交互这很棒,因为用户会看到输出 立即地。这就是为什么大多数人会在文本中打印一个换行符。

      如果您不这样做,但仍希望用户立即看到 输出,那么这次你应该使用fflush:

       printf("What day is lesson %d?: ", i);
       fflush(stdout);
       scanf("%d", &give[0].day[i]);
      

      我不知道是否可以保证scanf 刷新stdout 连接到终端,不管使用fflush(stdout) 是个好习惯 当你最后不打印换行符时。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-12-30
      • 2014-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-10
      相关资源
      最近更新 更多