В строке 4 массив argv используется для вывода числа установленных аргументов командной строки. Всего их оказалось семь, включая имя программы.
В строках 5 и 6 задается цикл for, который выводит значения всех аргументов командной строки по отдельности, обращаясь к ним по имени массива argv с указанием смещения [i]. Для вывода значений аргументов используется объект cout.
Листинг 16.20 является переписанной версией листинга 16.18, в которой имя файла задается как аргумент командной строки.
Листинг 16.20. Использование аргументов командной строки
1: #include
2:
3: class Animal
4: {
5: public:
6: Animal(intweight, long days):itsWeight(weight), itsNumberDaysAlive(days)( }
7: ~Animal(){ }
8:
9: int GetWeight()const { return itsWeight; }
10: void SetWeight(int weight) { itsWeight = weight; }
11:
12: long GetDaysAlive()const { return itsNumberDaysAlive; }
13: void SetDaysAlive(long days) { itsNumberDaysAlive = days; }
14:
15: private:
16: int itsWeight;
17: long itsNumberDaysAlive;
18: };
19:
20: int main(int argc, char *argv[]) // возвращает 1 в случае ошибки
21: {
22: if (argc != 2)
23: {
24: cout << "Usage: " << argv[0] << " " << endl;
25: return(1);
26: }
27:
28: ofstream fout(argv[1],ios::binary);
29: if (!fout)
30: {
31: cout << "Unable to open " << argv[1] << " for writing.\n";
32: return(1);
33: }
34:
35: Animal Bear(50,100);
36: fout.write((char*) &Bear,sizeof Bear);
37:
38: fout.close();
39:
40: ifstream fin(argv[1],ios::binary);
41: if (!fin)
42: {
43: cout << "Unable to open " << argv[1] << " for reading.\n";
44: return(1);
45: }
46:
47: Animal BearTwo(1,1);
48:
49: cout << "BearTwo weight: " << BearTwo.GetWeight() << endl;
50: cout << "BearTwo days: " << BearTwo.GetDaysAlive() << endl;
51:
52: fin.read((char*) &BearTwo, sizeof BearTwo);
53:
54: cout << "BearTwo weight: " << BearTwo.GetWeight() << endl;
55: cout << "BearTwo days: " << BearTwo.GetDaysAlive() << endl;
56: fin.close();
57: return 0;
58: }
Результат:
BearTwo weight: 1
BearTwo days: 1
BearTwo weight: 50
BearTwo days: 100
Анализ:Объявление класса Animal аналогично представленному в листинге 16.18. Однако в этом случае пользователю не предлагается ввести имя файла, а используется аргумент командной строки. В строке 2 объявляется функция main(), принимающая два параметра: количество аргументов командной строки и указатель на массив символов, в котором сохраняются аргументы командной строки.
В строках 22—26 проверяется, соответствует ли установленное число аргументов ожидаемому. Если пользователь забыл ввести имя файла, то выводится сообщение об ошибке:
Usage TestProgram <���имя файла>
После этого программа завершает свою работу. Обратите внимание, что при выводе имени программы используется не константная строка, а значение argv[0] . Данное выражение будет правильно выводить имя программы, даже если оно будет изменено после компиляции.
В строке 28 программа пытается открыть двоичный файл с указанным именем. Однако, вместо того чтобы копировать и хранить имя файла во временном массиве, как это было в листинге 16.18, его можно задать в командной строке и затем возвратить из argv[1 ].
Точно так же имя файла возвращается в строке 40, где этот файл открывается для ввода данных, и в строках 25 и 31 при формировании сообщений об ошибках открытия файлов.
Сегодня вы познакомились с потоками и глобальными объектами cout и cin. Основное предназначение объектов istream и ostream состоит в инкапсулировании буферизированого ввода и вывода данных на стандартные устройства ввода-вывода.
В каждой программе создается четыре стандартных потоковых объекта: cout, cin, cerr и clog. Однако в большинстве операционных систем эти объекты можно переадресовывать.
Объект cin класса istream используется для ввода данных обычно вместе с перегружаемым оператором ввода (>>). Объект cout класса ostream используется для вывода данных в комбинации с оператором вывода (<<).
Стандартные объекты ввода-вывода включают много других функций-членов, например get() и put(). Поскольку эти методы возвращают ссылки на объект потока, несколько вызовов функций можно объединять в одном выражении.
Для настройки работы объектов потока используются манипуляторы. С их помощью можно устанавливать не только опции форматирования и отображения, но и многие другие атрибуты объектов потока.
Обмен данными с файлами осуществляется с помощью классов fstream, производных от класса iostream. Кроме обычных операторов ввода и вывода, эти классы поддерживают использование функций read() и write(), позволяющих считывать и записывать целые объекты в двоичные файлы.
Как определить, когда использовать операторы ввода и вывода, а когда другие функции-члены классов потока?
В целом операторы ввода и вывода проще в использовании, поэтому в большинстве случаев лучше обращаться именно к ним. В некоторых других случаях, когда эти операторы не справляются со своей работой (например, при вводе строки из слов, разделенных пробелами), можно прибегнуть к использованию других функций.
Читать дальше