【问题标题】:Storing integer array from file in structure C将文件中的整数数组存储在结构C中
【发布时间】:2012-11-29 22:18:38
【问题描述】:

我正在从文件读入结构并遇到问题。我有测试文件,其中第一个字母定义结构的名称,第二个数字告诉我它有多少个节点,其余数字是节点。文件示例:

A 4 1 2 3 4
B 5 1 2 3 9 8 
C 3 1 2 3 

所以例如结构应该是这样的:name->A; numberOfNodes->4;节点-> {1,2,3,4}。我保存每一行的结构是这样的:

struct mystruct{
char name[1];
int numberOfNodes;
int nodes[];
};

到目前为止我的功能:

lines = lineCount(courses); //calculates how many rows file has
struct courses course[lines];
co = fopen(courses, mode);
if(co == NULL){
    printf("Can't find the files.");
    exit(1);
}else{
    for(i = 0; i < lines; i++){
        fscanf(co, "%1s %d \n", &current, &id1); //Doesnt have any problems reading these two parameters;
        for(j = 0 ; j < id1; j++){ 
            fscanf(co, "%d", &course[i].nodes[j]); //Have no idea how to store array =/
        }
        strcpy(course[i].courseName, current);
        course[i].numberOfNodes = id1;
    }
}

编辑:很抱歉让你们感到困惑,它分配整数很好,但不是输出相同的东西,而是输出如下内容:

A 4 69 72 1 2
B 5 20 45 7 3 1 
C 3 2 45 1 

我认为这段代码没有做我想做的事情:

        for(j = 0 ; j < id1; j++){ 
            fscanf(co, "%d", &course[i].nodes[j]); //Have no idea how to store array =/
        }

不胜感激!

【问题讨论】:

  • 使用一个临时变量并读入它,然后根据我的回答将其设为 course[i].nodes[j] = tempVal,这被否决了。或者直接尝试 &(course[i].nodes[j]) 强制它获取正确的指针位置。但是将数组分配为动态是要走的路
  • 你应该使用char name而不是char name[1]

标签: c arrays io structure


【解决方案1】:

您的代码没有为整数数组分配任何内存,int nodes[] 被称为 灵活的数组成员它有它的用途并且它不保留 任何内存,您需要为nodes 数组分配动态内存:

struct mystruct {
    char name[1];
    int numberOfNodes;
    int *nodes;
};
...
fscanf(co, "%c %d \n", &current, &id1);   
course[i].nodes = malloc(sizeof(int)*id1);

请注意,%1s 格式说明符扫描 1 个字符的字符串,之后会添加一个空终止字节,因此您应该使用 %c 而不是只读取一个字符。

注意1:完成后不要忘记free()所有分配的内存,例如

free(course[i].nodes);

注意2:在C中分配内存的惯用方式是:

malloc(num_of_elements * sizeof *ptr_to_type); 

为了避免混淆,我没有在这里介绍,另外请注意,我个人不喜欢转换malloc()的结果,有一些很好的理由: Do I cast the result of malloc?

【讨论】:

  • 如果您真的想通过本书提供正确答案,请完成您的回复:使用free(nodes),其中nodes 是指向int 的指针。此外,malloc 函数返回一个void* 指针,任何类型的指针变量都可以将其视为有效。预先添加显式强制转换 - nodes = (int*) malloc(sizeof(int)*numberOfNodes); - 或者依赖默认强制转换不仅可以使代码更具可读性,而且可以确保你得到你想要的。
  • @LonWolf 首先有一个使用 free() 的注释,在 C you should not cast the result of malloc 中。这又是一个 C 答案,而不是 C++。
【解决方案2】:

您的问题是您不知道字母后面有多少个数字。 因此,您可以说不超过 1000 或您认为“足够”的任何内容。或者您将这个数字一个接一个地存储在一种链接结构中。如果您使用例如提供链接列表的库,那么以后会更容易完成。一个例子就是油嘴滑舌。

如果你想存储在数组中,你必须使用一些东西来为数组动态分配空间。您将需要一些 malloc/realloc/free 的组合。

存储数组的项目可以在你打印的时候完成 &course[i].nodes[j] 可以,但是你当然需要足够的空间来真正访问节点[j]

问候

【讨论】:

    【解决方案3】:

    如果您使用标准 C/C++,则需要在赋值之前初始化数组,并确保在 fscanf() 时获得正确的指针!

    struct mystruct{
    char name[1];
    int numberOfNodes;
    int* nodes;
    };
    

    然后在 if 的 else 部分:

    else{
        for(i = 0; i < lines; i++){
            fscanf(co, "%1s %d \n", &current, &id1); //Doesnt have any problems reading these two parameters;
            course[i].nodes = new int[id1]; //init array length of id1 value
            for(j = 0 ; j < id1; j++){ 
                int tempNode;
                fscanf(co, "%d", &tempNode); 
                course[i].nodes[j] = tempNode; //allocate the node value to the correct location. 
            }
            strcpy(course[i].courseName, current);
            course[i].numberOfNodes = id1;
        }
    

    或者,您应该能够使用以下方法绕过临时值:

    fscanf(co, "%d", &(course[i].nodes[j]));
    

    但我认为某些编译器可能无法将其视为正确。由于数据的结构,使用临时值更好 - 我的意见。

    最后别忘了循环遍历 course[] 向量和delete (course[i].nodes)

    如果您想要纯 C,则需要使用 malloc(),这可能会很麻烦 - 不如新的漂亮,请删除。

    无论如何,我建议使用 STL 向量来实现更轻松的内存管理,减轻指针分配的压力,并通过使用预定义的运算符函数 - push_back、pop_back、insert 来使用优雅的数据管理(迭代、添加、删除),删除。

    http://www.cplusplus.com/reference/vector/vector/


    我在一些代码中添加了“()”以强调运算符的优先级。

    【讨论】:

    • 那不是 C,那是混合的 C/C++ C 没有 newdelete 并且绝对没有 vector
    • 我还没准备好答案。我想提供一个符合 C++ 的解决方案,因为它更优雅。感谢您的反对。..
    • 问题被标记为C 而不是C++ 不需要C++ 解决方案,否决票意味着这个答案没有用,也无意冒犯您。
    • @LonWolf:更优雅?这是您的观点,malloc 处理起来可能很痛苦也是您的观点,问题标记为 C,您的建议可能会混淆 op
    【解决方案4】:
    #include <stdio.h>
    #include <stdlib.h>
    
    struct mystruct {
        struct mystruct *next;
        char name; /* No need to dim array as name[1] */
        int numberOfNodes;
        int nodes[];
    };
    
    int main(void)
    {
        /* Don't like VLA's, I used a list */
        struct mystruct *curr, *first = NULL, *prior = NULL;
        char s[256], *p;
        FILE *f;
        int i;
    
        /* Open (No need to count lines before) */
        f = fopen("data", "r");
        if (f == NULL) {
            perror("fopen");
            exit(EXIT_FAILURE);
        }
        /* Fill */
        while (fgets(s, sizeof(s), f) != NULL) {
            i = (int)strtol(&s[1], &p, 10);
            if (i == 0) continue; /* Skip blank or 0 node */
            /* Flexible array must be alloced with parent */
            curr = malloc((sizeof *curr) + (sizeof(int) * (size_t)i));
            curr->next = NULL;
            curr->name = s[0];
            curr->numberOfNodes = i;
            for (i = 0; i < curr->numberOfNodes; i++) {
                curr->nodes[i] = (int)strtol(p, &p, 10);
            }
            if (prior) {
                prior->next = curr;
            } else {
                first = curr;
            }
            prior = curr;
        }
        fclose(f);
        /* Print */
        curr = first;
        while (curr) {
            printf("%c %d", curr->name, curr->numberOfNodes);
            for (i = 0; i < curr->numberOfNodes; i++) {
                printf(" %d", curr->nodes[i]);
            }
            printf("\n");
            curr = curr->next;
        }
        /* Free */
        while (first) {
            curr = first->next;
            free(first);
            first = curr;
        }
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-27
      相关资源
      最近更新 更多