如何使用scanf读取文件中的每个单词。
在c代码中。我有一个输入文件(在中调用),它是一个mad库,格式为“我真的有<形容词>眼睛”(在中没有空格),我想编写一个bool函数,它使用scanf读取每个单词,并返回true如果调用者中的单词以“开头,如何使用scanf读取文件中的每个单词。,c,scanf,C,Scanf,在c代码中。我有一个输入文件(在中调用),它是一个mad库,格式为“我真的有眼睛”(在中没有空格),我想编写一个bool函数,它使用scanf读取每个单词,并返回true如果调用者中的单词以“开头,word的大小必须足以容纳文本中最大的单词(+3个字符,2个代表和nul termanting字符。您应该将单词的最大长度作为参数传递给istoken,但由于您使用的是扫描,因此必须硬编码字段宽度修饰符以保护数组边界。(这是建议使用fgets而不是scanf——但您必须使用scanf)的原因之一。不要
word
的大小必须足以容纳文本中最大的单词(+3个字符,2个代表
和nul termanting字符。您应该将单词的最大长度作为参数传递给istoken
,但由于您使用的是扫描
,因此必须硬编码字段宽度修饰符以保护数组边界。(这是建议使用fgets
而不是scanf
——但您必须使用scanf
)的原因之一。不要在调用者中略过word
的缓冲区大小。以下内容在调用者中应该足够了(对您来说可能是main()
):
无需使用first
或firstindex
。要检查字符串中的第一个字符,只需取消对指针的引用。这样,只需执行以下操作:
/* istoken = returns true if word is a token */
bool istoken (char *word) {
while (scanf("%1023s", word) == 1) /* did a valid read take place? */
if (*word == '<') /* is 1st char '<' ? */
return true; /* return true */
return false; /* out of words, return false */
}
示例使用/输出
$ echo "my dog has <too> many fleas." | ./bin/scanftoken
found token: '<too>'
$ ./bin/scanftoken
found token: '<too>'
$ cat tokenfile.txt
<too>
这通常是您希望避免的。在程序设计中,您希望(作为目标)将实现(程序的功能、计算等)与输入/输出分开。这使得您的代码在被多个希望输出printf(“标记为:%s\n”,word);
虽然有点不常见,但是如果调用方随后使用word
中的istoken
返回值来确定如何处理令牌,则您的istoken
函数定位令牌并返回true/false
更有意义。如果您只是从intoken内部打印它,如果找到令牌,则不使用return在调用者中,那么为什么要声明它为bool
呢?如果您不使用return,您也可以将它声明为void
就像我说的,这是(一个目标)。只要代码是有效的,就可以以任何方式考虑代码。在istoken
中使用printf
对于临时调试目的也是完全有效的。(事实上,这是您拥有的最有用的调试工具之一,只需在程序的逻辑路径中撒上临时的printf
语句,就可以找到代码按预期工作的位置以及可以说“火车从轨道上掉下来”的位置
文件I/O示例
好的,我们终于开始解决这个'XY'
问题了。因为,正如我现在所理解的,你有一个文件中的文本(我使用了“myfile.txt”
作为输入),你想在istoken
中读取你的输入文件,并将word
和true/false
返回到main()
如果true
则将令牌写入输出文件(我之前在输出文件中使用了“tokenfile.txt”),然后需要使用main()
中的fopen
打开输入文件和输出文件,如下所示:
FILE *ifp = fopen ("myfile.txt", "r"), /* infile pointer */
*ofp = fopen ("tokenfile.txt", "w"); /* outfile pointer */
#include <stdio.h>
#include <stdbool.h>
#define MAXC 1024
/* istoken = returns true if word is a token */
bool istoken (FILE *ifp, char *word) {
while (fscanf(ifp, "%1023s", word) == 1) /* valid read take place? */
if (*word == '<') /* is 1st char '<' ? */
return true; /* return true */
return false; /* out of words */
}
int main (void) {
char word[MAXC] = "";
FILE *ifp = fopen ("myfile.txt", "r"), /* infile pointer */
*ofp = fopen ("tokenfile.txt", "w"); /* outfile pointer */
if (ifp == NULL) { /* validate input open for reading */
perror ("fopen-myfile.txt");
return 1;
}
if (ofp == NULL) { /* validate output open for writing */
perror ("fopen-tokenfile.txt");
return 1;
}
if (istoken (ifp, word)) { /* call istoken passing open ifp */
printf ("found token: '%s'\n", word); /* output token */
fprintf (ofp, "%s\n", word); /* write token to outfile */
}
else
fprintf (stderr, "error: no token found.\n");
fclose (ifp); /* close infile pointer */
if (fclose(ofp) == EOF) /* validate "close-after-write" */
perror ("stream error on outfile stream close");
return 0;
}
(我不是那么有创意,我只是用ifp
作为输入文件指针,用ofp
作为输出文件指针)
无论何时打开文件,在尝试读取或写入文件之前,必须验证文件是否已实际打开以进行读取或写入(例如,fopen
成功)。例如:
if (ifp == NULL) { /* validate input open for reading */
perror ("fopen-myfile.txt");
return 1;
}
if (ofp == NULL) { /* validate output open for writing */
perror ("fopen-tokenfile.txt");
return 1;
}
/* istoken = returns true if word is a token */
bool istoken (FILE *ifp, char *word) {
while (fscanf(ifp, "%1023s", word) == 1) /* valid read take place? */
if (*word == '<') /* is 1st char '<' ? */
return true; /* return true */
return false; /* out of words */
}
现在,当两个文件都打开时,您可以调用istoken
并从ifp
读取。但是,这需要修改istoken
以获取FILE*
参数,以便与fscanf
一起使用,而不是使用scanf
。例如:
if (ifp == NULL) { /* validate input open for reading */
perror ("fopen-myfile.txt");
return 1;
}
if (ofp == NULL) { /* validate output open for writing */
perror ("fopen-tokenfile.txt");
return 1;
}
/* istoken = returns true if word is a token */
bool istoken (FILE *ifp, char *word) {
while (fscanf(ifp, "%1023s", word) == 1) /* valid read take place? */
if (*word == '<') /* is 1st char '<' ? */
return true; /* return true */
return false; /* out of words */
}
最后,您必须fclose
您打开的文件。但是您写入的文件有一个扭曲。您应该验证fclose
,以确保在ofp
上不会发生流错误,否则可能不会被捕获。例如
fclose (ifp); /* close infile pointer */
if (fclose(ofp) == EOF) /* validate "close-after-write" */
perror ("stream error on outfile stream close");
总而言之,您可以执行以下操作:
FILE *ifp = fopen ("myfile.txt", "r"), /* infile pointer */
*ofp = fopen ("tokenfile.txt", "w"); /* outfile pointer */
#include <stdio.h>
#include <stdbool.h>
#define MAXC 1024
/* istoken = returns true if word is a token */
bool istoken (FILE *ifp, char *word) {
while (fscanf(ifp, "%1023s", word) == 1) /* valid read take place? */
if (*word == '<') /* is 1st char '<' ? */
return true; /* return true */
return false; /* out of words */
}
int main (void) {
char word[MAXC] = "";
FILE *ifp = fopen ("myfile.txt", "r"), /* infile pointer */
*ofp = fopen ("tokenfile.txt", "w"); /* outfile pointer */
if (ifp == NULL) { /* validate input open for reading */
perror ("fopen-myfile.txt");
return 1;
}
if (ofp == NULL) { /* validate output open for writing */
perror ("fopen-tokenfile.txt");
return 1;
}
if (istoken (ifp, word)) { /* call istoken passing open ifp */
printf ("found token: '%s'\n", word); /* output token */
fprintf (ofp, "%s\n", word); /* write token to outfile */
}
else
fprintf (stderr, "error: no token found.\n");
fclose (ifp); /* close infile pointer */
if (fclose(ofp) == EOF) /* validate "close-after-write" */
perror ("stream error on outfile stream close");
return 0;
}
#包括
#包括
#定义maxc1024
/*istoken=如果word是标记,则返回true*/
bool-istoken(文件*ifp,字符*word){
当(fscanf(ifp,“%1023s”,word)==1)/*发生有效读取时*/
如果调用者中有(*word==',word
的大小必须足以容纳文本中最大的单词(+3个字符,2个代表
和nul termanting字符。您应该将单词的最大长度作为参数传递给istoken
,但由于您使用的是扫描
,因此必须硬编码字段宽度修饰符以保护数组边界。(这是建议使用fgets
而不是scanf
——但您必须使用scanf
)的原因之一。不要在调用者中略过word
的缓冲区大小。以下内容在调用者中应该足够了(对您来说可能是main()
):
无需使用first
或firstindex
。要检查字符串中的第一个字符,只需取消对指针的引用。这样,只需执行以下操作:
/* istoken = returns true if word is a token */
bool istoken (char *word) {
while (scanf("%1023s", word) == 1) /* did a valid read take place? */
if (*word == '<') /* is 1st char '<' ? */
return true; /* return true */
return false; /* out of words, return false */
}
示例使用/输出
$ echo "my dog has <too> many fleas." | ./bin/scanftoken
found token: '<too>'
$ ./bin/scanftoken
found token: '<too>'
$ cat tokenfile.txt
<too>
这通常是您希望避免的。在程序设计中,您希望(作为目标)将实现(程序的功能、计算等)与输入/输出分开。这使得您的代码在被多个希望输出printf(“标记为:%s\n”,word);
虽然有点不常见,但是如果调用方随后使用该返回来确定如何处理word
中的令牌,则查找令牌并返回true/false
的istoken
函数更有意义