Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 从文件中读取数据,并使用指针将数据放入动态结构中_C_Pointers_Gcc_Struct - Fatal编程技术网

C 从文件中读取数据,并使用指针将数据放入动态结构中

C 从文件中读取数据,并使用指针将数据放入动态结构中,c,pointers,gcc,struct,C,Pointers,Gcc,Struct,我正在尝试制作一个程序来管理学生的信息。但由于缺乏c编程技巧,我不能很好地使用指针 以下是源代码: #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct { int id; char fName[8]; char lName[8]; } Student; void main() { int size = 0; int i

我正在尝试制作一个程序来管理学生的信息。但由于缺乏c编程技巧,我不能很好地使用指针

以下是源代码:

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

typedef struct
{
    int id;
    char fName[8];
    char lName[8];
} Student;

void main()
{

    int size = 0;
    int i = 0;

    /* get max lines */
    scanf("%d", &size);

    Student *students = (Student*) malloc(sizeof(Student) * size); // allocate whole table
    Student *pointAt = students; // pointer used to point whole table by memory address

    /* retrieves data from stdin */
    for (i = 0; i < size; i++)
    {
        scanf("%d", &((*pointAt).id));
        printf("recorded id at %d is %d\n", i, (*pointAt).id);
        fgets((*pointAt).fName, sizeof((*pointAt).fName), stdin);
        printf("recorded fName at %d is %s\n", i, (*pointAt).fName);
        fgets((*pointAt).lName, sizeof((*pointAt).lName), stdin);
        printf("recorded lName at %d is %s\n", i, (*pointAt).lName);
        while (getchar() != '\n')
            ;
    }

    free(students);
}
2
11223344 Jennifer Smith
22334455 John Bob
a.out < test.txt
recorded id at 0 is 11223344
recorded fName at 0 is  Jennif
recorded lName at 0 is er Smit
recorded id at 1 is 22334455
recorded fName at 1 is  John B
recorded lName at 1 is ob
^Z
Suspended
for(i=0; i<size; i++) {
scanf("%d", &((*pointAt).id));
printf("recorded id at %d is %d\n", i, (*pointAt).id);
getchar();
fgets((*pointAt).fName, sizeof((*pointAt).fName), stdin);
printf("recorded fName at %d is %s\n", i, (*pointAt).fName);
getchar();
fgets((*pointAt).lName, sizeof((*pointAt).lName), stdin);
printf("recorded lName at %d is %s\n", i, (*pointAt).lName);
}
recorded id at 0 is 11223344
recorded fName at 0 is Jennifer
recorded lName at 0 is Smith

recorded id at 1 is 22334455
recorded fName at 1 is John Bob
recorded lName at 1 is Smith
*注意,这里第一行的2用于设置动态分配结构的大小,用于:Student students=(Student)malloc(sizeof(Student)*size);因为只有两个学生,詹妮弗和约翰

下面是我运行来测试这个的命令:

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

typedef struct
{
    int id;
    char fName[8];
    char lName[8];
} Student;

void main()
{

    int size = 0;
    int i = 0;

    /* get max lines */
    scanf("%d", &size);

    Student *students = (Student*) malloc(sizeof(Student) * size); // allocate whole table
    Student *pointAt = students; // pointer used to point whole table by memory address

    /* retrieves data from stdin */
    for (i = 0; i < size; i++)
    {
        scanf("%d", &((*pointAt).id));
        printf("recorded id at %d is %d\n", i, (*pointAt).id);
        fgets((*pointAt).fName, sizeof((*pointAt).fName), stdin);
        printf("recorded fName at %d is %s\n", i, (*pointAt).fName);
        fgets((*pointAt).lName, sizeof((*pointAt).lName), stdin);
        printf("recorded lName at %d is %s\n", i, (*pointAt).lName);
        while (getchar() != '\n')
            ;
    }

    free(students);
}
2
11223344 Jennifer Smith
22334455 John Bob
a.out < test.txt
recorded id at 0 is 11223344
recorded fName at 0 is  Jennif
recorded lName at 0 is er Smit
recorded id at 1 is 22334455
recorded fName at 1 is  John B
recorded lName at 1 is ob
^Z
Suspended
for(i=0; i<size; i++) {
scanf("%d", &((*pointAt).id));
printf("recorded id at %d is %d\n", i, (*pointAt).id);
getchar();
fgets((*pointAt).fName, sizeof((*pointAt).fName), stdin);
printf("recorded fName at %d is %s\n", i, (*pointAt).fName);
getchar();
fgets((*pointAt).lName, sizeof((*pointAt).lName), stdin);
printf("recorded lName at %d is %s\n", i, (*pointAt).lName);
}
recorded id at 0 is 11223344
recorded fName at 0 is Jennifer
recorded lName at 0 is Smith

recorded id at 1 is 22334455
recorded fName at 1 is John Bob
recorded lName at 1 is Smith
问题是:

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

typedef struct
{
    int id;
    char fName[8];
    char lName[8];
} Student;

void main()
{

    int size = 0;
    int i = 0;

    /* get max lines */
    scanf("%d", &size);

    Student *students = (Student*) malloc(sizeof(Student) * size); // allocate whole table
    Student *pointAt = students; // pointer used to point whole table by memory address

    /* retrieves data from stdin */
    for (i = 0; i < size; i++)
    {
        scanf("%d", &((*pointAt).id));
        printf("recorded id at %d is %d\n", i, (*pointAt).id);
        fgets((*pointAt).fName, sizeof((*pointAt).fName), stdin);
        printf("recorded fName at %d is %s\n", i, (*pointAt).fName);
        fgets((*pointAt).lName, sizeof((*pointAt).lName), stdin);
        printf("recorded lName at %d is %s\n", i, (*pointAt).lName);
        while (getchar() != '\n')
            ;
    }

    free(students);
}
2
11223344 Jennifer Smith
22334455 John Bob
a.out < test.txt
recorded id at 0 is 11223344
recorded fName at 0 is  Jennif
recorded lName at 0 is er Smit
recorded id at 1 is 22334455
recorded fName at 1 is  John B
recorded lName at 1 is ob
^Z
Suspended
for(i=0; i<size; i++) {
scanf("%d", &((*pointAt).id));
printf("recorded id at %d is %d\n", i, (*pointAt).id);
getchar();
fgets((*pointAt).fName, sizeof((*pointAt).fName), stdin);
printf("recorded fName at %d is %s\n", i, (*pointAt).fName);
getchar();
fgets((*pointAt).lName, sizeof((*pointAt).lName), stdin);
printf("recorded lName at %d is %s\n", i, (*pointAt).lName);
}
recorded id at 0 is 11223344
recorded fName at 0 is Jennifer
recorded lName at 0 is Smith

recorded id at 1 is 22334455
recorded fName at 1 is John Bob
recorded lName at 1 is Smith
  • 它似乎可以很好地检索studentID,但不能检索名字(fName)和姓氏(lName)。fName似乎也检索到了空间,这是它应该避免的

  • 由于使用“while(getchar()!='\n');”清除输入缓冲区,程序进入无限循环。所以我按ctrl+z(^z)强制终止程序,您可以在我的示例输出中看到

  • 我怎样才能解决这个问题?非常感谢


    第一次修复后更改了部分源:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct
    {
        int id;
        char fName[8];
        char lName[8];
    } Student;
    
    void main()
    {
    
        int size = 0;
        int i = 0;
    
        /* get max lines */
        scanf("%d", &size);
    
        Student *students = (Student*) malloc(sizeof(Student) * size); // allocate whole table
        Student *pointAt = students; // pointer used to point whole table by memory address
    
        /* retrieves data from stdin */
        for (i = 0; i < size; i++)
        {
            scanf("%d", &((*pointAt).id));
            printf("recorded id at %d is %d\n", i, (*pointAt).id);
            fgets((*pointAt).fName, sizeof((*pointAt).fName), stdin);
            printf("recorded fName at %d is %s\n", i, (*pointAt).fName);
            fgets((*pointAt).lName, sizeof((*pointAt).lName), stdin);
            printf("recorded lName at %d is %s\n", i, (*pointAt).lName);
            while (getchar() != '\n')
                ;
        }
    
        free(students);
    }
    
    2
    11223344 Jennifer Smith
    22334455 John Bob
    
    a.out < test.txt
    
    recorded id at 0 is 11223344
    recorded fName at 0 is  Jennif
    recorded lName at 0 is er Smit
    recorded id at 1 is 22334455
    recorded fName at 1 is  John B
    recorded lName at 1 is ob
    ^Z
    Suspended
    
    for(i=0; i<size; i++) {
    scanf("%d", &((*pointAt).id));
    printf("recorded id at %d is %d\n", i, (*pointAt).id);
    getchar();
    fgets((*pointAt).fName, sizeof((*pointAt).fName), stdin);
    printf("recorded fName at %d is %s\n", i, (*pointAt).fName);
    getchar();
    fgets((*pointAt).lName, sizeof((*pointAt).lName), stdin);
    printf("recorded lName at %d is %s\n", i, (*pointAt).lName);
    }
    
    recorded id at 0 is 11223344
    recorded fName at 0 is Jennifer
    recorded lName at 0 is Smith
    
    recorded id at 1 is 22334455
    recorded fName at 1 is John Bob
    recorded lName at 1 is Smith
    

    尝试解决以下两个问题:

  • 增加fname(可选lname)的大小以保留它 与fname一致)从8到9。您的第一个输入“jennifer”是8 字符长。但是
    fgets
    也将“\0”计算为另一个字符。 所以它认为“jennifer\0”有9个字符长。因此,增加 fname的大小为9个字符,以容纳整个字符串
  • 字段ID和fname之间有一个空格,然后是fname 还有名字。您需要使用该空格字符。注意一个额外的 输出中的空间。您可以使用
    getchar()
    使用它

  • 尝试解决以下两个问题:

  • 增加fname(可选lname)的大小以保留它 与fname一致)从8到9。您的第一个输入“jennifer”是8 字符长。但是
    fgets
    也将“\0”计算为另一个字符。 所以它认为“jennifer\0”有9个字符长。因此,增加 fname的大小为9个字符,以容纳整个字符串
  • 字段ID和fname之间有一个空格,然后是fname 还有名字。您需要使用该空格字符。注意一个额外的 输出中的空间。您可以使用
    getchar()
    使用它

  • fgets
    完全按照您的要求执行。传递并声明一个八个字符的缓冲区。上一次读取是一个
    scanf%d
    ,因此它在第一个非数字字符(此处为空格)上停止。然后将输入流定位到
    jennifer…
    (注意初始空格!)
    fgets
    读取7个字符,并在第8个位置放置一个终止null,该位置给出:

     1 2 3 4 5 6 7 8
       J e n n i f \0
    
    如何修复?停止混合
    fgets
    scanf
    。。。并增加缓冲区的大小。由于最长的名称为Jennifer(8个字符),因此包含终止null的最小大小为9。还要避免这种可怕的黑客行为:
    while(getchar()!='\n';
    ,如果文件不是由
    \n
    终止的,或者如果最后一个
    \n
    fgets
    吃掉,这将导致无限循环

    最后但并非最不重要的一点是,控制输入函数(如scanf)的返回值。还需要main返回一个int而不是void,并且malloc返回值不应在C中强制转换

    固定代码可能如下所示:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct
    {
        int id;
        char fName[12];    
        char lName[12];
    } Student;
    
    int main()
    {
    
        int size = 0;
        int i = 0;
    
        /* get max lines */
        int cr = scanf("%d", &size);
        if (cr != 1) {
            fprintf(stderr, "Incorrect size");
            return 1;
        }
    
        Student *students = malloc(sizeof(Student) * size); // allocate whole table
        Student *pointAt = students; // pointer used to point whole table by memory address
    
        /* retrieves data from stdin */
        for (i = 0; i < size; i++)
        {
            cr = scanf("%d%11s%11s", &(pointAt->id),pointAt->fName, pointAt->lName);
            if (cr != 3) {
                fprintf(stderr, "Incorrect format line %d\n", i+1);
                return 1;
            }
            printf("recorded id at %d is %d\n", i, (*pointAt).id);
            printf("recorded fName at %d is %s\n", i, (*pointAt).fName);
            printf("recorded lName at %d is %s\n", i, (*pointAt).lName);
            pointAt += 1; // point to next struct in array
        }
        free(students);
        return 0;
    }
    
    #包括
    #包括
    #包括
    类型定义结构
    {
    int-id;
    char-fName[12];
    字符名称[12];
    }学生;
    int main()
    {
    int size=0;
    int i=0;
    /*获取最大行数*/
    int cr=scanf(“%d”和大小);
    如果(cr!=1){
    fprintf(标准“尺寸不正确”);
    返回1;
    }
    Student*students=malloc(sizeof(Student)*size);//分配整个表
    Student*pointAt=students;//用于按内存地址指向整个表的指针
    /*从stdin检索数据*/
    对于(i=0;iid)、pointAt->fName、pointAt->lName);
    如果(cr!=3){
    fprintf(stderr,“不正确的格式行%d\n”,i+1);
    返回1;
    }
    printf(“在%d处记录的id是%d\n”,i,(*pointAt).id);
    printf(“在%d处记录的fName是%s\n”,i,(*pointAt).fName);
    printf(“在%d处记录的lName是%s\n”,i,(*pointAt).lName);
    pointAt+=1;//指向数组中的下一个结构
    }
    免费(学生);
    返回0;
    }
    
    fgets
    完全按照您的要求执行。您传递并声明一个八个字符的缓冲区。上一次读取是一个
    扫描%d
    ,因此它在第一个非数字字符(这里是空格)上停止。然后输入流定位在
    Jennifer…
    (注意初始空格!).
    fgets
    读取7个字符,并在第8个位置放置一个终止null,该位置给出:

     1 2 3 4 5 6 7 8
       J e n n i f \0
    
    如何修复?停止混合
    fgets
    scanf
    …并增加缓冲区的大小。由于最长的名称是Jennifer(8个字符),包含终止null的最小大小是9。同时也避免了可怕的攻击:
    while(getchar()!='\n';
    如果文件没有被
    \n
    终止,或者最后一个
    \n
    fgets吃掉,则保证导致无限循环

    最后但并非最不重要的一点是,控制输入函数(如scanf)的返回值。还需要main返回一个int而不是void,并且malloc返回值不应在C中强制转换

    固定代码可能如下所示:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct
    {
        int id;
        char fName[12];    
        char lName[12];
    } Student;
    
    int main()
    {
    
        int size = 0;
        int i = 0;
    
        /* get max lines */
        int cr = scanf("%d", &size);
        if (cr != 1) {
            fprintf(stderr, "Incorrect size");
            return 1;
        }
    
        Student *students = malloc(sizeof(Student) * size); // allocate whole table
        Student *pointAt = students; // pointer used to point whole table by memory address
    
        /* retrieves data from stdin */
        for (i = 0; i < size; i++)
        {
            cr = scanf("%d%11s%11s", &(pointAt->id),pointAt->fName, pointAt->lName);
            if (cr != 3) {
                fprintf(stderr, "Incorrect format line %d\n", i+1);
                return 1;
            }
            printf("recorded id at %d is %d\n", i, (*pointAt).id);
            printf("recorded fName at %d is %s\n", i, (*pointAt).fName);
            printf("recorded lName at %d is %s\n", i, (*pointAt).lName);
            pointAt += 1; // point to next struct in array
        }
        free(students);
        return 0;
    }
    
    #包括
    #包括
    #包括
    类型定义结构
    {
    int-id;
    char-fName[12];
    字符名称[12];
    }学生;
    int main()
    {
    int size=0;
    int i=0;
    /*获取最大行数*/
    int cr=scanf(“%d”和大小);
    如果(cr!=1){
    fprintf(标准“尺寸不正确”);
    返回1;
    }
    Student*students=malloc(sizeof(Student)*size);//分配整个表
    Student*pointAt=students;//用于通过备忘录指向整个表的指针