问题描述
我正在尝试使用以下C编程语言,任何帮助,或者如果您可以完成代码,将不胜感激:
我正在尝试使用C编程语言编写一个使用文件io的程序,该程序将使用sscanf函数解析单词并输出txt文档(bar.txt)内所有句子中的每个单词。这是说明。
编写一个打开文件bar.txt的程序,将其命名为“ reader”。传递参数以指示要读取的行。将基于参数“ lines”的文件中的所有行读入缓冲区,然后使用sscanf将句子的所有单词解析为不同的string *变量。将每个单词打印到屏幕上,然后回车。您可以硬连线文件名(bar.xt的路径)或使用选项输入文件名。
这是我正在使用的txt文件(bar.txt):
bar.txt
this is the first sentence
this is the 2nd sentence
this is the 3rd sentence
this is the 4th sentence
this is the 5th sentence
文件结尾:bar.txt
-f是可选的(如果未提供,则具有来自先前程序2(bar.txt)的硬连线名称) 从1到10的'lines'整数(请记住文件中包含来自先前程序的5-10个字符串) 输入程序的示例输入示例为:
./ reader -f bar.txt 1
输出:
opening file "bar.txt"
File Sentence 1 word 1 = this
File Sentence 1 word 2 = is
File Sentence 1 word 3 = the
File Sentence 1 word 4 = first
File Sentence 1 word 5 = sentence
另一个示例
./ reader -f bar.txt 5
输出:
File Sentence 5 word 1 = this
File Sentence 5 word 2 = is
File Sentence 5 word 3 = the
File Sentence 5 word 4 = 5th
File Sentence 5 word 5 = sentence
命令示例:
./reader -f bar.txt 5
./reader -f bar.txt 2
./reader -f bar.txt 7
./reader 2
./reader 5
./reader 8
./reader 11
#include <stdlib.h>
#include <stdio.h>
#define MAXCHAR 1000
int main(int argc,char *argv[]) {
FILE *file;
char string[MAXCHAR];
char* filename = "c:\\cprogram\\fileio-activity\\bar.txt";
int integer = argv[3][0] - 48;
int i; //for loops
if (argv[1][0] == '-' && argv[1][1] == 'f')
{
file = fopen(filename,"r");
if (file == NULL){
printf("Could not open file %s",filename);
return 1;
}
while (fgets(string,MAXCHAR,file) != NULL)
printf("%s",string);
fclose(file);
return 0;
}
}
解决方法
如果他们使用argv
选项,则需要从-f
获取文件名。而且您需要根据是否提供了此选项,从不同的参数获取行数。
使用strcmp()
比较字符串,而不是分别测试每个字符。并使用atoi()
将lines
参数转换为整数,因为您的方法仅适用于一位数字。
#include <stdlib.h>
#include <stdio.h>
#define MAXCHAR 1000
function usage() {
fprintf(stderr,"Usage: reader [-f filename] lines\n");
exit(1);
}
int main(int argc,char *argv[]) {
FILE *file;
char string[MAXCHAR];
char* filename = "c:\\cprogram\\fileio-activity\\bar.txt";
int integer;
int i; //for loops
if (argc < 2) {
usage();
}
# Process arguments
if (strcmp(argv[1],"-f") == 0)
{
if (argc < 4) {
usage();
}
filename = argv[2];
integer = atoi(argv[3]);
} else {
integer = atoi(argc[1]);
}
file = fopen(filename,"r");
if (file == NULL){
fprintf(stderr,"Could not open file %s\n",filename);
return 1;
}
while (fgets(string,MAXCHAR,file) != NULL)
printf("%s",string);
fclose(file);
return 0;
}
,
要添加到Barmar已经回答的内容中,以完成任务的进一步步骤:
将字符串拆分为单独的单词通常称为 tokenization ,为此我们通常使用strtok()
。有几种方法可以使用sscanf()
来做到这一点。例如:
-
将
sscanf(string,"%s %s %s",word1,word2,word3)
与可能需要的许多字缓冲区一起使用。 (如果使用例如char word1[100]
,然后使用%99s
,以避免缓冲区溢出错误。必须为字符串结尾字符\0
保留一个字符。)sscanf()
的返回值告诉您将多少个单词复制到字缓冲区。但是,如果string
包含的单词数超出了您指定的数量,则多余的单词将丢失。如果练习指定字符串的最大长度,例如 N ,那么您知道最多可以有 N / 2 + 1个单词,每个最大长度 N ,因为每对连续的单词必须至少用一个空格或其他空格字符分隔。
-
使用
sscanf(string + off," %s%n",word,&len)
获取循环中的每个单词。对于每个新单词,它将返回1(将int len
设置为正数),并且当0
起始于EOF
时,将返回string
或off
还有更多的话。这个想法是,对于每个新单词,您将
off
增加len
,从而在每次迭代中检查string
的 rest 。 -
使用
sscanf(string + off," %n%*s%n",&start,&end)
和int start,end
来获取包含下一个单词的位置范围。在通话前设置start = -1
和end = -1
,并在通话后重复end > start
。将end
添加到off
,前进到下一个单词。下一个单词(当
start >= 0
时)的开头是string + start
,并且具有end - start
个字符。要“模拟”
strtok()
行为,可以使用以下命令临时保存终止字符(可以是空格或字符串末尾)。char saved = string[off + end];
,然后将其替换为字符串结尾字符string[off + end] = '\0';
,这样(string + start)
是指向单词的指针,就像strtok()
返回一样。在下一次扫描之前,请执行string[off + end] = saved;
恢复保存的字符,并执行off += end;
前进到下一个单词。
第一个是最简单的,但在实际程序中最不有用。 (它可以正常工作,但是我们通常不事先知道字符串的长度和字数限制。)
当您具有备用模式时,第二个选项非常有用,您可以尝试输入下一个“单词”或项目;例如,当读取2D或3D向量(平面或三维空间中的点)时,通过尝试尝试从<1 2 3>
到[1,2,3]
到1 2 3
,可以支持多种不同的格式首先解析最复杂/最长的,然后尝试下一个,直到其中一个起作用。 (如果它们都不起作用,那么输入当然是错误的。)
第三个最有用的地方在于,它实质上描述了strtok()
的工作方式及其副作用。 (已保存的字符在内部作为静态变量隐藏。)