Блог пользователя freopen

Автор freopen, 14 лет назад, По-русски
Мне захотелось наконец разобраться в способах ввода-вывода в C++, какой из них быстрее и удобнее. Поэтому я написал прогу, которая проверит скорость работы основных способов ввода/вывода в C++.
Итак, разберем все тесты по порядку:

Вывод программы

Test: (printf, 10000000 ints) 2.50c
Test: (cout, 10000000 ints) 3.02c
Test: (write, 10000000 ints, 104827485 chars) 2.88c + 0.25c
Test: (scanf, 10000000 ints) 2.61c
Test: (fwrite, 10000000 ints, 104827485 chars) 2.88c + 0.26c
Test: (cin, 10000000 ints) 8.32c
Test: (printf, 100000000 chars) 1.87c
Test: (scanf, 100000000 chars) 8.44c
Test: (cout, 100000000 chars) 6.98c
Test: (cin, 100000000 chars) 12.51c
Test: (putchar, 100000000 chars) 2.26c
Test: (getchar, 100000000 chars) 1.99c
Test: (read, 100000000 chars) 0.08c + 0.57c
Test: (fread, 100000000 chars) 0.08c + 0.59c

Разбор тестов

  1. printf вывел 107 целых чисел. Относительно быстро и удобно. Вполне можно использовать.
  2. Тоже самое сделал cout. Немного медленнее, но это когда как. Иногда cout работает довольно медленно.
  3. write, как функция ostream. Работает быстро. Очень быстро. Похоже, что в основе лежит fwrite. Первое время - преобразование чисел в строку. Второе - вывод. Примечательно, что вывод куда быстрее.
  4. scanf. Работает ровно также как и printf. Сносно и удобно в использовании.
  5. fwrite. Функция из C. Работает идентично write и сравнимо с ней по сложности использования. Ну может чуть чуть сложнее.
  6. Вот и первый fail. cin считывает числа медленно. Раза в 4 медленнее, чем все остальное. Если вам в программе требуется считать миллион чисел, готовьтесь потратить на это 0.8 секунд cin-а. А возможно и больше.
  7. Переходим к символам. printf выводит символы чуть быстрее, чем числа. Видимо, из-за отсутствия необходимости преобразовывать число.
  8. А вот это стало неожиданностью. scanf на редкость медленно читает символы. Файлик был размером около 100Мб, но все равно мог бы и побыстрее.
  9. cout выводит символы медленно. В 3 раза медленнее, чем printf.
  10. cin считывает символы совсем медленно. У меня уходило 1.2 секунды на каждые 10Мб. Есть и еще один сюрприз. Он выкидывает whitespace. Даже когда считывает один символ. Про это надо не забывать. Лечится так: cin >> noskipws;
  11. putchar. Предназначен для вывода одного символа. И это у него выходит прекрасно. 
  12. getchar. Предназначен для ввода одного символа. И также он это делает очень быстро.
  13. Наконец, блочный ввод-вывод. Опять указано два параметра. Первый - время считывания. Второй - проверка на правильность считывания. Второй нужен только для сравнения. Данные предсказуемо совпадают.
  14. См. выше

Вывод

  1. Для чисел лучше использовать cin(если время не очень критично), или printf(если критично).
  2. Для символов лучше использовать getchar и putchar.
  3. Что-то мне не верится в возможность считать 100Мб данных в оперативку за 0.08 секунд. Есть версия, что файл был кеширован в оперативке. Кто знает, как это проверить и как исправить - пишите в комменты.
  4. Надо доделать тесты для строк и дробного типа. Но это уже попозже.

Тем, кто хочет проверить это на своем компьютере

Пожалуйста. Вот программа: http://pastebin.com/DpmjHF7C. Учтите, что она заменит файл temp.txt на свой, а также ей надо 100Мб свободного места и 200Мб оперативки. И пришлите мне вывод программы в комменты или в личку. Под влиянием этих данных, я возможно, изменю разбор тестов. Большое спасибо всем, кто запустит прогу у себя и пришлет мне результаты, а также тем, кто укажет мне на неточности в программе или предложит другие тесты.
  • Проголосовать: нравится
  • +20
  • Проголосовать: не нравится

14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Почти что с самого начала работы на плюсах использую scanf/printf. Удобно во многих случаях, быстро. cin/cout использую только в случае ввода/вывода string. Ну и getline иногда.
К слову, на экзамене по плюсам теория была на cin/cout, которую я успешно провалил и чуть не получил 4 =)
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Ну вот, а символы читает медленно. Кто же знал...
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Ну, %s вроде бы тоже неплохо считывает (ТЛ не ловил еще таким образом), если дело касается чаровских массивов. Символы - тоже не ловил ТЛ со scanf. 
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Попробуем еще раз. Я строки еще буду разбирать. Строки тоже десятком способов считать можно. Просто пока хочется посмотреть, есть ли интерес к теме и подправить код. А потом уже наделать еще тестов.
        • 14 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Да про строки я уже понял =) Это так, к слову =)
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
А fputs и fgets (и их аналоги для stdin/stdout puts и gets)? Они после fread и fwrite по скорости будут (быстрее считать строку gets'ом, чем getchar'ами).
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    В том то и дело, что строку. Со строками будут отдельные тесты. Позже. Об этом написано в посте.
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Ну fread тоже не отдельные чары читает :)
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        В общем то да, но я лишь утверждал, что разобрал целые и символы. Можно считать это моей наработкой на будущее :).
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
У меня вопрос: при использовании cin символы читаются до левого пустого символа. Как узнать, какой символ был левым пустым?
  • 14 лет назад, # ^ |
      Проголосовать: нравится +1 Проголосовать: не нравится
    Попробую перефразировать. cin при чтении символа пропускает все whitespace символы. Как узнать, что пропустил cin?
    Если я правильно понял вопрос, то во-первых, обычно не используют cin для такого рода задач. А во-вторых - cin >> noskipws >> c; не будет пропускать whitespace символы.
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Да, правильно понял) Я просто гуглил и нашёл выражение "левый пустой символ")

      Спасибо, сейчас попробую.

14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
1)
Меня вот это удивило:
Test: (printf, 100000000 chars) 1.87c
Test: (putchar, 100000000 chars) 2.26c
Почему же, интересно, printf обошел putchar...

2)
Быстрее (не медленнее) scanfа и printfа числа читает и пишет вот эта жесть:
int get_num()
{
char c;
int res=0;
do
{
c = getchar();
}
while ( c < '0' || c > '9' );
do
{
res=res*10+c-'0';
c = getchar();
}
while ( c >= '0' && c <= '9' );
return res;
}
void pr_num2( int n )
{
if ( n )
{
pr_num2( n / 10 );
putchar( n % 10 + '0' );
}
}
void pr_num( int n )
{
if ( n )
{
pr_num2( n / 10 );
putchar( n % 10 + '0' );
}
else
putchar('0');
}

Использовал её когда сдавал "на скорость" 1100 на тимусе. :)
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Но я думаю, что get_num и pr_num в реальной жизни нигде не не нужны. К тому же не являются стандартными методами. Но для статистики, возможно, интересно будет.
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Сложно сказать. Ссылку на код я дал. Анализируй или запусти у себя - посмотрим, что получится.
  • 14 лет назад, # ^ |
      Проголосовать: нравится +1 Проголосовать: не нравится
    Кстати у твоих функций просто напрашивается inline в заголовке
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Оу, спасибо!
      Время действительно с 0.062с уменьшилось до рекордных 0.046с.
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      В чём разница функции и/или процедуры inline и без неё?
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Ссылка
        Если коротко, то эту функцию компилятор будет стремиться раскрыть во всех местах вызова. Т.е. вставить внутренности функции там, где она вызывается вместо собственно вызова. Экономит время, необходимое на создание функции и на отправление ее в call stack. Эффективно, когда есть маленькая, нерекурсивная, часто вызываемая функция.
        • 14 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Бытует мнение (и я с ним солидарен), что современные компиляторы автоматически делают инлайн всех функций, которых можно заинлайнить.
          • 14 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится
            а что понимается под современным компилятором?

            на моей памяти не менее двух раз был инцидент, когда написание inline позволяло получить вердикт AC вместо TL, компилятор gnu c++ 3.4.2
            • 14 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится
              Как утверждает эта картинка, gcc делает такую оптимизацию при -O3. Другое дело, что вряд ли в какой-то тестирующей системе стоит -O3 по умолчанию, поэтому я пожалуй погорячился.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Люди, пост родился из этого комментария. Можете ему написать, что этот пост существует. А то я 5 раз попробовал и не вышло. Спасибо.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
а где temp.txt взять?
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    ммм. Зачем тебе temp.txt? Он вроде только программе нужен, но программа его и без тебя создаст. Просто если в той же директории лежит temp.txt с нужной для тебя инфой, то после запуска нужная инфа исчезнет.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
вот характеристики моего ноута:

а вот чё вывело:

  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Думается мне, что у винды проблемы с непечатаемыми символами. Сейчас поправим код. Ага, вот новый.
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      o.O

      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Обратите внимание, насколько putchar(11 строка) шустрее printf(7). Также обратите внимание, что cin(6) в 11 раз медленнее scanf(4). И вообще cin(6,10) тут очень тормоз, а результаты ни капли не смахивают на мои. Однако выводы по использованию остаются те же. У кого есть дополнительная информация по поводу этих (весьма странных) данных - прошу поделиться, ибо я в замешательстве.
        • 14 лет назад, # ^ |
            Проголосовать: нравится +1 Проголосовать: не нравится
          Может сделать вывод примерно таким?
          Test  1: (10000000 ints, printf) 2.50c
          Test  2: (10000000 ints, cout) 3.02c
          Test  3: (10000000 ints, write) 2.88c + 0.25c

          Тогда будет проще ссылаться на номер теста и, возможно, проще смотреть.
          • 14 лет назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится
            Уже в новой версии. Кстати, попробуй сдать 1100 за 0.031. Там есть несколько очень забавных моментов, которые красиво решаются.
            • 14 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится
              Сейчас спать надо.
              А сдать обязательно попробую. :)
14 лет назад, # |
  Проголосовать: нравится +1 Проголосовать: не нравится
Если возможно, может ли администрация показать соответствующие циферки на серверах codeforces, чтобы можно было понять, с какой скоростью осуществляется считывание и запись данных?
14 лет назад, # |
  Проголосовать: нравится +1 Проголосовать: не нравится
хотелось бы задать пару вопросов, хотя возможно не в подходящий пост...
1) как в С++ перевести коретку на следующую строку? в пасцале это можно сделать readln(), а вот в С++ не знаю(((
2) как в С++ прочитать строку интов? в пасцале это можно записать так : while not eoln do read();

за ранее благодарю!

  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    1) cout << '\n'; или можно cout << std::endl;
    2) while (cin >> x) {}
    • 14 лет назад, # ^ |
        Проголосовать: нравится -6 Проголосовать: не нравится
      ты с паскалем или делфой знаком немного хоть???
      1) вообще бред, в С++ cin эквивалентен паскалевскому read().
      я же прошу, вот тебе даже такой пример, у тебя на входе дана симметрическая матрица
      1 2 0
      2 3 7
      0 7 9
      а я прошу как считать только :
      1
      2 3
      0 7 9
      т.к. все символы мне нет смысла читать, если сказано что матрица симметрическая.

      2) ты написал пока не конец файла!!! в паскале это эквивалентно while not eof !!!!
      а я прошу пока не конец строки (((

      ЗЫ так в принципе и ожидал что мне это ответят(((
      • 14 лет назад, # ^ |
          Проголосовать: нравится +1 Проголосовать: не нравится
        сорри, невнимательно прочитал твой пост.. И думаю не стоит сразу так резко на это реагировать.
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        вообще, тебе это скорее всего надо для того, чтобы писать лабы по ВМА с симметрическими матрицами.. но там они и будут введены как треугольные. В противном случае в С++ ничего такого нету, считывай строку - из неё выдирай инты.
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Не знаю, как надо "правильно", но я в таких случаях делаю так:
    1) scanf("\n");

    2)     string str;
    getline(cin, str);
    stringstream ss(str);
    int elem;
    while (ss >> elem) {
    DoSmthWith(elem);
    }
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      а нельзя ли читать инты не выделяя их из строки? просто в таком случае будет быстрее читать посимвольно и выделять инты. или я не прав?
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Считать строку быстрее, потом из неё sscanf'ом считывать всё что хочешь в любом формате. Перевести каретку можно, например, с помощью gets, но в любом случае надо дочитать строку до конца(и в паскале тоже), чтобы узнать где её конец:) Так что от считывания всего ввода не убежишь.
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      1) Так не стоит делать. Смотри мой ответ снизу.
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    1)
    char buffer[100500];
    gets(buffer);

    НЕ РЕКОМЕНДУЕТСЯ писать scanf("\n"); так как он прочитает все пробельные символы (т.е. может сразу несколько пустых строчек зохавать).

    2)

    while ( scanf("%d", &n) == 1 ) {
        ...
    }

    Сканф возвращает количество удачно прочитанных аргументов.
    Если он не может прочитать то, что его просят (если там один аргумент), то он возвращает 0.
    Если и прочитать ничего не удалось, и настал конец файла – сканф будет выдавать -1.

    ПОЭТОМУ не стоит писать так:
    while ( scanf("%d", &n) )

    Много раз сам валился на этом. :)
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      1) Спасибо, не знал. В олимпиадных задачах чаще всего нужно просто пропустить все пробелы и переводы строк до нужных данных. Там scanf("\n") работает.

      2) while ( scanf("%d", &n) == 1 ) { ... } 
      читает все числа из файла, а тут нужно одну строчку. Лучше всего тут прочитать сначала строку, а потом распарсить sscanf-ом или stringstream-ом. 

      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        1) Я раньше тоже всегда так читал. :)
        А потом в Сазанке у нас упала программа вот с таким тестом.
        3
                       
        a b c
        d e f

        scanf("\n") прочитал аж до начала третей строчки. Потом три gets() в цикле выдали 3ю, 4ю и 4ю (!) строчки у нас был стабильно WA.

        2) Вот теперь я неправильно прочитал))
        Привожу рабочий код sscanf (спасибо Foton за по сути его написание :)

        char buffer[10000], *iter, s[1000];

        int main()

        {

            gets(buffer);

            iter = buffer;

            while ( *iter == ' ' )

                    iter++;

            while ( sscanf(iter, "%s", &s) == 1 )

            {

                sscanf(s, "%d", &a);

                printf("%d ", a);

                iter += strlen(s);

                    while ( *iter == ' ' )

                        iter++;

            }

            return 0;

        }

        • 14 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Если туда сверху прикрутить

          #include <cstdio>
          #include <string.h>
          int a;

          то оно скомпилируется.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

вот:

  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    А что это?
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Здорово. А можно это же самое в release-mode? Кстати, обратите внимание, как здраво не рулит cin на интах на этом компе.
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      а что такое release mode, тут немного погуглил(оказывается есть debug mode) нашел на англ яз с которым у меня не сложились отношения, можно в двух слова в чем отличие?

      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        debug mode - скомпилировать прогу с отладочной информацией. В exe войдет исходный текст проги, способ ее остановить на любой строчке, проверка разных вещей типа выхода за границы массивов и т.п.
        release mode - скомпилировать программу соптимизировав ее для полноценной работы.

        Проги на серверах чаще тестируются в release mode. Поэтому он нам более интересен.
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Хотел сказать, но забыл. Этот mode ставится в настройках среды обычно. Например в minGW Studio это называется "Set active configuration".
        • 14 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          спс за инфу

          у меня codeblocks 8.02 не нашел там ничего такого:(

14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Test: (printf, 10000000 ints) 11.34c

Test: (cout, 10000000 ints) 27.69c

Test: (write, 10000000 ints, 56609008 chars) 6.67c + 1.55c

Test: (scanf, 10000000 ints) 7.17c

Test: (fwrite, 10000000 ints, 56609008 chars) 6.67c + 1.31c

Test: (cin, 10000000 ints) 31.34c

Test: (printf, 100000000 chars) 41.64c

Test: (scanf, 100000000 chars) 52.09c

Test: (cout, 100000000 chars) 25.36c

Test: (cin, 100000000 chars) 69.89c

Test: (putchar, 100000000 chars) 14.25c

Test: (getchar, 100000000 chars) 18.23c

Test: (read, 100000000 chars) 1.55c + 0.53c

Test: (fread, 100000000 chars) 1.17c + 0.47c

  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Спасибо. Как у тебя все небыстро. scanf и cin не рулят на char-ах
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Может сделать так:
      scanf:
      всё про сканф

      printf:
      всё про принтф

      cin:
      ...

      cout:
      ...

      gectchar:
      ...

      putchar:
      ...

      gets:
      ...

      puts:
      ...

      read:
      ...

      fread:
      ...

      И одинаковые тесты (по возможности) для каждого метода ввода и вывода.

      А вообще да, у меня медлене машинка.
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Почитай код и поймешь, где ты не прав. Все будет, но чуть позже
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Я читал немного. :) Можно будет поразбираться.
      Кстати, это release...
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Проект, на котором тестируется скорость различных языков на различных системах: http://shootout.alioth.debian.org/
14 лет назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится
советаю функцию scanf("%d", &var) писать так:

var = get();

inline int get()
{
    for (C = getchar(); (C < 48 || C > 57) && C != '-'; C = getchar());
    if (C == '-')
        neg = 1,
        C = getchar();
    else
        neg = 0;
    x = 0;
    for (; 47 < C && C < 58; C = getchar())
        x = x*10 + C - 48;
    if (neg)
        return -x;
    else
        return x;
}


Функция get() читает по одному символу и преобразовывает эти символы в число.

Тэстил. Заметно ускоряет время.
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Почитай вот эту ветку. У меня было что-то подобное.
  • 14 лет назад, # ^ |
      Проголосовать: нравится +3 Проголосовать: не нравится

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

    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Авторы олимпиадных задач все-таки разные бывают и расслабляться не стоит в любом случае. А такие трюки иногда помогают протолкнуть n^2 при n=10000, если нужен nlogn. Редко, правда. Но вот на codeforces люди начинают выть даже если задачи незначительно отличаются от среднестатистической задачи. И потом, кто сказал, что знание тонкостей языка бесполезно. Оно может помочь в задачах на оптимизацию, в которых не надо особо оптимизировать ввод.
14 лет назад, # |
Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
А вот эту штуку не пробовал? http://codeforces.me/blog/entry/10
Хорошо бы и с ней протестить cin, cout . . .
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Вопрос по С++ или даже по Visual Studio, но относится к ТопКодеру.

Писал долго SRMы в NetBeans на Java и был доволен, но сегодня меня Java по некоторым причинам разочаровала и не в первый раз, так что я решил вернуться к С++.

Теперь вопрос: как сделать, чтобы в режиме отладки окно консоли не закрывалось мгновенно? Я использую плагин moj, но не знаю, как его модифицировать, чтоб вписать туда что-то типа system("pause");

Второй вопрос. Где нужно поставить галочку в настройках, если это вообще возможно, чтобы закрывающиеся скобки (и обычные, и фигурные) добавлялись автоматически? Особо хочется добавления фигурных скобок - в NetBeans привык и теперь совсем непривычно их самому ставить.

Третий вопрос. Какой самый правильный способ перевода строки в число и обратно и чтения чисел из строки?
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Ну есть stringstream, он действует и туда и обратно, правда он тормознутый зараза... Перевод из строки в число если в 32-битный то atol(atoi), 64-битный я ручками перевожу если stringstream в ТЛ хочет уйти.
    Действует stringstream так:
    #include<sstream>
    ...
    int n; string s;
    cin >>s;
    stringstream ss;
    ss <<s;
    ss>>n;
    ну и в обратную точно так же:
    ss<<n;
    ss>>s;
    • 14 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится
      Спасибо.
      А если в строке всякие там запятые, то мне надо эти чары считывать?
      • 14 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится
        Не понял насчет запятых. Дабловое число что ли?
        • 14 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится
          Нет.
          Я же сказал, что мне эта штука нужна для ТопКодера, а там частенько данные задают в виде строки, в которой числа разделены чаще всего пробелами, но, бывает, и запятыми.
  • 14 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

    1) Чтение чисел из строки без тормозов:

    char str[mxx]="1 2";

    sscanf(str,"%d %d",&n,&m);

    2) Строка в число для 64-битных чисел без тормозов:

    char str[mxx]="12345678910111213";

    long long big;

    sscanf(str,"%I64d",&big);

    Про консоль не очень понял. Если в режиме отладки, то ставишь breakpoint на последний return 0. А если просто запустить и посмотреть что вывелось на консоль, то как вариант написать _getch() //#include <conio.h> . Не забыть его потом убрать!!! :)

    • 14 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится
      Проблема была с консолью в том, чтобы мне этот getch() или system("pause") не писать вручную каждый раз. Кажется, разобрался, как поместить это в плагин.

      Ладно, и sscanf как-нибудь попробую.
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Чтение чисел... Ну можно int n;cin>>n, scanf("%d",&n) и его разновидности. Лучше все-таки сканф, т.к. можно чтобы кое-какие символы пропускал-ставишь эти символы после %d
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    как сделать, чтобы в режиме отладки окно консоли не закрывалось мгновенно? Я использую плагин moj, но не знаю, как его модифицировать, чтоб вписать туда что-то типа system("pause");

    Ctrl + F5?
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    1) Используй "Win32 Console Application" вместо "Empty Project" при создании проекта. Поставь галку в "Additional options->Empty project" чтобы созданный консольный проект был чистым. 
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
спасибо за статью. помогла уложить в ограничения.
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Рад, что моя статья оказалась полезна. Зачем вы написали в английский интерфейс?
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Какой rand() на твоей машине? В Windows и Linux они отличаются!
  • 14 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Привет, Миша. А то ты не знаешь :). Linux, я тогда не подумал сделать универсальный rand.
14 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Для создания временного файла лучше использовать tmpfile (http://cplusplus.com/reference/clibrary/cstdio/tmpfile/) или tmpnam (http://cplusplus.com/reference/clibrary/cstdio/tmpnam/). Также можно временный файл удалить в конце или через atexit.
14 лет назад, # |
Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится
> Вот и первый fail. cin считывает числа медленно. Раза в 4 медленнее, чем все остальное. Если вам в программе требуется считать миллион чисел, готовьтесь потратить на это 0.8 секунд cin-а. А возможно и больше.

> cin считывает символы совсем медленно. У меня уходило 1.2 секунды на каждые 10Мб.

Это потому что вы неправильно используете потоки для считывания... Попробуйте так:

void test_ifstream_int() {
	int cur = clock();
	ifstream ifs("temp.txt", ifstream::in);
	for(int i = 0; i < N; i++) {
		int t;
		ifs >> t;
		if(t != a[i]) {
			fprintf(stderr, "Fail with ifstream\n");
			exit(1);
		}
	}
	ifs.close();
	fprintf(stderr, "Test: (ifstream, %d ints) %.2lfc\n", N, (clock() - cur + .0) / CLOCKS_PER_SEC);
}

ну и, соответственно так:
void test_ifstream_char() {
	int cur = clock();
	ifstream ifs("temp.txt", ifstream::in);
	for(int i = 0; i < N; i++) {
		char t;
		ifs >> t;
		if(t != s[i]) {
			fprintf(stderr, "Fail with ifstream\n");
			exit(1);
		}
	}
	ifs.close();
	fprintf(stderr, "Test: (ifstream, %d chars) %.2lfc\n", NC, (clock() - cur + .0) / CLOCKS_PER_SEC);
}

Результат:
Test: (cin, 10000000 ints) 6.04c
Test: (ifstream, 10000000 ints) 2.08c
Test: (cin, 100000000 chars) 9.43c
Test: (ifstream, 100000000 chars) 0.19c

Просто использовать небуферизированный ввод для чтения 100МБ - это как-то не по-программистски. ;)



> Есть и еще один сюрприз. Он выкидывает whitespace. Даже когда считывает один символ. Про это надо не забывать. Лечится так: cin >> noskipws;

Может лечится гораздо проще... cin.get(t); вместо cin >> t; - заодно и производительность вырастает.
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Гораздо проще - понятие растяжимое. К примеру, у меня в программе символ считывается в 30-40 местах, тогда уж лучше noskipws, чем везде переделывать.
13 лет назад, # |
  Проголосовать: нравится +1 Проголосовать: не нравится
А как в timus 1000 задачу за 0.001 сдают ? Особый ввод вывод ?
  • 13 лет назад, # ^ |
      Проголосовать: нравится +4 Проголосовать: не нравится
    Раньше было можно, так как программы, работающие неподсчётно быстро, получали время 0.001 (а теперь минимум - 0.015)
13 лет назад, # |
  Проголосовать: нравится +1 Проголосовать: не нравится
После добавления в начало main() шаманства для ускорения потоков -- "std::ios_base::sync_with_stdio(false);", программа начала падать:
===
Test: (printf, 10000000 ints) 2.45c
Test: (cout, 10000000 ints) 3.08c
Test: (write, 10000000 ints, 104827485 chars) 3.13c + 0.31c
Fail with scanf
===
Строка компиляции: g++ -Wall q.cpp -o q
g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3
Никто не в курсе почему такое происходит и как с этим бороться?
Если закомментить падающие методы, то, как и ожидалось, потоки показывают примерно такую же производительность, что и scanf/printf.
  • 13 лет назад, # ^ |
      Проголосовать: нравится +1 Проголосовать: не нравится
    Вопрос снят.
    std::ios_base::sync_with_stdio(false), как видно из названия, отключает синхронизацию со стандартными потоками.
    С другой стороны printf() у меня работает нормально даже с отключенной синхронизацией.
    В итоге, чтобы тест прошел с
    std::ios_base::sync_with_stdio(false), пришлось закомментить test_scanf_int(); и test_cout_char();
    Есть предположения почему?
    Главный вопрос: как безопасно ускорять потоки, чтобы как минимум можно было использовать printf().
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится
Много и трудно мне пришлось бороться за производительность C/C++ ных программ на разных платформах, начиная от тех у которых аж по 1кб оперативки... И я одно скажу - обязательно нужно указывать компилятор, указывать опции оптимизации с которыми выполнялась проверка... Ну и всё равно интерес в этом сравнении останется довольно академическим... ;-)
  • 13 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится
    Академическим, как и многое на этом сайте.
  • 13 лет назад, # ^ |
      Проголосовать: нравится -6 Проголосовать: не нравится

    У меня есть практическая статья на эту тему, правда больше для новичков и про текстовые файлы. Советы и приёмы использования C++ I/O

    • 13 лет назад, # ^ |
      Rev. 2   Проголосовать: нравится +10 Проголосовать: не нравится

      Раз уж поднялась эта древняя тема.. По советам по ссылке выше

      Вот такая вот конструкция while (!std::getline(inf, name, '|').eof()) обычно не используется. Короче, да и корректнее while (std::getline(inf, name, '|'))

      • 13 лет назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        И чем же это корректней?

        • 13 лет назад, # ^ |
            Проголосовать: нравится +9 Проголосовать: не нравится

          Тем, что читает, пока может прочитать, а не пока не конец файла.

          • 13 лет назад, # ^ |
              Проголосовать: нравится -7 Проголосовать: не нравится

            getline() возращает поток, а не bool. То что C++ даёт возможность приводить всё что угодно к bool радует, в основном, любителей писать "магический код", вроде такого

            if (w) { // CHip and DAle }

            Заставляющий читающего вспоминать все слова что он знает на 'w', такие что могут быть true/false, вместо того что написать нормально

            if (thread_worker != NULL) { // banana banana }

            Что еще хуже, ваша замена меняет смысл. Проверяя eof() автор соглашается выйти из цикла только в случае eof(). Если произойдет другая ошибка, её можно обработать в теле цикла, и продолжить чтение, т.к. ошибка может быть в конкретных данных (а не во всех) или во временных обстоятельствах.

            • 13 лет назад, # ^ |
                Проголосовать: нравится +20 Проголосовать: не нравится
              1. Есть вещи, которые становятся в языке идиомами, и их использование для профессиональных программистов не выглядит чем-то магическим.

              2. В приведенном по ссылке коде в теле цикла нет никаких проверок. Поэтому, если произойдет другая ошибка, то он останется в цикле навсегда.

              http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5

              • 13 лет назад, # ^ |
                  Проголосовать: нравится +8 Проголосовать: не нравится

                Частично соглашусь с Petrosian.

                В идеале мои собственные функции работы с потоками возвращали бы количество считанных байт/символов. Если это неприменимо (например, для чисел), пусть результатом будет bool успешности считывания.

                Почему приходится вызывать 2 функции вместо одной (например, gcount после getline) для меня не очень понятно.

                Но приходится работать с тем, что есть. И eof действительно недостаточно надёжная функция.

»
13 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Test: (printf, 10000000 ints) 2.15c Test: (cout, 10000000 ints) 2.36c Test: (write, 10000000 ints, 104827485 chars) 3.14c + 0.30c Test: (scanf, 10000000 ints) 3.22c Test: (fwrite, 10000000 ints, 104827485 chars) 3.14c + 0.41c Test: (cin, 10000000 ints) 8.65c Test: (printf, 100000000 chars) 2.04c Test: (scanf, 100000000 chars) 7.30c Test: (cout, 100000000 chars) 6.61c Test: (cin, 100000000 chars) 9.88c Test: (putchar, 100000000 chars) 2.10c Test: (getchar, 100000000 chars) 1.66c Test: (read, 100000000 chars) 0.04c + 0.79c Test: (fread, 100000000 chars) 0.04c + 0.79c

»
12 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Hi, I found that by adding ios_base::sync_with_stdio(false); cin.tie( static_cast<ostream*>(0) );

cin performance boosts drastically. However, it makes it work wrong when used along stdio.

  • »
    »
    12 лет назад, # ^ |
    Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

    ios_base::sync_with_stdio(false) turns off synchornization between stdio and iostream, iostream standard stream objects may operate independently of standard C streams, and this leads to unexpectedly interleaved characters.

    Try to turn on and turn off synchronization between calling tests.

»
12 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Если не ошибаюсь, можно сделать такую штуку: cin.sync_with_stdio(false); cout.sync_with_stdio(false); Тогда cin и cout будут работать гараздо быстрее.

  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Да ладно?

  • »
    »
    12 лет назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Можно заменить на одну строчку

    ios_base::sync_with_stdio(0);
    
  • »
    »
    12 лет назад, # ^ |
    Rev. 3   Проголосовать: нравится +17 Проголосовать: не нравится

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

    Тогда бы вы, например, узнали, что ваши 2 строчки делают одно и тоже 2 раза. Что эквивалентно тому что сделать 1 раз. Собственно, вызывают статический метод, объект которому не нужен