2

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

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 =/
        }

将不胜感激任何帮助!

4

4 回答 4

2

您的代码不会为整数数组分配任何内存,它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(),有一些很好的理由: 我是否转换了 malloc 的结果?

于 2012-12-12T08:52:42.673 回答
1
#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;
}
于 2012-12-12T09:52:48.083 回答
0

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

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

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

问候

于 2012-12-12T08:57:35.807 回答
-1

如果您使用标准 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、erase 来使用优雅的数据管理(迭代、添加、删除)。

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


我在一些代码中添加了 '()' 以强调操作员的优先级。

于 2012-12-12T08:58:03.873 回答