C ++:从stdin读取字符串的最快方法

时间:2014-02-19 19:15:59

标签: c++ input getchar

我们可以使用getchar_unlocked通过操作类似的字符来快速读取stdin中的整数:

int scan_d()
{
    int ip = getchar_unlocked(), ret = 0, flag = 1;

    for(; ip < '0' || ip > '9'; ip = getchar_unlocked())
    {
        if(ip == '-')
        {
            flag = -1;
            ip = getchar_unlocked();
            break;
        }
    }

    for(; ip >= '0'&& ip <= '9'; ip = getchar_unlocked())
        ret = ret * 10 + ip - '0';
    return flag * ret;
}

有没有办法使用上面的方法快速读取stdin中的字符串? gets比cin / scanf快,但同时拥有空白的关键处理。我想过为字符串修改上面的代码但是遇到了空白问题。此外,似乎逐个读取字符串的每个字符都会更慢。

通过stdin,我的意思是用户输入字符串(无文件处理)

3 个答案:

答案 0 :(得分:3)

  

有没有办法使用上面的方法快速读取stdin中的字符串?

当然可以。如果您更清楚地预期它如何行动,我们甚至可以提供代码。

  

gets比cin / scanf快,但同时拥有对空白的批判性处理。

cinscanf也可以这样做:How to cin Space in c++?How do you allow spaces to be entered using scanf?

  

我想过为字符串修改上面的代码但是遇到了空白问题。

有什么问题? https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem

  

此外,似乎逐个读取字符串的每个字符都会变慢。

比块读取慢?当然。但是,一次读取一个字符实际上是判断字符串结尾的唯一方法。您可以阻止读入缓冲区并旋转它以查找字符串的结尾,这称为缓冲。但是stdin已经被缓冲了,所以再次缓冲它会使更慢更快。读取空格分隔字符串的方法不会比一次使用getchar_unlocked一个字符更快。

答案 1 :(得分:2)

不确定我的基准测试是否正确..这是我第一次真正测试速度..

无论如何,这里是:

http://ideone.com/KruGD2

#include <cstdio>
#include<iostream>
#include <sstream>
#include <chrono>

std::chrono::time_point<std::chrono::steady_clock> hClock()
{
    return std::chrono::steady_clock::now();
}

std::uint32_t TimeDuration(std::chrono::time_point<std::chrono::steady_clock> Time)
{
    return std::chrono::duration_cast<std::chrono::nanoseconds>(hClock() - Time).count();
}


void Benchmark(const char* Name, std::string &str, void(*func)(std::string &str))
{
    auto time = hClock();
    for (int i = 0; i < 100; ++i)
    {
        func(str);
        str.clear();
    }
    std::cout<<Name<<" took: "<<TimeDuration(time) / 100<<" nano-seconds.\n";
}

void unlocked_bench(std::string &str)
{
    char c = '0';
    while((c = getchar_unlocked()) && (c != -1 && c != '\n' && c != '\r'))
    {
        str += c;
    }
}

void getchar_bench(std::string &str)
{
    char c = '0';
    while((c = getchar())  && (c != -1 && c != '\n' && c != '\r'))
    {
        str += c;
    }
}

void getline_bench(std::string &str)
{
    std::cin.getline(&str[0], str.size());
}

void scanf_bench(std::string &str)
{
    scanf("%[^\n]100s", &str[0]);
}

void fgets_bench(std::string &str)
{
    fgets(&str[0], str.size(), stdin);
}

void cinread_bench(std::string &str)
{
    std::cin.read(&str[0], str.size());
}

int main()
{
    std::string str;
    str.reserve(100);

    Benchmark("getchar_unlocked", str, unlocked_bench);
    Benchmark("getchar", str, getchar_bench);
    Benchmark("getline", str, getline_bench);
    Benchmark("scanf", str, scanf_bench);
    Benchmark("fgets", str, fgets_bench);
    Benchmark("cinread", str, cinread_bench);

    return 0;
}

输入:

Hello There
Hello There
Hello There
Hello There
Hello There
Hello There

输出:

getchar_unlocked took: 436 nano-seconds.
getchar took: 330 nano-seconds.
getline took: 619 nano-seconds.
scanf took: 522 nano-seconds.
fgets took: 44 nano-seconds.
cinread took: 67 nano-seconds.

答案 2 :(得分:0)

由于人类比计算机慢,因此没有快速的方法来从用户输入您的程序。

如果用户以每分钟1个字母的速率打字,您的程序将等待1分钟以获得下一个字符。期。不能读得更快。

如果您的程序每秒可以从用户读取1个字符,并且我的程序需要1毫秒才能读取一个字符,则两个程序最终将等待60,000毫秒以便下一个用户的字符。我的程序更快吗?是。这有什么不同吗?没有。你驾驶的红色信号比我快吗?

根据我的经验,关于用户输入的所有优化都已关闭。不要打扰。 It wastes your time and annoys the pig.

如果您的程序需要30秒才能执行操作,则仍需要等待30秒才能让用户输入下一个字符。

专注于坚固性:

  • 用户可以输入无效值吗?
  • 您的程序如何告诉用户该值无效?
  • 用户可以输入的字符多于缓冲区可以支持的字符数吗?

如果必须,阻止从用户读取或使用getline读取字符串。