如何使用 fgets() 读取 C 语言中文件的内容并将其存储到数组中?

How do I read the contents of a file in C and store it into an array using fgets()?

提问人:McLovinIt 提问时间:9/27/2017 更新时间:9/27/2017 访问量:4272

问:

因此,我需要创建一个单词搜索程序,该程序将读取包含字母的数据文件,然后在最后需要找到的单词 例如:

f a q e g g e e e f


o e q e r t e w j o


t e e w q e r t y u


政府


自由

字母和单词的列表更长,但无论如何我需要将字母保存到数组中,我遇到了困难,因为它从不存储正确的数据。这是我到目前为止所拥有的

#include <stdio.h>

int main()
{
int value;
char letters[500];

while(!feof(stdin))
{
   value = fgets(stdin);

   for(int i =0; i < value; i++)
   {
      scanf("%1s", &letters[i]);
   }

   for(int i=0; i<1; i++)
   {
      printf("%1c", letters[i]);
   }
}
}

我也不知道在将字符放入数组后,如何将单词存储到单独的数组中。

C 数组 stdin fgets feof

评论

1赞 Iwillnotexist Idonotexist 9/27/2017
请注意,这并没有说明您是否在文件末尾;它说你是否遇到过EOF。它可能正好位于文件的末尾,但没有尝试越过它,在这种情况下,将返回,直到您尝试再读取一个字节(并失败)。feof()feof()0
1赞 Basile Starynkevitch 9/27/2017
考虑像这里这样使用getline
1赞 ryyker 9/27/2017
文件中是否有符号或字符串可以使您的代码区分字母的结束位置和单词的开始位置?

答:

1赞 atru 9/27/2017 #1

用字符或单词存储行的一种方法是将它们存储在指向数组的指针数组中 - 行,

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

#define MAXLET 500
#define MAXLINES 1000

int main()
{
    char *lptr;
    // Array with letters from a given line
    char letters[MAXLET];
    // Array with pointers to lines with letters
    char *lineptr[MAXLINES];

    // Length of current array
    unsigned len = 0;
    // Total number of lines
    int nlines = 0;

    // Read lines from stdin and store them in 
    // an array of pointers
    while((fgets(letters,MAXLET,stdin))!=NULL)
    {
        len = strlen(letters);
        letters[len-1] = '\0';
        lptr = (char*) malloc(len);
        strcpy(lptr, letters);
        lineptr[nlines++]=lptr;
    }

    // Print lines
    for (int i = 0; i < nlines; i++)
        printf("%s\n", lineptr[i]);

    // Free allocated memory
    for (int i = 0; i < nlines; i++)
        free(lineptr[i]);
}

在下文中,指向 中的每一行的指针都存储在 中。存储后,您可以访问和操作每一行 - 在这个简单的情况下,我只将它们一一打印,但稍后将显示简单操作的示例。最后,程序释放先前分配的内存。最好在分配的内存不再使用后释放它。stdinlineptr

存储一行的过程包括从 中获取每一行,收集它的长度 ,通过将其替换为 (可选) 来剥离它的字符,用 为其分配内存,最后将指向该内存位置的指针存储在 中。在此过程中,程序还会计算输入行数。stdinstrlennewline\0malloclineptr

您可以为两个输入(chars 和 words)实现此序列。这将产生一个干净的、随时可用的输入。还可以考虑将行集合移动到函数中,这可能需要将类型数组设置为全局。如果您有任何问题,请告诉我。lineptr

要记住的是,对于给定的数据集,尤其是可能必须增加(从字面上看,假设您不会超过 1000 行)。MAXLETMAXLINESMAXLINES 1000

此外,在 Unix 和 Mac 上,该程序允许您按原样读取文件,使用它可以很容易地修改为直接从文件中读取。$ prog_name < in_file

以下是一些用法示例 - 存储指向每行(数组)的指针,因此程序首先检索指向一行的指针,然后像任何数组一样继续:lineptr

// Print 3rd character of each line
// then substitute 2nd with 'a'
char *p;
for (int i = 0; i < nlines; i++){
    p = lineptr[i];
    printf("%c\n", p[2]);
    p[1] = 'a';
}

// Print lines
for (int i = 0; i < nlines; i++)
    printf("%s\n", lineptr[i]);

// Swap first and second element
// of each line
char tmp;
for (int i = 0; i < nlines; i++){
    p = lineptr[i];
    tmp = p[0];
    p[0] = p[1];
    p[1] = tmp;
}

// Print lines
for (int i = 0; i < nlines; i++)
    printf("%s\n", lineptr[i]);

请注意,这些示例只是一个演示,并假设每行至少有 3 个字符。此外,在您的原始输入中,字符由空格分隔 - 这不是必需的,事实上没有空格会更容易。

0赞 Serge Ballesta 9/27/2017 #2

value = fgets(stdin);是一个可怕的表情!你根本不尊重函数的语法。我的手册页显示fgets

char * fgets(char * restrict str, int size, FILE * restrict stream);

因此,在这里,由于您没有在正确的位置传递流,因此您可能会收到一个底层 io 错误,并且 fgets returns ,该错误被转换为 0 值。然后下一个循环只是一个无操作。NULLint

读取带有 fgets 的行的正确方法是:

if (NULL == fgets(letters, sizeof(letters), stdin) {
    // indication of end of file or error
    ...
}
// Ok letters contains the line...
2赞 J...S 9/27/2017 #3

您说要从数据文件中读取数据。如果是这样,您应该打开该文件。

FILE *fin=fopen("filename.txt", "r");
if(fin==NULL)
{
    perror("filename.txt not opened.");
}

在输入文件中,前几行由单个字母组成,每个字母由空格分隔。

如果要将这些字母中的每一个存储到字符数组中,可以使用以下循环加载每行。letters

char c;
int i=0;
while(fscanf(fin, "%c", &c)==1 && c!='\n')
{
    if(c!=' ')
    {
        letters[i++]=c;
    }
}

这将只存储字母,而不是字符串,因为没有字符。\0

阅读底部的单词可以用 .fgets()

您对该函数的使用是错误的。fgets()

它的原型是

char *fgets(char *str, int n, FILE *stream);

看这里

请注意,也会将尾随的 newline() 存储到字符串中。您可能希望将其删除,例如fgets()\n

str[strlen(str)-1]='\0';

用于将底部的单词读入字符数组,并将 替换为 .fgets()\n\0

并做

fgets(letters, sizeof(letters, fin);

当您想要接受来自键盘的输入并存储到 .stdinfinletters

请注意,也会将尾随的 newline() 存储到 。您可能希望将其删除,例如fgets()\nletters

letters[strlen(letters)-1]='\0';


只是说,将是一个字符而不是字符串。letters[i]

scanf("%1s", &letters[i]);

应该是

scanf("%c", &letters[i]);
1赞 ryyker 9/27/2017 #4

您帖子中的代码似乎与您声明的目标不符,表明您尚未掌握您正在使用的功能的正确应用。
你已经表达了一个想法,描述了你想做什么,但你所采取的步骤(至少是那些显示的步骤)不会让你到达那里。甚至没有接近。

手头有一张地图来计划计划你的步骤总是好的。算法是一种软件地图。但是,在你计划你的步骤之前,你需要知道你要去哪里。

您的既定目标:

1) Open and read a file into lines.    
2) Store the lines, somehow. (using fgets(,,)?)     
3) Use some lines as content to search though.  
4) Use other lines as objects to search for  

需要回答的一些问题:

a) 如何将搜索内容与要搜索的字符串区分开来 为?
b) 如何存储搜索内容?
c) 如何存储搜索词?
d) 如何进行内容和搜索词之间的比较?
e) 文件中有多少行?(示例
f) 最长线的长度?(讨论和示例)(e&f用于创建存储)
g) 如何使用 fgets()。(也许是谷歌搜索:如何使用 fgets
h) 使用 feof() 时需要注意什么?(讨论和审查
i) 为什么在第二次调用 scanf 后我的输入不正确?(回答
)

完成目标中项目的识别和具体化,然后回答这些(也许还有其他)问题。在这一点上,您将准备好开始确定到达那里的步骤。