Мы можем использовать 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 я подразумеваю, что строка вводится пользователем (без обработки файлов)
Есть ли способ быстро прочитать строки из stdin, используя что-то вроде выше?
Конечно. Если бы вы поняли, как вы ожидаете, что это будет действовать, мы могли бы даже предоставить код.
get быстрее, чем cin / scanf, но в то же время обладает критической обработкой пробелов.
cin
а также scanf
может сделать это также: Как cin Space в c ++? а также Как разрешить ввод пробелов с помощью scanf?
Я думал об изменении приведенного выше кода для строк, но столкнулся с проблемами с пробелами.
Какие проблемы? https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem
Кроме того, кажется, что чтение каждого символа строки один за другим будет медленнее.
Медленнее, чем чтение блока? Конечно. Но тогда, чтение по одному символу за раз — действительно единственный способ узнать, где находится конец строки. Вы можете заблокировать чтение в буфере и прокрутить его, чтобы найти конец строки, это называется буферизацией. Но stdin
уже буферизован, поэтому буферизация снова сделает это помедленнее не быстрее Не будет более быстрого способа чтения строки, разделенной пробелом, чем использование getchar_unlocked
по одному персонажу за раз.
Не уверен, что мои тесты верны вообще .. Это моя первая проверка скорости на самом деле ..
Во всяком случае, здесь идет:
#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.
Поскольку люди медленнее, чем компьютер, нет быстрого способа получить информацию от пользователя для вашей программы.
Если пользователь печатает со скоростью 1 буква в минуту, ваша программа будет ждать 1 минуту для следующего символа. Период. Не могу читать быстрее.
Если ваша программа может читать 1 символ в секунду от пользователя, а моей программе требуется 1 мс для чтения символа, обе программы в конечном итоге ждут 60000 мсек для символа следующего пользователя. Моя программа быстрее? Да. Есть ли разница? Нет. Вы ехали быстрее до красного сигнала, чем я?
По моему опыту, все оптимизации в отношении пользовательских входов отключены. Не беспокойся Это тратит впустую ваше время и раздражает свинью.
Если вашей программе требуется 30 секунд для выполнения операции, ей все равно придется ждать еще 30 секунд, пока пользователь не введет следующий символ.
Вместо этого сконцентрируйтесь на надежности:
Если необходимо, заблокируйте чтение от пользователя или используйте getline
читать строку.