从stdin输入文件时无限读取输入

时间:2014-03-09 22:43:53

标签: c csv segmentation-fault

我想解析CSV文件中的信息并将其显示在我的屏幕上。我的问题是我一直在接收从我的while循环中转储的Segmentation fault core,这应该是将CSV文件信息存储到不同的数组中以表示CSV中的不同列。我的CSV中的样本行是大米,10,20,$ 2.00,表示食品,库存,再订购限制和每单位成本。

    char buffer[1024];
    char *line=buffer;
    FILE *file=fopen("inventory.csv", "rw");
    int x;
    int i=0;
    int j=0;
    char *food [100];
    int stock [100];
    double cost [100];
    int reorder [100];
    while (fgets(line, 2048, file) != NULL){
                            food[i] = (strtok(line, ","));
                            stock [i] = (atoi(strtok(NULL, ",")));
                            reorder[i] = (atoi(strtok(NULL, ",")));
                            cost[i] = (atof(strtok(NULL, ",")));
                            line=line+25;
                            i++;    }

4 个答案:

答案 0 :(得分:1)

首先,您的代码存在一个基本问题:您希望读取无限量的数据并将其存储到有限的空间中。

更多细节:

  • 你在每行之后继续前进25行,它指向大小为1024的缓冲区,所以在40行后你将在它结束后写。
  • 您的数组大小为100,因此在100行后,您将在结束后编写。

您是否需要存储您永远阅读的所有内容?

现在如果这不是问题,也可能是strtok找不到“,”并返回NULL,你应该在使用结果之前检查strtok的返回值。例如,如果您的文件以某些空行结束,或者只是在您读取的行的最后一个元素之后没有“,”,则可能会失败。

答案 1 :(得分:0)

我敢打赌,您正在尝试访问阵列中不存在的位置。尝试在程序崩溃前查看最后i值。

答案 2 :(得分:0)

请看下面的课程。你可以用

来调用它

的main.cpp

Stock line_stock;
file >> line_stock; //Use it in a loop cause it only reads a line

Stock.h

#include <iostream>
#include <string>

class Stock {
public:
private:
    std::string food;
    unsigned int stock;
    double cost; 
    unsigned int reorder;

    friend std::istream& operator >> (std::istream& is, Stock& s){
        char coma;
        is >> s.food >> coma>> 
                s.stock >> coma >> 
                s.cost >> coma >> 
                s.reorder;
        return is;
    }
};

// double在money上运行不正常,而是使用unsigned int。除以100得到美元和%100得到美分。

使用该类读取一行,然后处理它,然后你就到了下一行。

答案 3 :(得分:0)

当尝试读取具有未知数量的数据线的文件时,会想到两种方法:

1)逐行阅读并根据需要调整内存分配 2)解析文件两次。首先找到所需的长度。

健壮的程序通常使用方法#1。但#2对于学习者来说更简单。 #2如下。

FILE *file = fopen("inventory.csv", "rw");
// Test for file == NULL

char buffer[100];
size_t n = 0;
// Find number of lines
while (fgets(buffer, sizeof buffer, file) != NULL) 
  n++;

char *food    = malloc(n * sizeof *food);
int stock     = malloc(n * sizeof *stock);
double  *cost = malloc(n * sizeof *cost);
int *reorder  = malloc(n * sizeof *reorder);
// TBD: Add checks for failed malloc

rewind(file);
size_t i = 0;
for (i = 0; i<n; i++) {
  char name[sizeof buffer];
  if (fgets(buffer, sizeof buffer, file) != NULL) Handle_UnexpectedError();
  int cnt = sscanf(buffer, "%s ,%d ,%d , $%lf", 
      name, &stock[i], &reorder[i], &cost[i]);
  if (cnt != 4) Handle_FormatError();
  food[i] = strdup(name);
}
fclose(file);

// Use  food, stock, reorder, cost

// When done
for (i = 0; i<n; i++) {
  free(food[i]);
}
free(food); 
free(stock); 
free(reorder); 
free(cost);