在C中修改并打印typedef< d'd数组

时间:2014-12-12 00:19:36

标签: c structure typedef

我正在学习使用结构,当用C进行一次练习时,这个疑问来找我。 我有这段代码:

#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>

#define MAX_STRING 256
#define MAX_CHILD 2000
#define MAX_GIFTS 20
#define MAX_LINE 1024

typedef char String[MAX_STRING];
typedef char Line[MAX_LINE];

typedef struct {    
    String child_name;  
    int grade;               //integer between 0 and 5
    String gift_name;   
    int price;              //price of the gift
} Data;

typedef struct { 
    String name;        
    int price;          
    bool received;      //true if the child will get this gift

} Gift;

typedef Gift Gifts[MAX_CHILD];

typedef struct{ 
    String name;            
    int grade;      
    Gifts asked;         //gifts the child asked for
    int n_asked;        
} Child;

typedef Child Children[MAX_CHILD];

Data make_data (String line){
    Data d;
    sscanf(line,"%s %d %s %d", d.child_name, &d.grade, d.gift_name, &d.price);
    return d;
}

Child make_child(Data d) {
    Child c;
    strcpy(c.name, d.child_name);
    c.grade = d.grade;
    c.n_asked = 0;
    return c;
}

Gift make_gift(Data d){
    Gift g;
    strcpy(g.name, d.gift_name);
    g.price = d.price;
    g.received = false;
    return g;
}

int process(char file_name[]){
    Line line;
    FILE *f = fopen(file_name, "r");
    while(fgets(line, MAX_LINE, f) != NULL){
        make_data(line);  
    }
    int fclose (FILE *f);
}

int main(){
    process("data.txt");
    return 0;
}

所以这个程序收到这种格式的文件文本:

John 4 Bike 200
Alice 3 Computer 800
Alice 3 Candy 10
Mike 5 Skate 100

并在函数进程中构建数据。

问题是,我想将所有子项存储在数组Children []中并打印它(打印所有数组或类似于Children [0],Children [1]等)。我尝试了一些方法但没有成功......因为数组是Child类型而不是char *。即使我只是Children cs;,我也会遇到分段错误。有没有办法可以实现这个目标?

我的第二个问题是,最初我有#define MAX_CHILD 20000,当我尝试编译时,我得到一个错误说&#34;数组'儿童'的大小太大&#34;。为什么会这样?我认为它不会发生在礼物上,但会发生在儿童身上,因为结构Child在成员上有一个礼物类型,这意味着它需要更多的空间。

任何帮助表示感谢。

2 个答案:

答案 0 :(得分:0)

the use of the typedef's (and so on) 
instead of just writing the code out where it is needed
is unneeded (and distracting) and mis-leading and 
makes the code much more difficult to follow.

This function:

Data make_data (String line)
{
    Data d;
    sscanf(line,"%s %d %s %d", d.child_name, &d.grade, d.gift_name, &d.price);
    return d;
}

has several problems:
1) the parameter list will cause the compiler to 'set aside' enough room
   for the String struct,
   invoke a memcpy() to copy the String struct
   to that 'set aside' memory from the callers' memory
   Then copy the 'set aside' memory to the called functions' stack
   That 'set aside' memory will never be used for anything else
   The stack will be cluttered with the contents of the String struct
   until the function returns
   such activity is a real 'bear' to debug
2) the returned value from sscanf() needs to be checked
   to assure that all 4 conversion operations were successful
3) the function return is a instance of the Data struct.
   This will cause the compiler to 'set aside' enough room
   for the Data struct.
   that 'set aside' memory will never be used for anything else
   invoke a memcpy() to copy the Data struct from the stack
   to the 'set aside' memory
   then perform the return from the function
   then the compiler will cause the caller to 
   invoke memcpy() to copy the Data struct
   from the 'set aside' memory to the caller's Data struct area.
   such activity is a real 'bear' to debug.

The function should be written more like this:

int make_data (String *pLine, Data* pData)
{
    int returnValue = 1; // initialize to indicate function successful

    if( 4 != sscanf(pLine," %s %d %s %d", 
                    pData->child_name, 
                   &pData->grade, 
                    pData->gift_name, 
                   &pData->price) )
    { // then sscanf failed
        perror( "sscanf failed for Line" );
        returnValue = 0; // indicate to caller that function failed
    } //  end if

    return( returnValue );
} // end function: make_data

and the caller(s) of this function should be adjusted accordingly

the make_gift() function has the same passed parameter
and returned parameter problems.

答案 1 :(得分:0)

  

问题是,我想将所有子节点存储在数组中   儿童[]并打印它(打印所有数组或只是一些东西   类似于儿童[0],儿童[1]等。

存储:

    static Children cs;
    size_t nc = 0;  // number of children
    while (fgets(line, MAX_LINE, f))
    {
        #include <search.h>
        Data d = make_data(line);  
        Child c = make_child(d);
        Child *cp = lsearch(&c, cs, &nc, sizeof c, (int (*)())strcmp);
        cp->asked[cp->n_asked++] = make_gift(d);
    }

打印:

    int i, j;
    for (i = 0; i < nc; ++i)
    {
        printf("%s (grade %d) asked for %d:\n",
               cs[i].name, cs[i].grade, cs[i].n_asked);
        for (j = 0; j < cs[i].n_asked; ++j)
            printf("\t%s\t%d\n", cs[i].asked[j].name, cs[i].asked[j].price);
    }

(我们不能简单地打印聚合类型对象 - 我们必须打印单个元素。)