使用 fgets 和 strtok 从文件中的单行中检索单词
retrieving words from a single line in a file using fgets and strtok
我有下面的函数,它从文件中读取单词并使用 fgets 和 strtok 输出每个单词,其中文件中的单词用换行符分隔:
word1
word2
word3
我正在尝试模仿文件中的单词位于仅由 space:
分隔的一行的功能
word1 word2 word3
但是,我似乎只能在将 strtok 字符更改为“”并尝试读取一行时获得第一个单词。我不确定我错过了什么。
#include <string.h>
#include <malloc.h>
int readLines;
char *output[255];
char *filename = "commands.txt";
char fileRead(const char *filename, char *output[255])
{
int count = 0;
char input[255];
char *line;
FILE *file = fopen(filename, "r");
if (file == NULL) {
printf("Cannot open file: %s\n", filename);
} else {
while(count < 255 && fgets(input, sizeof(input), file)) {
line = strtok(input, "\n");
if (line) {
output[count++] = strdup(line); /* Store replica */
}
}
fclose(file);
}
return count;
}
char *strdup(const char *str)
{
char *ret = malloc(strlen(str)+1);
if (ret) {
strcpy(ret, str);
}
return ret;
}
int main(int argc, char *argv[])
{
readLines = fileRead(filename, output);
/* read from array and pass into flag function */
for (int x = 0; x < readLines; ++x) {
printf("%s\n", output[x]);
free(output[x]);
}
return 0;
}
如果我理解你的问题——你想要分隔文件中所有包含在一行中的单词 (tokens),那么你正在使用 strtok
错误。在您的代码中,您有 line = strtok(input, "\n");
,其中 delimiter 是 newline。如果你想分隔 space 分隔的单词,那么你还需要在分隔符中包含一个 space
,例如char *delim = " \n";
此外,在第一次调用 strtok
时,您使用缓冲区的变量名称(或指向缓冲区的指针)保存要标记化的文本。对于所有剩余的对 strtok
的调用(例如,对于单词 2, 3, 4...
),您使用 NULL
代替它并检查 return.
将您的示例简化,您可以执行以下操作:
#include <stdio.h>
#include <string.h>
#define MAXC 255
int main (int argc, char **argv) {
char buf[MAXC] = "",
*delim = " \n";
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
if (!fgets (buf, MAXC, fp)) { /* read one line from file */
fprintf (stderr, "error: file read failed.\n");
return 1;
}
/* tokenize line with strtok */
for (char *p = strtok (buf, delim); p; p = strtok (NULL, delim))
printf ("%s\n", p);
if (fp != stdin) fclose (fp); /* close file if not stdin */
return 0;
}
示例输入文件
$ cat dat/strtok.dat
my dog has fleas
例子Use/Output
$ ./bin/strtokoneline <dat/strtok.dat
my
dog
has
fleas
如果我误解了,请发表评论,我很乐意进一步提供帮助。如果您对答案还有其他疑问,请提问。
如果您更喜欢将 strtok
循环编写为 while
循环而不是 for
(这样更容易查看),您可以执行如下操作:
char buf[MAXC] = "",
*p = buf,
*delim = " \n";
...
p = strtok (buf, delim); /* get first token (word) */
while (p) {
printf ("%s\n", p);
p = strtok (NULL, delim); /* get remaining tokens */
}
我有下面的函数,它从文件中读取单词并使用 fgets 和 strtok 输出每个单词,其中文件中的单词用换行符分隔:
word1
word2
word3
我正在尝试模仿文件中的单词位于仅由 space:
分隔的一行的功能word1 word2 word3
但是,我似乎只能在将 strtok 字符更改为“”并尝试读取一行时获得第一个单词。我不确定我错过了什么。
#include <string.h>
#include <malloc.h>
int readLines;
char *output[255];
char *filename = "commands.txt";
char fileRead(const char *filename, char *output[255])
{
int count = 0;
char input[255];
char *line;
FILE *file = fopen(filename, "r");
if (file == NULL) {
printf("Cannot open file: %s\n", filename);
} else {
while(count < 255 && fgets(input, sizeof(input), file)) {
line = strtok(input, "\n");
if (line) {
output[count++] = strdup(line); /* Store replica */
}
}
fclose(file);
}
return count;
}
char *strdup(const char *str)
{
char *ret = malloc(strlen(str)+1);
if (ret) {
strcpy(ret, str);
}
return ret;
}
int main(int argc, char *argv[])
{
readLines = fileRead(filename, output);
/* read from array and pass into flag function */
for (int x = 0; x < readLines; ++x) {
printf("%s\n", output[x]);
free(output[x]);
}
return 0;
}
如果我理解你的问题——你想要分隔文件中所有包含在一行中的单词 (tokens),那么你正在使用 strtok
错误。在您的代码中,您有 line = strtok(input, "\n");
,其中 delimiter 是 newline。如果你想分隔 space 分隔的单词,那么你还需要在分隔符中包含一个 space
,例如char *delim = " \n";
此外,在第一次调用 strtok
时,您使用缓冲区的变量名称(或指向缓冲区的指针)保存要标记化的文本。对于所有剩余的对 strtok
的调用(例如,对于单词 2, 3, 4...
),您使用 NULL
代替它并检查 return.
将您的示例简化,您可以执行以下操作:
#include <stdio.h>
#include <string.h>
#define MAXC 255
int main (int argc, char **argv) {
char buf[MAXC] = "",
*delim = " \n";
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
fprintf (stderr, "error: file open failed '%s'.\n", argv[1]);
return 1;
}
if (!fgets (buf, MAXC, fp)) { /* read one line from file */
fprintf (stderr, "error: file read failed.\n");
return 1;
}
/* tokenize line with strtok */
for (char *p = strtok (buf, delim); p; p = strtok (NULL, delim))
printf ("%s\n", p);
if (fp != stdin) fclose (fp); /* close file if not stdin */
return 0;
}
示例输入文件
$ cat dat/strtok.dat
my dog has fleas
例子Use/Output
$ ./bin/strtokoneline <dat/strtok.dat
my
dog
has
fleas
如果我误解了,请发表评论,我很乐意进一步提供帮助。如果您对答案还有其他疑问,请提问。
如果您更喜欢将 strtok
循环编写为 while
循环而不是 for
(这样更容易查看),您可以执行如下操作:
char buf[MAXC] = "",
*p = buf,
*delim = " \n";
...
p = strtok (buf, delim); /* get first token (word) */
while (p) {
printf ("%s\n", p);
p = strtok (NULL, delim); /* get remaining tokens */
}