好的,我知道如何将值放入文件的结构中。
我在文件中的值与我的逗号分开。数据是这样的:
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吗?
答案 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()
。