C 将值从文件放入结构中
好的,我知道如何将值从文件放入结构中 文件中的值与逗号分开。数据如下:C 将值从文件放入结构中,c,struct,C,Struct,好的,我知道如何将值从文件放入结构中 文件中的值与逗号分开。数据如下: number, product, price, other 只有某些项目具有其他值 如何在结构中具有可选值 例如: typedef struct stockItem { int number; char* product; int price; char *other; } stockItem; while (fgets(str, 255, invf) != NULL){ i
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);
我输入的数据如下:
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吗?是的,对于每个没有该字段的项,应该将
other
设置为null
。这是表示没有指向某个对象的正常方式
另外,strtok()
将返回一个指向str
的内部指针,您可以对每个项目重复使用该指针。您应该确保stockItem_new()
函数实际上是在复制该数据(使用strdup()
或strcpy()
),而不仅仅是将该字段设置为指针,否则所有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$ ./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\u item\u print()
函数检查other
字段是否为NULL
,如果为空,则输出(无)
。否则它会正常打印
还要注意,将NULL
传递到free()
是可以的,因此我们不必检查stock\u item\u destroy()函数中的other
字段
最后,我没有对它做任何更改(除了在分隔符列表中添加'\n'
),但是您使用strtok()
解析代码非常脆弱,应该扩展以包含更多的错误检查。例如,strtol()
优于atoi()
,每次strtok()
返回NULL是的,对于没有该字段的每个项目,都应该将other
设置为NULL
。这是表示没有指向某个对象的正常方式
另外,strtok()
将返回一个指向str
的内部指针,您可以对每个项目重复使用该指针。您应该确保stockItem_new()
函数实际上是在复制该数据(使用strdup()
或strcpy()
),而不仅仅是将该字段设置为指针,否则所有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$ ./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\u item\u print()
函数检查other
字段是否为NULL
,如果为空,则输出(无)
。否则它会正常打印
还要注意,将NULL
传递到free()
是可以的,因此我们不必检查stock\u item\u destroy()函数中的other
字段
最后,我没有对它做任何更改(除了在分隔符列表中添加'\n'
),但是您使用strtok()
解析代码非常脆弱,应该扩展以包含更多的错误检查。例如,strtol()
比atoi()
好,每次你都应该检查strtok()
是否返回NULL
我已经确保在stockItem_new()中使用了strdup,所以在我的结构中,我是将值更改为NULL还是在循环中执行?最简单的方法是在循环中执行。然后stockItem\u new()
可以检查传递给它的other
的值是否为NULL
。如果是,它可以将该字段设置为NULL
。如果不是,那么它可以复制它,就像使用stockCode
一样。因此,如果我在循环中执行此操作,我是否必须在每次循环后将其设置为NULL,否则该值将无法继续执行?@blarssss:请稍等,我会写出一些代码。我已确保在stockItem_new()中使用了strdup,所以在我的结构中,我会将值更改为NULL还是在循环中执行?最简单的方法是在循环中执行。然后stockItem\u new()
可以检查传递给它的other
的值是否为NULL
。如果是,它可以将该字段设置为NULL
。如果不是,那么它可以复制它,就像stockCode
一样。因此,如果我在循环中执行此操作,我是否必须在每次循环后将其设置为NULL,否则该值不会继续执行?@blarssss:请稍等,我会写出一些代码。