将文本文件读入 2 个独立的字符数组(C 语言)

发布于 2024-10-18 03:39:26 字数 1946 浏览 2 评论 0原文

对于一堂课,我必须编写一个程序来读取以下格式的文本文件:


TAEDQ Q
ZHPNI U
CKEWD I
VUXOF C
BPIRG K
NRTBR B
退出

快速
棕色
FOX


我试图将字符放入字符数组中,每一行都是它自己的数组。 我可以从文件中读取数据,这是我用来解析文件的代码:


char** getLinesInFile(char *filepath)  
{  
    FILE *file;  
    const char mode = 'r';  
    file = fopen(filepath, &mode);  
    char **textInFile;  

    /* Reads the number of lines in the file. */
    int numLines = 0;
    char charRead = fgetc(file);
    while (charRead != EOF)
    {
        if(charRead == '\n' || charRead == '\r')
        {
            numLines++;
        }
        charRead = fgetc(file);
    }

    fseek(file, 0L, SEEK_SET);
    textInFile = (char**) malloc(sizeof(char*) * numLines);

    /* Sizes the array of text lines. */
    int line = 0;
    int numChars = 1;
    charRead = fgetc(file);
    while (charRead != EOF)
    {
        if(charRead == '\n' || charRead == '\r')
        {
            textInFile[line] = (char*) malloc(sizeof(char) * numChars);
            line++;
            numChars = 0;
        }
        else if(charRead != ' ')
        {
            numChars++;
        }
        charRead = fgetc(file);
    }

    /* Fill the array with the characters */
    fseek(file, 0L, SEEK_SET);
    charRead = fgetc(file);
    line = 0;
    int charNumber = 0;
    while (charRead != EOF)
    {
        if(charRead == '\n' || charRead == '\r')
        {
            line++;
            charNumber = 0;
        }
        else if(charRead != ' ')
        {
            textInFile[line][charNumber] = charRead;
            charNumber++;
        }
        charRead = fgetc(file);
    }

    return textInFile;
}

这是我的程序的运行:


欢迎使用 Word 搜索!

输入您希望我们解析的文件:testFile.txt TAEDQQ!ZHPNIU!CKEWDI!VUXOFC!BPIRGK!NRTBRB!退出!THE!QUICK!BROWN!FOX 分段错误


这是怎么回事? A)为什么会有感叹号,B)为什么最后会出现段错误?我在 main 中做的最后一件事是迭代数组/指针。

For a class I have to write a program to read in a text file in the format of:


T A E D Q Q
Z H P N I U
C K E W D I
V U X O F C
B P I R G K
N R T B R B
EXIT
THE
QUICK
BROWN
FOX


I'm trying to get the characters into an array of chars, each line being its own array.
I'm able to read from the file okay, and this is the code I use to parse the file:


char** getLinesInFile(char *filepath)  
{  
    FILE *file;  
    const char mode = 'r';  
    file = fopen(filepath, &mode);  
    char **textInFile;  

    /* Reads the number of lines in the file. */
    int numLines = 0;
    char charRead = fgetc(file);
    while (charRead != EOF)
    {
        if(charRead == '\n' || charRead == '\r')
        {
            numLines++;
        }
        charRead = fgetc(file);
    }

    fseek(file, 0L, SEEK_SET);
    textInFile = (char**) malloc(sizeof(char*) * numLines);

    /* Sizes the array of text lines. */
    int line = 0;
    int numChars = 1;
    charRead = fgetc(file);
    while (charRead != EOF)
    {
        if(charRead == '\n' || charRead == '\r')
        {
            textInFile[line] = (char*) malloc(sizeof(char) * numChars);
            line++;
            numChars = 0;
        }
        else if(charRead != ' ')
        {
            numChars++;
        }
        charRead = fgetc(file);
    }

    /* Fill the array with the characters */
    fseek(file, 0L, SEEK_SET);
    charRead = fgetc(file);
    line = 0;
    int charNumber = 0;
    while (charRead != EOF)
    {
        if(charRead == '\n' || charRead == '\r')
        {
            line++;
            charNumber = 0;
        }
        else if(charRead != ' ')
        {
            textInFile[line][charNumber] = charRead;
            charNumber++;
        }
        charRead = fgetc(file);
    }

    return textInFile;
}

This is a run of my program:


Welcome to Word search!

Enter the file you would like us to parse:testFile.txt
TAEDQQ!ZHPNIU!CKEWDI!VUXOFC!BPIRGK!NRTBRB!EXIT!THE!QUICK!BROWN!FOX
Segmentation fault


What's going on? A), why are the exclamation marks there, and B) why do I get a seg fault at the end? The last thing I do in the main is iterate through the array/pointers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

翻了热茶 2024-10-25 03:39:26

1)在程序的第一部分中,您错误地计算了文件中的行数。文件中的实际行数是 11 行,但您的程序得到 10 行。您需要从 1 开始计数,因为文件中始终至少有一行。因此更改

int numLines = 0;

int numLines = 1;

2) 在程序的第二部分中,您错误地计算了每行的字符数。您需要保持计数器初始化相同。在段的开头,您将 numChars 初始化为 1。在这种情况下,您需要在每次迭代后将计数器重置为 1,因此更改:

numChars = 0;

numChars = 1;

这应该为所有非空格字符和结束 NULL 终止符提供足够的空间。请记住,在 C 中,char* 字符串始终以 NULL 结尾。

3) 你的程序也没有考虑行终止符的差异,但在我的测试环境下这不是问题——fgetc 只返回一个字符作为行终止符,即使文件是用 \r\n 终止符保存的。

4)在程序的第二部分中,您也没有为最后一行分配内存。当您尝试访问未分配的空间时,这会导致程序的第三部分出现段错误。

请注意您的代码如何仅保存以 \r 或 \n 结尾的行。你猜怎么着,从技术上讲,EOF 是最后一行的结束行,它不符合条件。所以你的第二个循环不会将最后一行保存到数组中。

要解决此问题,请在第二部分之后添加以下内容:
textInFile[line] = (char*) malloc(sizeof(char) * numChars);

4)在程序输出中,您会看到那些奇怪的感叹号,因为您没有以 NULL 终止字符串。因此,您需要在下面添加标记为 NULL 终止的行:

if(charRead == '\n' || charRead == '\r')
{
    textInFile[line][charNumber] = 0; // NULL termination
    line++;
    charNumber = 0;
}

5) 因为您正在检查 EOF,所以您在第三个循环中遇到相同的问题,因此您必须在 return 之前添加此行

textInFile[line][charNumber] = 0; // NULL termination

6) 我也遇到一些头痛,因为整个程序结构。您将同一个文件一个字符一个字符地读取了 3 次!这是极其缓慢且低效的。

固定代码如下:

char** getLinesInFile(char *filepath)  
{  
    FILE *file;  
    const char mode = 'r';  
    file = fopen(filepath, &mode);  
    char **textInFile;

    /* Reads the number of lines in the file. */
    int numLines = 1;
    char charRead = fgetc(file);
    while (charRead != EOF)
    {
        if(charRead == '\n' || charRead == '\r')
        {
            numLines++;
        }
        charRead = fgetc(file);
    }

    fseek(file, 0L, SEEK_SET);
    textInFile = (char**) malloc(sizeof(char*) * numLines);

    /* Sizes the array of text lines. */
    int line = 0;
    int numChars = 1;
    charRead = fgetc(file);
    while (charRead != EOF)
    {
        if(charRead == '\n' || charRead == '\r')
        {
            textInFile[line] = (char*) malloc(sizeof(char) * numChars);
            line++;
            numChars = 1;
        }
        else if(charRead != ' ')
        {
            numChars++;
        }
        charRead = fgetc(file);
    }
textInFile[line] = (char*) malloc(sizeof(char) * numChars);

    /* Fill the array with the characters */
    fseek(file, 0L, SEEK_SET);
    charRead = fgetc(file);
    line = 0;
    int charNumber = 0;
    while (charRead != EOF)
    {
        if(charRead == '\n' || charRead == '\r')
        {
            textInFile[line][charNumber] = 0; // NULL termination
            line++;
            charNumber = 0;
        }
        else if(charRead != ' ')
        {
            textInFile[line][charNumber] = charRead;
            charNumber++;
        }
        charRead = fgetc(file);
    }
    textInFile[line][charNumber] = 0; // NULL termination

    return textInFile;
}

1) In the first part of your program, you are miscounting the number of lines in the file. The actual number of lines in the file is 11, but your program gets 10. You need to start counting from 1, as there will always be at least one line in the file. So change

int numLines = 0;

to

int numLines = 1;

2) In the second part of the program you are miscounting the number of characters on each line. You need to keep your counter initializations the same. At the start of the segment you initialize numChars to 1. In that case you need to reset your counter to 1 after each iteration, so change:

numChars = 0;

to

numChars = 1;

This should provide enough space for all the non-space characters and for the ending NULL terminator. Keep in mind that in C char* strings are always NULL terminated.

3) Your program also does not account for differences in line termination, but under my test environment that is not a problem -- fgetc returns only one character for the line terminator, even though the file is saved with \r\n terminators.

4) In the second part of your program, you are also not allocating memory for the very last line. This causes your segfault in the third part of your program when you try to access the unallocated space.

Note how your code only saves lines if they end in \r or \n. Guess what, EOF which technically is the line ending for the last line does not qualify. So your second loop does not save the last line into the array.

To fix this, add this after the second part:
textInFile[line] = (char*) malloc(sizeof(char) * numChars);

4) In your program output you are seeing those weird exclamation points because you are not NULL terminating your strings. So you need to add the line marked as NULL termination below:

if(charRead == '\n' || charRead == '\r')
{
    textInFile[line][charNumber] = 0; // NULL termination
    line++;
    charNumber = 0;
}

5) Because you are checking for EOF, you have the same problem in your third loop, so you must add this before the return

textInFile[line][charNumber] = 0; // NULL termination

6) I am also getting some headaches because of the whole program structure. You read the same file character by character 3 times! This is extremely slow and inefficient.

Fixed code follows below:

char** getLinesInFile(char *filepath)  
{  
    FILE *file;  
    const char mode = 'r';  
    file = fopen(filepath, &mode);  
    char **textInFile;

    /* Reads the number of lines in the file. */
    int numLines = 1;
    char charRead = fgetc(file);
    while (charRead != EOF)
    {
        if(charRead == '\n' || charRead == '\r')
        {
            numLines++;
        }
        charRead = fgetc(file);
    }

    fseek(file, 0L, SEEK_SET);
    textInFile = (char**) malloc(sizeof(char*) * numLines);

    /* Sizes the array of text lines. */
    int line = 0;
    int numChars = 1;
    charRead = fgetc(file);
    while (charRead != EOF)
    {
        if(charRead == '\n' || charRead == '\r')
        {
            textInFile[line] = (char*) malloc(sizeof(char) * numChars);
            line++;
            numChars = 1;
        }
        else if(charRead != ' ')
        {
            numChars++;
        }
        charRead = fgetc(file);
    }
textInFile[line] = (char*) malloc(sizeof(char) * numChars);

    /* Fill the array with the characters */
    fseek(file, 0L, SEEK_SET);
    charRead = fgetc(file);
    line = 0;
    int charNumber = 0;
    while (charRead != EOF)
    {
        if(charRead == '\n' || charRead == '\r')
        {
            textInFile[line][charNumber] = 0; // NULL termination
            line++;
            charNumber = 0;
        }
        else if(charRead != ' ')
        {
            textInFile[line][charNumber] = charRead;
            charNumber++;
        }
        charRead = fgetc(file);
    }
    textInFile[line][charNumber] = 0; // NULL termination

    return textInFile;
}
毁我热情 2024-10-25 03:39:26

你的数组不是 null 终止的。这或许可以解释这两个问题。请务必为空终止符分配一个额外的字符。

You aren't null terminating your arrays. This probably explains both problems. Be sure to allocate an extra character for the null terminator.

土豪 2024-10-25 03:39:26

这样做:

if(charRead == '\n')
    {
        textInFile[line] = (char*) malloc(sizeof(char) * (numChars+1));
        line++;
        numChars = 0;
    }

然后:

 if(charRead == '\n')
    {
        textInFile[line][charNumber]='\0';
        line++;
        charNumber = 0;
    }

您还将读取该文件 3 次! 这个帖子很好地解释了如何有效地读取文件。

Do This:

if(charRead == '\n')
    {
        textInFile[line] = (char*) malloc(sizeof(char) * (numChars+1));
        line++;
        numChars = 0;
    }

Then:

 if(charRead == '\n')
    {
        textInFile[line][charNumber]='\0';
        line++;
        charNumber = 0;
    }

Also you are reading the file 3 times! This thread has some good explanation on how to read a file efficiently.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文