1

ファイルを読み込んで、個々の行を個別の要素として配列に入れる関数があります。次に、配列を通過し、構造体内の特定の位置に特定の要素を配置することになっています。

私はほとんどそれを持っています... すべてが正しいことを確認するために構造体を印刷すると、余分な文字が表示されます!

これはファイルにあるものです:

123
pre
45
cse
67
345
ret
45
cse
56

そして、これはそれが印刷しているものです:

123
pre
45
cse
C
67
345
ret
45
cse
8
56

コードは次のとおりです。

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

struct students         //Defining structure for students
{
    int id;        //Students ID Number
    char name[30];      //Students Name
    int age;            //Students Age
    char dept[4];       //Studets Department
    int grade;          //Students Grade
};



int main()
{
    struct students list[20];
    FILE *f;
    char line[30];
    char **temp = NULL;
    int num_righ = 0;
    int id5;
    int age5;
    int grade5;
    int i, k;

    f = fopen("records.txt", "r");



    while(fgets(line, sizeof (line), f) != NULL)
    {
        if (line != NULL)
        {
            num_righ++;
            temp = (char**)realloc(temp, sizeof(char*) *num_righ);
            temp[num_righ - 1] = strdup(line);
        }
    }

    fclose(f);
    k = 0;
    i = 0;
    while (temp[i] != NULL)
    {
        id5 = atoi(temp[i]);
        list[k].id = id5;
        i++;
        strcpy(list[k].name, temp[i]);
        i++;
        age5 = atoi(temp[i]);
        list[k].age = age5;
        i++;
        strcpy(list[k].dept, temp[i]);
        i++;
        grade5 = atoi(temp[i]);
        list[k].grade = grade5;
        i++;
        k++;


    }
    for (i = 0; i < k; i++)
    {
        printf("%d\n", list[i].id);
        printf("%s", list[i].name);
        printf("%d\n", list[i].age);
        printf("%s\n", list[i].dept);
        printf("%d\n", list[i].grade);
    }
}
4

2 に答える 2

4

注意すべきことの 1 つは、'C' の 10 進値が 67 で、'8' の 10 進値が 56 であることです。students 配列の dept 配列が小さすぎます。改行文字を取得しているため、終了文字を格納できません。printf は、char として出力されるグレード整数まで実行されます。

編集:むしろ、配列は小さすぎませんが、fgets は配列を埋める改行を取得しているため、null ターミネータが適切に格納されません。

于 2013-10-31T01:30:08.873 に答える
1

次のコードは、複数の問題に対処しています。文字列が「安全に」コピーされることを確認するだけでなく ( を使用しstrncpy、文字列を で終了する'\0')、メモリ内のすべてのデータの 2 番目のコピーを作成しないようにします。 (おもちゃの例の問題ではありませんが、悪い習慣から始めるのはなぜですか)。

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

struct students         //Defining structure for students
{
    int id;        //Students ID Number
    char name[30];      //Students Name
    int age;            //Students Age
    char dept[4];       //Studets Department
    int grade;          //Students Grade
};

int main()
{
    struct students list[20];
    FILE *f;
    char line[30];
    char **temp = NULL;
    int num_righ = 0;
    int id5;
    int age5;
    int grade5;
    int i, k=0;
    char *newLine;

    f = fopen("records.txt", "r");
    int s = 0;  // this is the "state" counter - it goes from 0 to 4, then back to 0

    while(fgets(line, sizeof (line), f) != NULL)
    {
       newLine = strchr(line, '\n');
       if(newLine) *newLine='\0'; // terminate string on the newline.
        switch(s) {
          case 0:
            list[k].id = atoi(line);
            break;
          case 1:
             strncpy(list[k].name, line, 30);
             list[k].name[29]='\0'; // make sure it is terminated
             break;
          case 2:
            list[k].age = atoi(line);
            break;
          case 3:
            strncpy(list[k].dept, line, 3);
            list[k].dept[3] = '\0'; // make sure it is terminated
            break;
          case 4:
            list[k].grade = atoi(line);
            break;
        }
        s++;
        if (s == 5) {
          s = 0;
          k++; // if it's 5, go back to zero and start reading next structure
        }
      }
    fclose(f);

    for (i = 0; i < k; i++)
    {
        printf("id: %d\n", list[i].id);
        printf("name: %s", list[i].name);
        printf("age: %d\n", list[i].age);
        printf("dept: %s\n", list[i].dept);
        printf("grade: %d\n\n", list[i].grade);
    }
}
于 2013-10-31T01:23:41.410 に答える