一些代码读取.csv文件崩溃 [英] Some code of reading .csv file crashed

查看:164
本文介绍了一些代码读取.csv文件崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用代码来读取一个csv文件,并通过获取行和列来更改一个值。在第一次我读取文件来检查那里有多少行和列,而不是创建一个动态的2D数组 - 每行都是文件中的一行。实际上使文件在2D数组中。比我更改所选行和col的值,并将整个数组写回文件。有人知道为什么会崩溃?它在第一行崩溃 -

I tried make a code to read a csv file and change one value by getting line and column. In the first I read the file to check how many lines and cols up there, and than I create a dynamic 2D array- every line is the line on the file. actually make the file in 2D array. and than I will change the value of the chosen line and col and write the whole array back to the file. someone know why it's crashed? it's crashed in the first line of -


bigArr [i] [j] =(char)ch;

bigArr[i][j]=(char)ch;

功能:

int changeValue(int line, int col, char str[],const char* path)
{
    FILE* csvFile = fopen(path, "r");
    char arr[VERY_BIG_MEMORY];
    int l = 0, c = 1;
    int i = 0,j=0;
    int ch = 0;
    if (!csvFile)
    {
        printf("Cant read the file\nPlease open a file\n");
        return -1;
    }
    do
    {
        ch = fgetc(csvFile);
        if (ch == ',')
        {
            c++;
        }
    } while (ch !='\n');
    fseek(csvFile, 0L, SEEK_SET);
    do
    {
        ch = fgetc(csvFile);
        if (ch == '\n')
        {
            l++;
        }
    } while (ch!=EOF);
    char** bigArr = (char**)calloc(l*c,sizeof(char*));
    for (i = 0; i < l*c; i++)
    {
        bigArr[i] = (char*)calloc(10,sizeof(char));
    }
    fseek(csvFile, 0L, SEEK_SET);
    do
    {

        ch = fgetc(csvFile);
        if (ch == ',')
        {
            j++;
        }
        else if (ch == '\n')
        {
            i++;
        }
        else
        {
            bigArr[i][j]=(char)ch;
        }
    } while (ch != EOF);
}


推荐答案

崩溃的循环应该是更像:

The loop that's crashing should be more like:

enum { MAX_FIELD_WIDTH = 10 };  // Including null terminator

i = j = 0;
while ((ch = getc(csvFile)) != EOF)
{
    if (ch == ',' || ch == '\n')
    {
        bigArr[i++][j] = '\0';
        j = 0;
    }
    else
    {
        if (j < MAX_FIELD_WIDTH - 1)
            bigArr[i][j++] = ch;
        // else ignore excess characters
}

警告:未经测试的代码!

您的代码只是创建一个线性列表 l * c 字段值,这是罚款。您可以通过访问字段 bigArr [n * c] 通过选择行 n bigArr [n * c + c - 1] (从第0行开始计算)

Your code is simply creating a linear list of l * c field values, which is fine. You can pick the fields for line n by accessing fields bigArr[n * c] through bigArr[n * c + c - 1] (counting from line 0).

对于诸如 l c ,我使用较长的名称,如(或线)和 cols 。还不长,但更有意义。应该使用单个字符名称范围有限。

For important variables like l and c, I use longer names such as rows (or lines) and cols. Still not long, but more meaningful. Single character names should be used with limited scope.

请注意,此代码忽略CSV格式的细微之处,例如带有双引号内的逗号的字段,更不用说双引号中的换行符领域。它也忽略了行中不同数量字段的可能性。如果代码跟踪行号,则可以处理太多的字段(忽略额外的)和太少的字段(为缺少的字段创建空条目)。如果预扫描文件的代码更清晰,则可以保留每行最小和最大列数以及行数的记录。

Note that this code ignores subtleties of the CSV format such as fields with commas inside double quotes, let alone newlines within double quoted fields. It also ignores the possibility of varying numbers of fields in the lines. If the code kept track of line numbers, it would be possible to handle both too many fields (ignoring the extra) and too few fields (creating empty entries for missing fields). If the code that pre-scans the file was cleverer, it could keep a record of the minimum and maximum number of columns per line as well as the number of lines. Problems could then be diagnosed too.

使用更复杂的内存管理方案,也可以扫描文件一次,如果文件实际上具有优势,终端或管道,而不是磁盘文件。它也可以处理任意长的字段值,而不是将它们限制为10个字节,包括终端空字节。

With a more complex memory management scheme, it would also be possible to scan the file just once, which has advantages if the file is actually a terminal or pipe, rather than a disk file. It could also handle arbitrarily long field values instead of restricting them to 10 bytes including the terminal null byte.

代码应该检查文件是否可以打开,并在完成后将其关闭。当前的函数界面是:

The code should check that the file could be opened, and close it when it is finished. The current function interface is:

int changeValue(int line, int col, char str[], const char* path)

但显示的代码会忽略前三个值。这可能是因为最终的代码会更改读取的值之一,然后重写该文件。如果被要求更改不存在的列或行,则可能会报告错误。这些相对较小的意义可能是由于最小化以使代码类似于MCVE(如何创建最小,完整和可验证的示例? a>)。

but the first three values are ignored by the code shown. This is probably because the final code will change one of the values read and then rewrite the file. Presumably, it would report an error if asked to change a non-existent column or line. These relatively minor infelicities are probably due to the minimization to make the code resemble an MCVE (How to create a Minimal, Complete, and Verifiable Example?).

这篇关于一些代码读取.csv文件崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆