从文件读取并使用指针

时间:2017-01-26 14:55:31

标签: 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 = 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);
}

我读取的文本文件名为test.txt:

2
11223344 Jennifer Smith
22334455 John Bob

*请注意,第一行中的2用于设置动态分配的struct的大小,用于:Student students =(Student )malloc(sizeof(Student)* size);因为只有2名学生,珍妮弗和约翰。

这是我跑来测试的命令:

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

问题是:

  1. 它似乎很好地检索了studentID,但没有找到名字(fName)和姓氏(lName)。似乎fName也会检索空间,它应该避免使用。

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

  3. 我该如何解决这个问题?非常感谢..

    首次修复后更改了部分来源:

    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
    

3 个答案:

答案 0 :(得分:1)

尝试解决这两个问题:

  1. 增加fname的大小(以及可选的lname以保留它 与fname一致从8到9.你的第一个输入“jennifer”是8 性格长。但fgets也将'\ 0'视为另一个角色。 所以它认为“jennifer \ 0”长9个字符。所以增加 fname的大小为9个字符以容纳整个字符串。
  2. 字段ID和fname之间有空格,然后是fname 和lname。你需要消耗那个空格字符。注意额外的 输出中的空格。您可以使用getchar()消费它。

答案 1 :(得分:1)

fgets正是您所要求的。您传递并声明一个包含八个字符的缓冲区。之前的读数是scanf %d,所以它已停在第一个非数字字符,这里是空格。然后输入流定位在Jenniffer...上(注意初始空格字符!)。 fgets读取7个字符并在第8个位置放置一个终止空值,它给出:

 1 2 3 4 5 6 7 8
   J e n n i f \0

如何解决?停止混合fgetsscanf ...并增加缓冲区的大小。由于最长的名字是Jennifer(8个字符),因此最小大小为9以包括终止空值。并且还要避免那种可怕的黑客攻击:while (getchar() != '\n';如果文件未被\n终止或者\nfgets吃掉,则可以保证导致无限循环1}}

最后但并非最不重要的是,控制输入函数的返回值,如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;
}

答案 2 :(得分:1)

  

您实际上并不需要再使用一个变量&#39; pointAt&#39;。你可以很好地使用malloc&#39; ed结构的学生来做你的事情。即使你这样做,这也是一个很好的做法,可以做到这一点。在释放已分配的struct之后为NULL。

free(students);
pointAt = NULL;
return 0;