Пока не компилируйте и не запускайте. Давайте сейчас разберемся, что же мы напрограммировали. Наша программа будет «продвинутой версией» программы из прошлой статьи, тоже строчку текста выводить будет, только несколько иначе :) При вызове из консоли программа будет принимать два параметра: первый - это строка текста, которую надо будет вывести, а второй - сколько раз надо будет её вывести.
Про iostream вы уже знаете, а вот cstdlib подключается для того, чтобы воспользоваться функцией atoi. Эта функция имеет во какую сигнатуру (см. также файл stdlib.h):
int atoi (const char* p);
Она преобразует строку p, представляющую собой численное значение (только из цифирей состоящую) в само численное значение. То быть строка ‘12345’ будет преобразована в 12345. Весьма полезная функция. Есть ещё две: atof и atol, преобразующие строчку в double и long соответственно. Если же строчка не представляет собой число (например ‘123g4a’) то будет возвращён 0. Вот как раз с помощью функции atoi мы преобразуем символьную строчку argv[2] в целое av2. Иначе ведь не прокатит! Так вот, преобразуем, а потом циклом for выводим av2 раз строку argv[1]. Кто не знает циклы - во-первых пора бы уже знать, а во вторых - идите в раздел «Язык программирования С++», постараюсь найти время и написать о них. Теперь попробуйте скомпилировать и запустить на выполнение программу. - Что такое? Вроде всё скомпилировалось, скомпоновалось, а когда начала запускаться программа нам вдруг сообщают об ошибке и предлагают отправить отчёт к какой-то там матери!... Неужели Matrix has us?! - Спокуха! Давайте разберёмся. Программа должна принять два параметра, а откуда она их возьмёт, когда мы запускаем её из среды Visual C++, никаких параметров не указывая? Вот и именно, что ниоткуда. Отсюда и лажа. Мы сейчас вот что сделаем: зайдём в консоль и запустим нашу прогу оттуда. Кто не знает, как в консоли работать (в MS-DOS), я здесь объяснять не буду ес-сно, почитайте там Фигурнова какого-нибудь… Итак давайте запустим теперь прогу из консоли, что называется, вручную и с параметрами. Командная строка при этом будет иметь, к примеру, такой вид:
D:Program FilesMicrosoft Visual StudioMyProjectsListing2Release>listing2 We_have_Matrix! 3
Только обратите внимание на то, что We_have_Matrix! пишем не через пробел, а через символ подчёркивания, т.к. пробелами разделяются параметры и прога так не поймёт (поймёт неправильно). Запускаем и упиваемся тожеством очередной маленькой победы над Матрицей! Но на самом то деле это ещё не победа, боя то никакого почти не было: так, три раза на заборе написали что-то, да и всё. К бою ещё подготавливаться и подготавливаться надо! А посему гружу дальше. Выходит, программа прекрасно работает из консоли. А как же быть с VC++? Да, я мог (и должен был), конечно, предусмотреть в программе возможность получения не только двух параметров командной строки, но и другого их числа. Но не сделал этого намеренно. Чтобы попроще. А если не понарошку, то учитывать такие нюансы необходимо. Ведь и из консоли мы можем программу вызвать, не указав параметры или указав непредвиденное число параметров. Поэтому надо в программе это дело обслужить: просто условным оператором или через исключения организовать выход проги из такого неудобного положения. Но на этом останавливаться не будем: нам ещё 2 варианта заготовок консольных приложений надо рассмотреть и разобрать.
A “Hello World!” application
Этот вариант, сразу скажу, практически бесполезен - чисто демонстрационная вещь (показуха одна!). Эта заготовка точно такая же, как и предыдущая (A simple application), с той лишь разницей, что она ещё и выводит с помощью функции printf строчку “Hello World!” на экран. Это различие заключается в одной строчке кода:
printf("Hello World!n");
Мы это с вами уже умеем, только с помощью не printf, а используя cout. Давайте, что ли, про функцию printf маленько и поговорим. Чтобы её использовать, нам надо подключить . Но не беспокойтесь об этом: посмотрите файл stdafx.h - среда уже сделала это за нас! Ну ещё бы монитор тряпочкой протирала и вообще цены бы ей не было! :) Функция printf осталась от языка С. Тем не менее, её очень часто можно встретить. Тем более что, как я уже говорил, хороший код на С будет прекрасно компилироваться и работать в компиляторе для С++. Даже вместе с кодом на С++ (правда в таком случае проблема совместимости всё же время от времени возникает, но она легко решаема). Из этого всего следует, что хотя бы в общих чертах рассмотреть функцию printf нам надо. Сигнатура у неё такая:
int printf(const char* , …)
Возвращает она нам количество выведенных символов. В случае строки “Hello World!” их будет 13 (не забываем про NULL в конце строки). В качестве параметра она принимает строку в стиле С (массив символов) (или же непосредственно строку в кавычках), причём их может быть несколько, тогда просто через запятую перечислим:
printf("Hello”, “ World!”, “n");
Это также как в cout можете несколько раз использовать << , а в cin >>.
Кстати, кто ещё не в курсе, для ввода в языке С++ используется такая хреновина: std::cin >> и дальше имя переменной, в которую будет записано то, что мы вводим. В С этим занимается функция gets() и др.
Также в printf могут указываться спецификаторы преобразования (это например когда мы значение какой-нибудь переменной хотим вывести), но подробно разговор о функции printf и потоках ввода вывода пойдёт в разделе «Язык программирования С++», там этой теме будет посвящена отдельная статья. Здесь же замечу еще, что использование функции printf нежелательно. Хотя, возможно с ней и проще обращаться, чем с cout и cin, но она имеет большой недостаток: плохой контроль типов данных (при неявных преобразованиях типов, например), что даже у опытных программистов становится иногда причиной досадных ошибок. Поэтому совет: пользуйтесь для ввода/вывода средствами C++!
Переходим к последнему варианту: консольное приложение с поддержкой MFC.
An application that supports MFC
Длянепосвящённых: MFC - Microsoft Foundation Class (базовыеклассы Microsoft). И более ничего об MFC писать сейчас не буду, т.к. MFC мы посвятим не просто статью, а целый раздел! Ладно, так и быть - напишу одной фразой: пакет MFC даёт возможность разрабатывать GUI-приложения (GUI - Graphic User Interface - графический пользовательский интерфейс) для Windows на языке С++ с использованием богатого набора библиотечных классов, причём эти библиотеки являются объектно-ориентированными (помимо инкапсуляции поддерживают наследование и полиморфизм). Однако, поскольку MFC в значительной степени ориентирована на работу с окнами, документами, представлениями и т.д., большая её часть остаётся невостребованной консольным приложением. Тем не менее, она всё равно может оказаться очень полезной!
Итак, выбираем теперь четвёртый вариант и смотрим, что нам сотворила среда Visual C++. Да! На этот раз видно, что поработала малышка! Много чего непонятного (и, надеюсь, понятного тоже) написала! Давайте разбираться…
Во-первых, новые файлы появились: Listing4.h, Listing4.rc, Resource.h.
Listing4.h - файл заголовка для нашего исходника. Пока что у нас здесь вот что: первые две строчки и самая последняя - предупреждение повторного подключения, это чтобы не вышло так, что мы бы включили дважды этот файл в какой-нибудь другой (можете почитать в разделе «Язык программирования С++» про стражи включения). Дальше три строчки - проверка версии MFC. Ну и, наконец, подключение файла Resource.h.
Практически каждое приложение, разрабатываемое в Visual C++, содержит один файл ресурсов, одноимённый с самим приложением и имеющий расширение .rc . В нашем случае это Listing4.rc. В нём находятся описания всех ресурсов нашего приложения. У нас здесь будет только таблица строковых ресурсов. В этом и есть высокое предназначение нашей заготовки - она выводит на экран строчку «Hello from MFC!», оформленную как строковый ресурс. Среда ведь на самом деле может сама (с нашей помощью конечно) объявить все необходимые ресурсы, дать им идентификаторы (уникальные имена), связать идентификаторы с конкретными числовыми значениями и т.д. На самом деле это очень удобно, например, для русификации приложения не понадобиться искать в программном коде места где выводятся строчки, а просто в таблице взять и поменять текст с английского на русский, сохранив при этом все идентификаторы и численные значения. В программном коде-то у нас прописаны идентификаторы. Так что умная среда, обеспечив нам такую политику, может избавить нас от значительного геморроя. И это лишь один пример халявы, которую дарит нам Visual C++. При попытке открыть файл Listing4.rc у нас открывается окошко ResourceView. Тут у нас и есть таблица строк. В ней мы можем изменить строку соответствующую данному идентификатору, или создать новый строковый ресурс, поставив ему в соответствие новый идентификатор. Просекаете логику? То-то!
В файле Resource.h просто, используя директиву #define , каждому идентификатору ставится в соответствие численное значение. Здесь же мы можем его поменять или указать его для нового ресурса.
Попробуйте запустить программу, поздоровайтесь с MFC и убедитесь, что приложение работает. Если поздоровались, значит работает. Между тем в нашем рабочем пространстве появилась папочка «External Dependencies» с файлом basetsd.h внутри. В нём, если хотите знать, нам показывают определения базовых типов данных. Это на случай, если нам вздумается (или придётся) использовать 64-битные типы данных.
Между тем и в уже известных нам файлах произошли значительные изменения. Давайте начнем теперь с файла StdAfx.h. В начале всё те же, что и в Listing4.h стражи включения, далее всё та же проверка версии MFC, дальше идёт строчка:
#define VC_EXTRALEAN // Exclude rarely-used stuff from Windows headers
- она для ускорения процесса компиляции (за счёт отказа от некоторых возможностей)
далее идут строчки с подключением основных MFC-шных файлов: afx.h, afxwin.h, afxext.h, afxdtctl.h, afxcmn.h.
Кстати, если будете программировать, используя MFC, очень советую посмотреть эти заголовочные файлы. Если вы знаете язык С++, то должны увидеть там не фигу, а полезную информацию по MFC-классам и функциям и т.д. Бывает ничуть не хуже справочников. А в качестве справочника очень советую MSDN Library.