C编程-使用sscanff

问题描述

我正在尝试使用以下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

argv的用法用法:更新程序[-f“文件名”]'行'

-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()来做到这一点。例如:

  1. sscanf(string,"%s %s %s",word1,word2,word3)与可能需要的许多字缓冲区一起使用。 (如果使用例如char word1[100],然后使用%99s,以避免缓冲区溢出错误。必须为字符串结尾字符\0保留一个字符。)

    sscanf()的返回值告诉您将多少个单词复制到字缓冲区。但是,如果string包含的单词数超出了您指定的数量,则多余的单词将丢失。

    如果练习指定字符串的最大长度,例如 N ,那么您知道最多可以有 N / 2 + 1个单词,每个最大长度 N ,因为每对连续的单词必须至少用一个空格或其他空格字符分隔。

  2. 使用sscanf(string + off," %s%n",word,&len)获取循环中的每个单词。对于每个新单词,它将返回1(将int len设置为正数),并且当0起始于EOF时,将返回stringoff还有更多的话。

    这个想法是,对于每个新单词,您将off增加len,从而在每次迭代中检查string rest

  3. 使用sscanf(string + off," %n%*s%n",&start,&end)int start,end来获取包含下一个单词的位置范围。在通话前设置start = -1end = -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()的工作方式及其副作用。 (已保存的字符在内部作为静态变量隐藏。)