【问题标题】:how to read each word in a string from a textfile如何从文本文件中读取字符串中的每个单词
【发布时间】:2016-02-12 23:59:55
【问题描述】:

我的代码如下图:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    FILE *fp = fopen("text.txt", "r");
    char c;
    int d = 0;
    char arr[2000];

    do {
        c = fgetc(fp);
        d = d + 1;

        if (c == '\n') {
            arr[d] = ' ';
        } else
            arr[d] = c;
    } while (c != EOF);

    int z = strlen(arr);
    arr[0]= '\0';

    for (int i = 0;i < z; i++) {
        arr[i] = arr[i +1];
    }

    fclose(fp);

    return 0;
}

代码从文本文件中读取一个字符串并将它们发送到数组 arr[2000](文本文件中有很多单词)。我想问是否有人知道代码通过空格而不是字符分隔的每个单词读取文本文件的方法。

例如,如果我有一个带有字符串的数组 arr:“Jack 是男孩”

arr[0] 将等于“Jack”而不是“J”

p.s(末尾的for循环删除索引0的原因是因为我一直在数组的开头得到一个“(”字符)

任何帮助将不胜感激。

【问题讨论】:

  • 您可能需要确保您阅读的字符不是EOF在使用之前。也许像while ((c = fgetc(fp)) != EOF) { ... } 那样做。
  • 哦,字符串终止符应该是 last 字符,没有它,strlen 之类的字符串函数将不起作用,您将得到 未定义的行为 i>.
  • 另外,你存储的第一个字符应该是arr[0],所以你应该在分配给arr[d]之后而不是之前增加你的索引d
  • 如上所述,您需要将d = d + 1; 移动到您的if 测试下方(或者在if 测试中使用例如arr[d++] = ' ';)。也无需调用strlen 来进行空终止。 d 已经保存了下一个字符的索引,所以只需 arr[d] = 0;
  • char c; --> int c;

标签: c


【解决方案1】:

你说:

例如,如果我有一个带有字符串的数组 arr:"Jack is a boy"

arr[0] 等于 "Jack" 而不是 "J"

为此,arr[0] 需要是一个指向空终止字符串的指针。这意味着,arr 必须是指针数组,而不是 chars 数组。

char* arr[SOME_SIZE] = {0}; // Make SOME_SIZE large enough for your needs.

现在您必须弄清楚从文件中读取的字符的存储位置。您可以使用Easiest way to get file's contents in C 中使用的方法来读取文件的全部内容。假设你有读取文件内容的代码,那么你有:

char* fileContents = readFileContents("text.txt");

现在,fileContents 指向一个如下所示的数组:

+---+---+---+---+---+---+---+---+---+---+---+---+---+----+
| J | a | c | k |   | i | s |   | a |   | b | o | y | \0 |
+---+---+---+---+---+---+---+---+---+---+---+---+---+----+

现在,您需要遍历该数组并确保:

  1. arr[0] - arr[3] 指向数组中的正确位置。
  2. 空白字符被空字符替换,以便arr[0] - arr[3] 指向以空字符结尾的字符串。
arr[0]              arr[1]       arr[2]   arr[3]
|                    |            |        |
v                    v            v        v
+---+---+---+---+----+---+---+----+---+----+---+---+---+----+
| J | a | c | k | \0 | i | s | \0 | a | \0 | b | o | y | \0 |
+---+---+---+---+----+---+---+----+---+-- -+---+---+---+----+

我希望能给你足够的信息来实现你需要的功能。

【讨论】:

    【解决方案2】:

    您在开始时获得了额外的字符,因为您开始在 arr[1] 填充您的数组。

    此外,您还可以使用 fread 函数让生活更轻松: size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); 一次阅读整个文本块。 然后,您可以在闲暇时将其分成单词。

    现在,如果您还想拥有一个“包含”所有单独单词的数组,您应该查看array of pointers to charchar *array[100](当然是适当的大小)。 C 不会自动处理字符串(正如您从问题的最后一点所期望的那样“arr[0] 将等于“Jack”而不是“J””。

    【讨论】:

    • 我会谨慎建议学习用户使用fread 而不是基本的fgetc。虽然建议其他可用功能很好,但更重要的是帮助他们理解如何正确地做他们首先有疑问的事情。一次freading 整个文件更快,mmaping 文件也是如此,但两者都不会帮助 OP 正确使用fgetc
    【解决方案3】:

    您还需要关注三个额外的微妙问题:

    int c = 0;  /* note: 'c' should be 'int' */
    

    虽然char 适用于普通字符,但如果您尝试读取包含多字节字符的文件,则会遇到问题。

    当您使用fopen 打开文件时,您需要在尝试读取文件之前检查该文件是否真的打开。只需要一个简单的测试:

    if (!fp) {  /* validate file open succeeded */
        fprintf (stderr, "error: file open failed 'text.txt'.\n");
        return 1;
    }
    

    (注意:if (!fp) 只是 if (fp == NULL) 的简写)

    接下来是你读取c的方式,赋值给array,然后测试是否c = EOF。当cEOF 时,什么会添加到数组中?

    在将c 分配给arr 之前,您需要测试是否c = EOF,而不是在EOF(即-1 generally)的情况下分配它。快速更改循环即可:

    /* test c before you add it to the array */
    while ((c = fgetc (fp)) != EOF)
    {
        if (c == '\n') {
            arr[d++] = ' ';
        } else
            arr[d++] = c;
    }
    arr[d] = 0; /* null-terminate, note '\0' = 0 */
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-04-12
      • 1970-01-01
      • 1970-01-01
      • 2017-09-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-07
      相关资源
      最近更新 更多