这是C ++中最快的输入方法
我为各种编程奥林匹克编码,从而提高时间效率,我正在寻找最快的方法获取输入,而不需要添加额外的库,即在标准可用目录内按照gcc编译器在比赛期间,我们显然不能添加库编译器。 直到现在我用C ++,我用cin和cout,但发现scanf和printf比它快得多,所以任何人都可以告诉我更快的方法,这可能是一个自定义函数,因为我不介意空间的复杂性,但我更喜欢时间。 Thankyou先进。
这些流总是比C-API函数慢,这是一个非常常见的误解,因为默认情况下,它们与C层同步。 所以是的,这是一个功能,而不是一个错误。
在不牺牲类型安全性(以及可读性,取决于您的口味)的情况下,您可以通过使用以下方式获得流的性能:
std::ios_base::sync_with_stdio (false);
一个小指标:
#include <cstdio>
#include <iostream>
template <typename Test>
void test (Test t)
{
const clock_t begin = clock();
t();
const clock_t end = clock();
std::cout << (end-begin)/double(CLOCKS_PER_SEC) << " secn";
}
void std_io() {
std::string line;
unsigned dependency_var = 0;
while (!feof (stdin)) {
int c;
line.clear();
while (EOF != (c = fgetc(stdin)) && c!='n')
line.push_back (c);
dependency_var += line.size();
}
std::cout << dependency_var << 'n';
}
void synced() {
std::ios_base::sync_with_stdio (true);
std::string line;
unsigned dependency_var = 0;
while (getline (std::cin, line)) {
dependency_var += line.size();
}
std::cout << dependency_var << 'n';
}
void unsynced() {
std::ios_base::sync_with_stdio (false);
std::string line;
unsigned dependency_var = 0;
while (getline (std::cin, line)) {
dependency_var += line.size();
}
std::cout << dependency_var << 'n';
}
void usage() { std::cout << "one of (synced|unsynced|stdio), plsn"; }
int main (int argc, char *argv[]) {
if (argc < 2) { usage(); return 1; }
if (std::string(argv[1]) == "synced") test (synced);
else if (std::string(argv[1]) == "unsynced") test (unsynced);
else if (std::string(argv[1]) == "stdio") test (std_io);
else { usage(); return 1; }
return 0;
}
用g ++ -O3和一个大文本文件:
cat testfile | ./a.out stdio
...
0.34 sec
cat testfile | ./a.out synced
...
1.31 sec
cat testfile | ./a.out unsynced
...
0.08 sec
这如何适用于您的案件取决于。 修改这个玩具基准测试,添加更多测试,并比较像std::cin >> a >> b >> c
和scanf ("%d %d %d", &a, &b, &c);
。 我保证,通过优化(即不在调试模式下),性能差异将会微妙。
如果这不能满足您的需求,您可以尝试其他方法,例如首先阅读整个文件(可能会或可能不会带来更多性能)或内存映射(这是非便携式解决方案,但大型桌面都有)。
更新
格式化输入:scanf与流
#include <cstdio>
#include <iostream>
template <typename Test>
void test (Test t)
{
const clock_t begin = clock();
t();
const clock_t end = clock();
std::cout << (end-begin)/double(CLOCKS_PER_SEC) << " secn";
}
void scanf_() {
char x,y,c;
unsigned dependency_var = 0;
while (!feof (stdin)) {
scanf ("%c%c%c", &x, &y, &c);
dependency_var += x + y + c;
}
std::cout << dependency_var << 'n';
}
void unsynced() {
std::ios_base::sync_with_stdio (false);
char x,y,c;
unsigned dependency_var = 0;
while (std::cin) {
std::cin >> x >> y >> c;
dependency_var += x + y + c;
}
std::cout << dependency_var << 'n';
}
void usage() { std::cout << "one of (scanf|unsynced), plsn"; }
int main (int argc, char *argv[]) {
if (argc < 2) { usage(); return 1; }
if (std::string(argv[1]) == "scanf") test (scanf_);
else if (std::string(argv[1]) == "unsynced") test (unsynced);
else { usage(); return 1; }
return 0;
}
结果:
scanf: 0.63 sec
unsynced stream: 0.41
通常,缓冲输入将是最快的。 你不得不刷新输入缓冲区的频率越高,输入就越快。 有关全面和非常丰富的讨论,请参阅此问题。 简而言之,read()具有较大的缓冲区大小,因为它几乎直接在操作系统中的相应系统调用的顶部。
可能scanf比使用流有点快。 虽然流提供了很多类型安全性,并且不必在运行时解析格式化字符串,但它通常具有不需要过多内存分配的优点(这取决于您的编译器和运行时)。 这就是说,除非性能是你唯一的最终目标,并且你处在关键路径中,那么你应该真正喜欢更安全(更慢)的方法。
Herb Sutter在这里写了一篇非常美味的文章
http://www.gotw.ca/publications/mill19.htm
他深入了解像sscanf和lexical_cast这样的字符串格式化程序的性能细节以及使它们缓慢或快速运行的类型。 这有点类似,可能是那些会影响C风格IO和C ++风格之间性能的东西。 与格式化程序的主要区别在于类型安全性和内存分配数量。
链接地址: http://www.djcxy.com/p/31525.html上一篇: Which is the fastest method of input in C++
下一篇: stdio vs iostream