不明白sscanf()函数是如何工作的

时间:2012-08-11 00:01:23

标签: c++ parsing file-io scanf

我不明白如何在C ++中使用sscanf()来读取文件。

我正在开发一个程序,它从文件中读取三个跑步者的名字,以及他们五个最佳时间中的每一个。我想平均每个跑步者的时间,并说出最佳跑步者是谁。我在文件IO方面遇到了最艰难的时刻。

Cplusplus.com已帮助了一些,但并没有真正说明如何阅读,将char *(名称)与花车(时间)等分开。等等,我无法逃避行话和解释技术

一位朋友向我展示了这段代码片段。

while(file>>str) {
    sscanf (str.c_str(),"%d",&myint);
}    

有人介意向我解释它是如何阅读的吗?

5 个答案:

答案 0 :(得分:4)

使用sscanf()被认为是一个古老的学校,但可能非常有益,值得掌握。我想你正在寻找类似的东西:

sscanf(input, "%s %f", name, &time);

其中input是文件中的一行。一些基础知识是%s用于基本字符串,%f用于浮点数。

享受编程的开始;只有获得经验才会变得更好。

答案 1 :(得分:2)

总的来说,sscanf()函数用于在格式字符串的指导下将(C)字符串转换为程序变量中的一系列值,该字符串描述了在字符串中找到的值。

解析引用的代码:

while (file >> str)
{
    sscanf(str.c_str(), "%d", &myint);
}

我们可以假设file是输入流,str是字符串。 while循环在每次迭代时从输入到字符串中读取一个“单词”,其中“单词”是一系列非空白字符,可能前面是一系列空白字符。

示例中的sscanf()语句有三个参数和一个被忽略的返回值(而不是冒险)。第一个参数是C样式字符串,因此读取的单词将转换为带有str.c_str()调用的C字符串。第二个参数是一个格式字符串,它告诉sscanf()字符串中的内容。在这种情况下,%d转换说明符表示十进制整数。第三个参数是指向相应类型的指针,其中将存储转换后的值。通常,格式字符串可以包含许多转换说明符,并且每个转换说明符都需要有一个指针参数(您可以通过抑制赋值来跳过数据)。

sscanf()的返回值是成功分配转化的次数。在这种情况下,您应该检查是否完成了一次转换。

这是一个基于你的例子的工作微型程序:

#include <iostream>
#include <string>
#include <cstdio>
#include <cstdlib>

static void read_stuff(std::istream &file)
{
    std::string str;
    while (file >> str)
    {
        std::cout << "IN: <<" << str << ">>" << std::endl;
        int myint;
        if (sscanf(str.c_str(), "%d", &myint) != 1)
        {
            std::cerr << "Oops: sscanf() failed" << std::endl;
            std::exit(1);
        }
        std::cout << "GOT: " << myint << std::endl;
    }
}

int main()
{
    read_stuff(std::cin);
    return(0);
}

假设您输入输入行:123 234 345 abc。然后程序产生:

IN: <<123>>
GOT: 123
IN: <<234>>
GOT: 234
IN: <<345>>
GOT: 345
IN: <<abc>>
Oops: sscanf() failed

请注意,如果您正在处理的名称包含名字和姓氏,可能包含中间名字,并且包含5个数字(全部在一行中),那么您可能需要一个不同的流程。您可能会使用getline()来读取整行,然后尝试使用sscanf()解析它(或者您可能使用stringstream代替)。当然,你必须处理的线路数量少于5个。 I / O总是很棘手,特别是当你不得不处理错误的数据时(生产质量代码总是必须准备好处理错误的数据)。

答案 2 :(得分:1)

scanf如果与printf相反。

“sscanf”中的第一个“s”表示它会扫描一个字符串。 “fscanf”扫描文件,“scanf”扫描标准输入。

格式与printf相同。

如果sprintf(s, "%d x", 5)将“5 x”打印到s而不是sscanf("5 x", "%d x", &n),则将5放入n。它总是与printf相反。

例外是%s。 printf中的%s打印每个字符串。 printf(“%s”,str); WILL print str,无论str是什么。在scanf中,%s是一个单词。一个词就是没有空格的东西。所以阅读%s只会读一个字。

sscanf(str, "%d", &a);表示str的格式为“%d”(单个十进制数字),并且您将此数字设为a(因为&amp; a是第二个参数)。

作为一个例子

int a,b,c,d;
sscanf("10,20,30,40", "%d,%d,%d,%d", &a, &b, &c, &d);

将导致a = 10,b = 20,c = 30,d = 40.每个%d将读取下一个参数,每个读数将读取一个十进制数。

答案 3 :(得分:1)

基本上你在sscanf函数的第二个参数中指定一个字符串格式来替换你想要的变量 用占位符解析。

说,您知道您的文件包含以下几行:

Father bought 8 bottles of rum on day 1.  
Father bought 11 bottles of rum on day 2.  
Father bought 5 bottles of rum on day 3.  
Father bought 19 bottles of rum on day 4. 

除了每天的瓶子数量之外,你不关心那个字符串中的任何东西。 你修复了没有改变的部分,即“父亲在一天买了一瓶朗姆酒” 并为要从字符串中提取的部分指定占位符。

您的代码看起来像这样:

int nDay, nBottles;
sscanf(str.c_str(), "Father bought %d bottles of rum on day %d", &nBottles, &nDay);
cout << "Day: " << nDay << ", bottles: " << nBottles << endl;

%之后的符号只指定要解析的部分的变量类型。 d这里表示十进制。

答案 4 :(得分:0)

只需使用sscanf(str.c_str(), "%d", &myint)代替sscanf(str, "%d", &myint)

我看到其他人解释了sscanf,但我认为你的问题有点不同。

sscanf是一个C函数,但您可以在C ++中使用它,因为C ++包含C. sscanf基本上取一个字符串,将其划分为您将要显示的内容,然后将这些部分分配给变量。但是在C中没有这样的事件叫string。因此,sscanf将其参数设为char*char pointer,它基本上与{{1}做同样的工作}}。

在C ++中,您应该使用string函数将c_str()转换为string