Я скоро забуду, как программировать. А может, и не забуду -- талант ведь вроде не пропьёшь? Но, пока не забыл, хочу написать.
1. В Паскале есть write и writeln. В качестве аргументов можно передать произвольное количество разнообразных переменных и констант, разделённых запятыми, и тебе всё это напечатают. Тривиальный пример:
x := 5;
write('x is', x);
Понятно, что реализовано это грубовато, через какое-то подобие препроцессора, обрабатывающего именно этот особый случай write/writeln. То, что обычно называют "грязный хак".
2. В Си есть printf, с ним такой номер не пройдёт -- то есть произвольное количество аргументов напечатать можно, но придётся указывать тип каждой переменной, которую ты хочешь напечатать (и, таким образом, косвенно -- их количество). То есть, примерно так:
x = 5;
printf("x is %d", x);
Тут %d как раз и говорит о том, что надо напечатать целое число из переменной, которая идёт следующим аргументом. Вероятно, специально для этой возможности -- печатать произвольное количество аргументов -- в Си и добавили возможность делать функцию с переменным числом аргументов -- varargs. То есть всё-таки пришлось тоже делать какой-то хак, пусть и не очень грязный.
Вообще, когда я в институте после Паскаля начал изучать Си, меня это поразило. Компилятор же знает, что это целое число -- нафига я должен ему это два раза говорить (первый раз при объявлении переменной, второй раз -- когда печатаю). "За то ль я гиб и мёрз в семнадцатом году"? Ну, поразился, поудивлялся, потом привык.
3. В Си-плюс-плюс есть cout, которому можно скормить всё и в любом количестве, примерно как и в Паскале, только синтаксис несколько странный:
x = 5;
cout << "x is" << x;
Те, кто знают Си, понимают << как оператор побитового сдвига влево. Тем, кто знает Си++, известно, что (почти) любой оператор можно переопределить, причём полиморфно (для разных типов данных делать разные действия). Это переопределение ещё называют "перегрузка операторов".
И вот, как только я (много лет назад) узнал, что в Си++ для того, чтобы получить что-то, подобное паскалевскому write, перегрузили оператор побитового сдвига влево -- я содрогнулся. Те, кто понимает, как всё это (классы, виртуальные функции, перегруженные операторы и полиморфизм) работает в Си++, и какая титаническая работа "в недрах" проделывается, чтобы напечатать "x is 5", наверное, тоже содрогаются.
И я всё ещё содрогаюсь! При этом в целом мне С++ как язык нравится. Но вот эти iostreams -- это просто какое-то извращение из извращений, какая-нибудь садомазогеронтопедогомофилия по сравнению с этим -- невинная забава.
PS а всё это я к тому, что часто языки критикуют за нестройность, наличие каких-то особых случаев, исключений -- но порой такие исключения нужны. Вот в варианте нумер 3 обошлись, казалось бы, без исключений -- но такую выгородили конструкцию, что уж, право слово, лучше бы сделали исключение в языке вместо этого.
Page Summary
![]() ![]() ![]() |
С++ iostreams
Исправь паскалевский пример, там ограничители строки — апострофы, а не кавычки. Исправь паскалевский пример, там ограничители строки — апострофы, а не кавычки. Я стесняюсь тебе намекнуть - но ты же знаешь что все эти cout << оптимизируются в очень простой код на стадии компиляции? Особенно если смотреть на gcc4.1 Это потому что авторам того же gcc не до оптимизации iostreams - им бы баги со всем остальным выловить :) Ты таки будешь смеяться, но тесты на производительность cout vs. *printf я проводил при тебе, cout рулит X0:-) |