2

ファイルから構造体に読み込んでいて、問題に遭遇しました。最初の文字が構造体の名前を定義するテストファイルがあります。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);

フォーマット指定子は 1 文字の文字列をスキャンすることに注意してください%1s。後でヌル終了バイトが追加されるため、%c代わりに 1 文字だけを読み取るために使用する必要があります。

free()注1:完了したら、割り当てたすべてのメモリを忘れないでください。例

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 に答える
-1

標準の C/C++ を使用している場合は、値を割り当てる前に配列を初期化する必要があります。

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 に答える