将值放入文件的结构中

时间:2016-04-02 14:03:38

标签: c struct

好的,我知道如何将值放入文件的结构中。

我在文件中的值与我的逗号分开。数据是这样的:

number, product, price, other

只有部分商品具有其他价值!

如何在结构中包含可选值?

这样:

typedef struct stockItem {
    int number;
    char* product;
    int price;
    char *other;
} stockItem;

我输入的数据如下:

while (fgets(str, 255, invf) != NULL){   
    int numOfItems = atoi(strtok(str, " ,"));
    char *stockCode = strtok(NULL, " ,");
    int price = atoi(strtok(NULL, " ,"));
    char *other = strTok(NULL, " "));

    stockItem *item = stockItem_new(numOfItems , stockCode, price, other);

它当然不会执行,因为有些项目有另一项,我该怎么办?我应该在每个没有其他值的值中插入null吗?

1 个答案:

答案 0 :(得分:3)

是的,对于没有该字段的每个项目,您应该将other设置为NULL。这是指示没有指向的东西的正常方式。

此外,strtok()将返回一个指向str的内部指针,您可以为每个项目重复使用该指针。您应确保stockItem_new()函数实际上正在复制该数据(使用strdup()strcpy()),而不仅仅是将该字段设置为等于指针,或者将此字段设置为{{1} s将最终指向同一个内存,每次调用struct时都会更改,并且在读取函数返回后可能会完全不存在。

以下是一些示例代码:

fgets()

当使用以下数据文件运行时:

#define _POSIX_C_SOURCE 200809L

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define BUFFER_SIZE 256

struct stock_item {
    int number;
    char * product;
    int price;
    char * other;
};

struct stock_item * stock_item_new(const int num_items,
                                   const char * stock_code,
                                   const int price,
                                   const char * other);
void stock_item_destroy(struct stock_item * item);
void stock_item_print(struct stock_item * item);

int main(void)
{
    FILE * fp = fopen("data.txt", "r");
    if ( !fp ) {
        perror("couldn't open data file");
        return EXIT_FAILURE;
    }

    char buffer[BUFFER_SIZE];
    const char * delim = " ,\n";
    while ( fgets(buffer, BUFFER_SIZE, fp) ) {
        int num_items = atoi(strtok(buffer, delim));
        char * stock_code = strtok(NULL, delim);
        int price = atoi(strtok(NULL, delim));
        char * other = strtok(NULL, delim);

        struct stock_item * new_item;
        new_item = stock_item_new(num_items, stock_code, price, other);

        stock_item_print(new_item);

        stock_item_destroy(new_item);
    }

    fclose(fp);

    return 0;
}

struct stock_item * stock_item_new(const int num_items,
                                   const char * stock_code,
                                   const int price,
                                   const char * other)
{
    struct stock_item * new_item = malloc(sizeof *new_item);
    if ( !new_item ) {
        perror("couldn't allocate memory for stock item");
        exit(EXIT_FAILURE);
    }

    new_item->number = num_items;
    new_item->price = price;

    new_item->product = strdup(stock_code);
    if ( !new_item->product ) {
        perror("couldn't allocate memory for product name");
        exit(EXIT_FAILURE);
    }

    if ( other ) {
        new_item->other = strdup(other);
        if ( !new_item->other ) {
            perror("couldn't allocate memory for 'other' field");
            exit(EXIT_FAILURE);
        }
    }
    else {
        new_item->other = NULL;
    }

    return new_item;
}

void stock_item_destroy(struct stock_item * item)
{
    free(item->product);
    free(item->other);
    free(item);
}

void stock_item_print(struct stock_item * item)
{
    printf("%d, %s, %d, %s\n", item->number, item->product,
            item->price, item->other ? item->other : "(none)");
}

产生以下输出:

paul@horus:~/src/sandbox/itemfile$ cat data.txt
20, rifle, 99
33, bucket, 30, plastic
50, fish, 5, gold
12, hammer, 45, left-handed
9, backscratcher, 13
paul@horus:~/src/sandbox/itemfile$ 

paul@horus:~/src/sandbox/itemfile$ ./itemfile 20, rifle, 99, (none) 33, bucket, 30, plastic 50, fish, 5, gold 12, hammer, 45, left-handed 9, backscratcher, 13, (none) paul@horus:~/src/sandbox/itemfile$ 函数会检查stock_item_print()字段是否为other,如果是,则输出NULL。否则它会正常打印。

另请注意,将"(none)"传递给NULL即可,因此我们无需检查free()函数中的other字段。

最后,我还没有对其进行任何更改(除了将stock_item_destroy()添加到分隔符列表中),但是使用'\n'的解析代码非常脆弱,应该进行扩展包括更多的错误检查。例如,strtok()优于strtol(),您应该每次都检查atoi()是否返回strtok()