【问题标题】:Reading a text file into 2 separate arrays of characters (in C)将文本文件读入 2 个单独的字符数组(在 C 中)
【发布时间】:2011-02-16 20:20:12
【问题描述】:

对于一个类,我必须编写一个程序来读取文本文件,格式为:


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
退出

快速
棕色
狐狸


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


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)为什么最后会出现段错误?我主要做的最后一件事是遍历数组/指针。

【问题讨论】:

  • 第一次读取文件只是为了调整数组的大小是一种非常低效的方法。也许您可以使用一种不需要您事先知道需要放入多少数据的数据结构? (提示)
  • 嗯,这是 C 类的介绍。我们只介绍了指针/数组/其他简单的东西。我更喜欢使用更好的数据结构,但我不知道我的选择是什么(我不确定是否会受到鼓励——我认为我们应该只用简单的操作来完成这个程序)。 :\
  • 请注意,由于文件使用的是\r\n,因此您目前正在对使用 dos 样式行尾的文件重复计算行数。

标签: c file pointers segmentation-fault


【解决方案1】:

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;
}

【讨论】:

  • 非常感谢。
  • 您应该学习如何调试您的代码,以便您的程序按预期工作。这就是我在这里所做的。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    这样做:

    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 次! This 线程对如何有效地读取文件有一些很好的解释。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-08
      • 2016-01-06
      • 1970-01-01
      相关资源
      最近更新 更多