int main(int argc, char **argv)
{
size_t wc;
4. Если пользователь запустит программу в оболочке и укажет имя файла (например, $ ./count_all_words some_textfile.txt
argv
и открыть, чтобы передать новый поток ввода в функцию wordcount
: if (argc == 2) {
ifstream ifs {argv[1]};
wc = wordcount(ifs);
5. В случае запуска пользователем программы без параметров мы предполагаем, что входные данные появятся из стандартного потока ввода:
} else {
wc = wordcount(cin);
}
6. На этом все, просто выведем количество слов, сохраненное в переменной wc
cout << "There are " << wc << " words\n";
};
7. Скомпилируем и запустим программу. Сначала передадим данные из стандартного потока ввода. Можно либо выполнить вызов echo, передав туда несколько слов, либо запустить программу и ввести несколько слов с клавиатуры. Во втором случае можно прервать ввод нажатием комбинации клавиш Ctrl+D
. Так выглядит вызовecho
:$ echo "foo bar baz" | ./count_all_words
There are 3 words
8. Если запустить программу и передать ей в качестве входного файла ее файл с исходным кодом, то она подсчитает количество слов, которые содержатся в нем:
$ ./count_all_words count_all_words.cpp
There are 61 words
Как это работает
Здесь особо нечего добавить, большую часть программы мы уже объяснили при реализации, поскольку сама программа очень короткая. Единственный факт, который можно немного пояснить: std::cin
std::ifstream
взаимозаменяемы. cin
имеет тип std::istream
, а std::ifstream
наследует от std::istream
. Взгляните на диаграмму наследования, приведенную в начале этой главы (см. рис. 7.1). Таким образом, они полностью взаимозаменяемы, даже во время работы программы.
Форматируем ваши выходные данные с помощью манипуляторов потока ввода-вывода
Во многих случаях недостаточно просто вывести строки и числа. Иногда числа нужно вывести в десятичной системе счисления, иногда — в шестнадцатеричной, а иногда — в восьмеричной. В одних ситуациях перед шестнадцатеричными числами префикс "0x"
При выводе чисел с плавающей точкой существует множество моментов, на которые можно повлиять. Нужно ли всегда выводить их с одинаковой точностью? Надо ли выводить их вообще? Или, может быть, требуется научное представление?
Помимо представления и системы счисления нужно также представить пользователю выходные данные в «аккуратном» виде. Некоторые выходные данные можно поместить, например, в таблицы, чтобы сделать их максимально читабельными.
Все это можно сделать с помощью потоков вывода. Некоторые из этих настроек важны и при преобразовании входных значений. В данном примере мы познакомимся с так называемыми
Как это делается
В этом примере мы выведем на экран числа, используя совершенно разные настройки форматов, чтобы ознакомиться с манипуляторами ввода-вывода.
1. Сначала включим все необходимые заголовочные файлы и объявим об использовании пространства имен std
#include
#include
#include
using namespace std;
2. Далее определим вспомогательную функцию, выводящую на экран целое число в разных стилях. Она принимает ширину отступа и символ-заполнитель, которым по умолчанию является ' '
void print_aligned_demo(int val,
size_t width,
char fill_char = ' ')
{
3. С помощью setw
123
с шириной 6
получим " 123"
или " 123"
. Можно управлять тем, с какой стороны будут вставлены символы-заполнители, используя std::left
, std::right
и std::internal
. При выводе чисел в десятичной форме манипулятор internal
выглядит похожим на right
. Но если мы выведем значение 0x1
, например с шириной 6
и манипулятором internal
, то получим "0x 6"
. Манипулятор setfill
определяет, какой именно символ будет применен для заполнения. Мы попробуем разные стили. cout << "================\n";
cout << setfill(fill_char);
cout << left << setw(width) << val << '\n';