提问人:Educg550 提问时间:12/16/2022 更新时间:12/16/2022 访问量:62
如何从 C 中的文件中获取使用“getline”获取缓冲区中的每个字符串
How to get each string within a buffer fetched with "getline" from a file in C
问:
我正在尝试从文件中文本的每一行中读取用逗号、点或空格分隔的每个字符串(为了简单起见,我只是接收字母数字字符)。我正在使用库中的函数,它可以很好地读取该行。但是当我尝试“迭代”使用它获取的缓冲区时,它总是返回从文件中读取的第一个字符串。假设我有一个名为“entry.txt”的文件,其中包含以下内容:scanf
getline
<stdio.h>
test1234 test hello
another test2
我的“main.c”包含以下内容:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_WORD 500
int main()
{
FILE *fp;
int currentLine = 1;
size_t characters, maxLine = MAX_WORD * 500;
/* Buffer can keep up to 500 words of 500 characters each */
char *word = (char *)malloc(MAX_WORD * sizeof(char)), *buffer = (char *)malloc((int)maxLine * sizeof(char));
fp = fopen("entry.txt", "r");
if (fp == NULL) {
return 1;
}
for (currentLine = 1; (characters = getline(&buffer, &maxLine, fp)) != -1; currentLine++)
{
/* This line gets "test1234" onto "word" variable, as expected */
sscanf(buffer, "%[a-zA-Z_0-9]", word);
printf("%s", word); // As expected
/* This line should get "test" string, but again it obtains "test1234" from the buffer */
sscanf(buffer, "%[a-zA-Z_0-9]", word);
printf("%s", word); // Not intended...
// Do some stuff with the "word" and "currentLine" variables...
}
return 0;
}
发生的情况是,我试图从缓冲区中按顺序获取每个字母数字字符串(即从现在开始的单词),而该函数只是给我指定缓冲区字符串中第一个单词的出现。此外,条目文件上的每一行都可以包含未知数量的单词,这些单词由空格、逗号、点、特殊字符等分隔。sscanf
我使用“getline”单独获取文件中的每一行,因为我需要从每行中获取每个单词,并使用“currentLine”变量将其存储在其他地方,这样我就知道给定的单词会来自哪一行。关于如何做到这一点的任何想法?
答:
fscanf
具有输入流参数。流可以更改其状态,以便第二次调用读取不同的内容。例如:fscanf
fscanf(stdin, "%s", str1); // str1 contains some string; stdin advances
fscanf(stdin, "%s", str2); // str2 contains some other sting
scanf
没有 stream 参数,但它有一个全局流可以使用,因此它的工作方式与 .fscanf(stdin, ...)
sscanf
没有 Stream 参数,也没有任何全局状态来跟踪读取的内容。有一个输入字符串。你扫描它,一些字符被转换,然后......其他什么都没有改变。字符串仍然是同一个字符串(否则怎么可能?),并且没有存储任何有关扫描进展程度的信息。
sscanf(buffer, "%s", str1); // str1 contains some string; nothing else changes
sscanf(buffer, "%s", str2); // str2 contains the same sting
那么一个可怜的程序员会做什么呢?
好吧,我撒谎了。只有在您不请求时,才会将有关扫描进展程度的信息存储在任何地方。
int nchars;
sscanf(buffer, "%s%n", str1, &nchars); // str1 contains some string;
// nchars contains number of characters consumed
sscanf(buffer+nchars, "%s", str2); // str2 contains some other string
为简洁起见,省略了错误处理和 %s
字段宽度。你永远不应该在实际代码中省略它们。
评论
/* This line should get "test" string, but again it obtains "test1234" from the buffer */
?!?!??为什么你认为第二次会产生不同的结果?sscanf(buffer, "%[a-zA-Z_0-9]", word);
sscanf(buffer, "%[a-zA-Z_0-9]", word);
sscanf(buffer, "%499[a-zA-Z_0-9]", word);
strtok()