Головна Обговорення Лінки Пошук Prykladna СС Прикладна _КОЛЕДЖ 28.07.2026 10:34:16 (EEST=GMT+2)
ACM -
Навігація -
Теми форуму +
Чи знали ви, що... ? (beta) -
Рейтинг найдорожчих гравців Європейських чемпіонатів.
1. Криштіану Роналду (МЮ) - 55 мільйонів євро
2. Лео Мессі (”Барселона”) - 55 мільйонів євро
3. Кака (”Мілан”) - 55 мільйонів євро
4. Стівен Джерард (”Ліверпуль”) - 45 мільйонів євро
5. Уейн Руні (МЮ) - 40 мільйонів євро
6. Дідьє Дрогба (”Челсі”) - 40 мільйонів євро
7. Самуель Ето’о (”Барселона”) - 40 мільйонів євро
8. Френк Лемпард (”Челсі”) - 38 мільйонів євро
9. Роналдіньйо (”Барселона”) - 38 мільйонів євро
10. Златан Ібрагімович (”Інтер”) - 38 мільйонів євро
Події
ПнВтСрЧтПтСбНд
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Перегляд теми
ACM Контестер | Online Judge System | acm.timus.ru
Автор Швидкий ввід\вивід
DixonD
Користувач

Повідомлень: 167
Звідки: ЛНУ ім. Івана Франка
Зареєстрований: 21.10.06
Опубліковано 24-12-2007 18:02
Ні для кого не секрет, що ввід\вивід у С++ через функції scanf, printf працює на порядок швидше, ніж через відповідні потоки cin і cout. Проте не всі знають, що той самий ввід скажімо цілих чисел можна зробити ще швидше, якшо враховувати специфіку вводу. Для цього потрібно використовувати функції getchar\putchar.
Приклад. Нехай нам потрібно зчитати ціле невід'ємне число, то можна написати щось на подобі такої функції:
char ch;

inline void GetInt(int& n)
{
n = 0;
ch = getchar();
while (ch>='0')
{
n = n*10+ch-48;
ch = getchar();
}
}




Інший приклад. Вивід цілого невід'ємного числа:
char st[16];
int top;
inline void PutInt(int n)
{
top = -1;
while (n>9)
{
st[++top] = n%10 + 48;
n/=10;
}
putchar(n+48);
while (top>=0)
putchar(st[top--]);
}




Таким чином швидкість виконання програм, які багато працюють із вводом і/або виводом ЗНАЧНО зростає.
Використовуючи щось подібне до вищенаписаних функцій + оптимізувавши дещо код, я зміг добитися накращого часу виконання на кількох задачах на Тімусі (<a href="http://acm.timus.ru/rating.aspx?space=1&num=1424">1424</a>, <a href="http://acm.timus.ru/rating.aspx?space=1&num=1512">1512</a>, <a href="http://acm.timus.ru/rating.aspx?space=1&num=1373">1373</a>, <a href="http://acm.timus.ru/rating.aspx?space=1&num=1450">1450</a>)

Цікаво почути вашу думку на цю тему.
DixonD 427265719 dixond[злий_пес]acm[на]lviv[на]ua DixonD (Lviv NU) http://dixond.blogspot.com/ Надіслати приватне повідомлення
Автор RE: Швидкий ввід\вивід
webmaster
Головний Адміністратор

Аватар користувача

Повідомлень: 1136
Зареєстрований: 17.03.07
Опубліковано 24-12-2007 22:41
Ця оптимізація відбувається через те, що у С++ ввід/вивід відбувається через регулярні вирази.
Наприклад:
printf("d = %d by %s", dec, str);
той вираз звісно потрібно процесорі розбирати.
Так само, можна написати таке:
printf("%d", dec);
тут також потрібно кожен раз розбирати той вираз, навіть якщо він малий.

Наведені приклади вводу/виводу через getchar/putchar, можна ще оптимізувати наступним чином:
вивести весь вивід у одну стрічку, а потім тільки звичайним виводом (printf("%s", str);). У цьому випадку також процесору потрібно розібрати той вираз, але це буде виконано тільки один раз, а при конструкції getchar/putchar відбувається багато викликів функцій, що потребує певного часу. Звісно ця оптимізація вже не дає такого сильного результату, але.
Приклад:
  1. char str[1000];
  2. int vals[1000];
  3. int N;
  4. ....
  5. int top = -1;
  6. for (int i=0; i < N; i++)
  7. {
  8. int n = vals[i];
  9. while (n)
  10. {
  11. st[++top] = n%10 + '0';
  12. n/=10;
  13. }
  14. st[++top] = ' ';
  15. }
  16. st[++top] = 0;
  17. printf("%s", str);


Змінив(ла) webmaster, 24-12-2007 23:50
brus07 brus07 (Lviv NU) http://acm.lviv.ua Надіслати приватне повідомлення
Автор RE: Швидкий ввід\вивід
Romko
Користувач

Повідомлень: 113
Звідки: mdegree
Зареєстрований: 07.11.06
Опубліковано 24-12-2007 22:42
nice!


Treizzz 7715843 Romko [Lviv NU] Надіслати приватне повідомлення
Автор RE: Швидкий ввід\вивід
DixonD
Користувач

Повідомлень: 167
Звідки: ЛНУ ім. Івана Франка
Зареєстрований: 21.10.06
Опубліковано 24-12-2007 23:16
Хм, по-моєму приклад некоректний, бо
while (n)
{
st[++top] = n%10 + '0';
n/=10;
}




дає наше число в перевернутому порядку. І знову ж таки по-моєму краще виводити puts(str), ніж printf("%s",str); , якшо лишень нам перевод стрічки не заважає.
+даний код для кожного числа дасть зайве ділення, і не буде працювати для нуля:)

Враховуючи наведені міркування мою функцію можна переписати наступним чином:

const int NM=50;
char st[NM];
int top;
inline void PutInt(int n)
{
top = NM - 1;
st[top] = 0;
while (n>9)
{
st[--top] = n%10 + 48;
n/=10;
}
st[--top] = n+48;
puts(st+top);
}


DixonD 427265719 dixond[злий_пес]acm[на]lviv[на]ua DixonD (Lviv NU) http://dixond.blogspot.com/ Надіслати приватне повідомлення
Перейти на форум:
Голосування
Що Ви б хотіли отримати в якості подарунку на змаганні з програмування?

Медалі

настільні ігри

торт

клавіатура, навушники, флешки і т.д.

квитки в кіно

квитки в аквапарк

квитки на пейнтбол

книги

футболки з логотипом змагання

Для участі в голосуваннях Ви повинні залогуватись.
Міні-чат +
Зараз на сайті -
Гостей: 1
На сайті немає зареєстрованних користувачів

Користувачів: 5,103
новачок: NataEvgten
Powered by PHP-Fusion © 2003-2006
LNU ACMania © 2004-2011 e-mail: webmaster@acm.lviv.ua
26,045,731 унікальних відвідувачів
Our projects: ACM Contester, _College.