我不明白如何在C ++中使用sscanf()
来读取文件。
我正在开发一个程序,它从文件中读取三个跑步者的名字,以及他们五个最佳时间中的每一个。我想平均每个跑步者的时间,并说出最佳跑步者是谁。我在文件IO方面遇到了最艰难的时刻。
Cplusplus.com已帮助了一些,但并没有真正说明如何阅读,将char *(名称)与花车(时间)等分开。等等,我无法逃避行话和解释技术
一位朋友向我展示了这段代码片段。
while(file>>str) {
sscanf (str.c_str(),"%d",&myint);
}
有人介意向我解释它是如何阅读的吗?
答案 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
。