我试图通过fscanf读取文件test.txt并将其存储在struct数组中。这是我试过的。这里的问题是fscanf
没有按预期工作。阅读完文件后,我也试图在屏幕上打印,但它不会工作。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Item {
double value;
int unit;
char name[50];
};
int load(struct Item* item, FILE* data);
void display(struct Item item, int variableA);
int main()
{
struct Item I;
int i;
char ck;
ck = fopen("test.txt", "r");
if (ck)
{
for (i = 0; i < 3; i++)
{
load(&I, ck);
display(I, 0); //DISPLAY FUNCTION THAT READS test.txt and DISPLAYS
}
fclose(ck);
}
return 0;
}
int load(struct Item* item, FILE* data)
{
fscanf(data, "%d,%.2lf,%s\n", &(*item).unit,&(*item).value,&(*item).name);
return 0;
}
void display(struct Item item, int variableA)
{
printf("|%3d |%12.2lf| %20s |***\n", item.unit, item.value, item.name);
return;
}
这是我在 test.txt文件中的内容:
205,11.20,John Snow
336,23.40,Winter is coming
220,34.20,You know nothing
错误:程序编译时会出现一些警告,但在执行代码时出现分段错误。
知道为什么吗?
输出期望:应从test.txt文件中读取OUTPUT,并将其显示在屏幕上。
答案 0 :(得分:3)
该计划存在多个问题:
1
char ck;
ck = fopen("test.txt", "r");
fopen
返回FILE*
,而不是char
,请使用
FILE* ck = fopen(...);
2
fscanf(data, "%d,%.2lf,%s\n", &(*item).unit,&(*item).value,&(*item).name);
始终检查fscanf
的返回值,如果它小于您请求的字段数,则对fscanf
的以下调用不太可能达到预期效果。此外,*item.unit
与item->unit
相同,请使用item->unit
因为它更短更清洁:
int ret = fscanf(data, "%d,%lf,", &item->unit, &item->value);
if (ret != 3) { // error }
第三,%s
匹配一系列非空白字符,因此当fscanf
读取&#34; John&#34;时,它将停止,下一个fscanf
电话将会阅读&#34; Snow&#34;期待一个整数。
因此,要输入带有空格的字符串,请改用fgets
,并记住最后删除换行符。
请尝试以下操作:
int main(void)
{
struct Item I;
int i;
FILE* ck;
int ret;
ck = fopen("test.txt", "r");
if (ck)
{
for (i = 0; i < 3; i++)
{
ret = load(&I, ck);
if (ret < 0)
break;
display(I, 0); //DISPLAY FUNCTION THAT READS test.txt and DISPLAYS
}
fclose(ck);
}
return 0;
}
int load(struct Item* item, FILE* data)
{
int ret = fscanf(data, "%d,%lf,", &item->unit, &item->value);
if (ret != 2) {
return -1;
}
fgets(item->name, sizeof item->name, data);
item->name[strlen(item->name)-1] = '\0';
return 0;
}
void display(struct Item item, int variableA)
{
printf("|%3d |%12.2lf| %20s |***\n", item.unit, item.value, item.name);
return;
}
输出:
$ ./a.out
|205 | 11.20| John Snow |***
|336 | 23.40| Winter is coming |***
|220 | 34.20| You know nothing |***
答案 1 :(得分:0)
您可以尝试这种不同的方法。
它使用:
malloc
,realloc
为结构数组分配和重新分配内存。我假设将使用更多更大行的文本文件,这允许数组在需要时调整大小以容纳更多信息。 strtok
解析,
分隔符之间的每个数据片段,然后将它们存储到结构数组中。fgets
将文件的每一行读入一个字符串,然后我们可以从中解析自己。 这是建议的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NAMESTRLEN 50
#define INITSIZE 3
#define MAXSIZE 100
typedef struct {
int unit;
double value;
char name[NAMESTRLEN+1];
} item_t;
typedef struct {
item_t *items;
int numlines;
} allitems_t;
allitems_t *initialize_arraystructs(void);
void print_arraystructs(allitems_t *allitems);
void read_insert_items(FILE *filestream, allitems_t *allitems);
void check_ptr(void *ptr, const char *msg);
int
main(void) {
allitems_t *allitems;
FILE *fp;
fp = fopen("test.txt", "r");
if (fp == NULL) {
fprintf(stderr, "%s\n", "Error reading file!\n");
exit(EXIT_FAILURE);
}
allitems = initialize_arraystructs();
read_insert_items(fp, allitems);
print_arraystructs(allitems);
return 0;
}
void
read_insert_items(FILE *filestream, allitems_t *allitems) {
int count = 0;
char line[MAXSIZE];
char *unit, *value, *name;
size_t numitems = INITSIZE;
allitems->items = malloc(numitems * sizeof(item_t));
check_ptr(allitems->items, "Initial Allocation");
while (fgets(line, MAXSIZE, filestream) != NULL) {
unit = strtok(line, ",");
value = strtok(NULL, ",");
name = strtok(NULL, "\n");
if (count == numitems) {
numitems *= 2;
allitems->items = realloc(allitems->items, numitems * sizeof(item_t));
check_ptr(allitems->items, "Reallocation");
}
allitems->items[count].unit = atoi(unit);
allitems->items[count].value = atof(value);
strcpy(allitems->items[count].name, name);
count++;
allitems->numlines++;
}
}
allitems_t
*initialize_arraystructs(void) {
allitems_t *allitems;
allitems = malloc(sizeof(allitems_t));
check_ptr(allitems, "Initial Allocation");
allitems->items = NULL;
allitems->numlines = 0;
return allitems;
}
void
print_arraystructs(allitems_t *allitems) {
int i;
for (i = 0; i < allitems->numlines; i++) {
printf("%d,%.2f,%s\n",
allitems->items[i].unit,
allitems->items[i].value,
allitems->items[i].name);
}
}
void
check_ptr(void *ptr, const char *msg) {
if (!ptr) {
printf("Unexpected null pointer: %s\n", msg);
exit(EXIT_FAILURE);
}
}