ввод — C ++: самый быстрый способ прочитать строку из стандартного ввода

Мы можем использовать 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, используя что-то вроде выше? get быстрее, чем cin / scanf, но в то же время обладает критической обработкой пробелов. Я думал об изменении приведенного выше кода для строк, но столкнулся с проблемами с пробелами. Кроме того, кажется, что чтение каждого символа строки один за другим будет медленнее.

Под stdin я подразумеваю, что строка вводится пользователем (без обработки файлов)

1

Решение

Есть ли способ быстро прочитать строки из stdin, используя что-то вроде выше?

Конечно. Если бы вы поняли, как вы ожидаете, что это будет действовать, мы могли бы даже предоставить код.

get быстрее, чем cin / scanf, но в то же время обладает критической обработкой пробелов.

cin а также scanf может сделать это также: Как cin Space в c ++? а также Как разрешить ввод пробелов с помощью scanf?

Я думал об изменении приведенного выше кода для строк, но столкнулся с проблемами с пробелами.

Какие проблемы? https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem

Кроме того, кажется, что чтение каждого символа строки один за другим будет медленнее.

Медленнее, чем чтение блока? Конечно. Но тогда, чтение по одному символу за раз — действительно единственный способ узнать, где находится конец строки. Вы можете заблокировать чтение в буфере и прокрутить его, чтобы найти конец строки, это называется буферизацией. Но stdin уже буферизован, поэтому буферизация снова сделает это помедленнее не быстрее Не будет более быстрого способа чтения строки, разделенной пробелом, чем использование getchar_unlocked по одному персонажу за раз.

3

Другие решения

Не уверен, что мои тесты верны вообще .. Это моя первая проверка скорости на самом деле ..

Во всяком случае, здесь идет:

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

Поскольку люди медленнее, чем компьютер, нет быстрого способа получить информацию от пользователя для вашей программы.

Если пользователь печатает со скоростью 1 буква в минуту, ваша программа будет ждать 1 минуту для следующего символа. Период. Не могу читать быстрее.

Если ваша программа может читать 1 символ в секунду от пользователя, а моей программе требуется 1 мс для чтения символа, обе программы в конечном итоге ждут 60000 мсек для символа следующего пользователя. Моя программа быстрее? Да. Есть ли разница? Нет. Вы ехали быстрее до красного сигнала, чем я?

По моему опыту, все оптимизации в отношении пользовательских входов отключены. Не беспокойся Это тратит впустую ваше время и раздражает свинью.

Если вашей программе требуется 30 секунд для выполнения операции, ей все равно придется ждать еще 30 секунд, пока пользователь не введет следующий символ.

Вместо этого сконцентрируйтесь на надежности:

  • Может ли пользователь ввести недопустимые значения?
  • Как ваша программа сообщает пользователю, что значение неверно?
  • Может ли пользователь ввести больше символов, чем может поддерживать ваш буфер?

Если необходимо, заблокируйте чтение от пользователя или используйте getline читать строку.

1
По вопросам рекламы [email protected]