Глава 3
В этой главе...
Эта глава поможет вам создать свою первую программу C++. (И даже не одну.) Начнем с создания управляемой программы C++. Это дружественное определение дано
разработчиками среды .NET программам, создаваемым для работы в этой среде, и обозначает, что при разработке этих программ предоставляется множество дополнительных возможностей (благодаря CLR) и обеспечивается их корректное выполнение (благодаря правильному управлению памятью и многому другому). Также вы научитесь создавать добрые старые (или стандартные) программы C++, для которых разработчики среды .NET придумали нехорошее название— неуправляемые программы. Но вначале вы научитесь создавать то, что является
основой любой программы C++ — исходные файлы.
Исходные файлы, или файлы реализации с расширением СРР (читается как С Plus Plus) либо С++, содержат в себе основную часть выполняемой программы. Именно здесь определяются функции, данные и ход выполнения программы. (Под ходом выполнения программы подразумевается последовательность, в которой будут выполняться отдельные выражения или части программы.)
Исходные файлы состоят из выражений. Выражением является строка программы, которая дает указание компьютеру выполнить какое-то действие.
Например, приведенная ниже строка является выражением, которое указывает компьютеру, что необходимо вычислить площадь квадрата путем умножения длины стороны на саму себя:
nArea = nSize * nSize;
Можно объединить несколько выражений, заключив их в фигурные скобки ({}). Например, допустим, что есть такое выражение:
if чай горячий, подожди немного;
(Команда if, которая будет более подробно рассмотрена в главе 11, указывает компьютеру на необходимость выполнить какое-то действие в случае, если справедливо некоторое условие.) Если вы хотите, чтобы в это же время компьютер сделал еще какое-то действие, можно набрать такое выражение:
if (чай горячий)
{
подожди немного; просмотри почту;}
Два выражения были объединены с помощью фигурных скобок.
Открывающую и закрывающую фигурные скобки можно также использовать для обозначения начала и окончания функции. Более подробно об этом речь идет в главе 2.
Если для выполнения функции требуется указание параметров, они заключаются в круглые скобки. Например:
if(номер занят)
{
Таким образом, функция подожди точно указывает, сколько нужно подождать, перед тем как еще раз позвонить. Узнать об этом более подробно (не о телефонных звонках, а об использовании параметров), вы сможете, прочитав главу 12.
Итак, подытожим полученные знания об использовании выражений:
Пожалуй, теории пока достаточно. Самое время заняться делом. Начнем с создания нового проекта .NET.
Обратите внимание на рис. 3.1. Если вы хотите создать папку Hello World в какой-
нибудь другой папке, укажите ее название в поле Location (Размещение) или щелкните на
кнопке Browse (Обзор), чтобы открыть окно для поиска этой папки.
Рис. З.1. Использование диалогового окна New Project
для создания проекта Hello World
Visual C++ создаст целый набор файлов, принадлежащих одному проекту. Один или несколько создаваемых проектов составляют одну задачу (solution). Более подробно о задачах речь идет в главе 4. Окно Solution Explorer (Разработчик задач), показанное на рис. 3.2, отображает файлы, из которых состоит проект Hello World.
Рис. З.2. В окне Solution Explorer можно увидеть файлы, используемые данным проектом
Все эти файлы были созданы для того, чтобы можно было реализовать простую программу, отображающую на экране сообщение Hello World. Чтобы увидеть исходные коды программы, дважды щелкните в окне Solution Explorer на значке HelloWorld. cpp. Этот файл расположен в папке Source Files (Исходные файлы) проекта Hello World.
К счастью, эта простая программа, отображающая на экране сообщение Hello World, может быть создана автоматически. Для этого выполните следующее.
Как только проект будет создан, на экране мелькнет черное окно и сразу же исчезнет. Разумеется, вы не успеете заметить, что было в этом окне. Так случается всегда, когда программа просто выполняет набор каких-то действий и сразу завершает свою работу.
Но как же определить, правильно программа работает или нет? И делает ли она вообще что-то? Сделать это можно разными способами. Из материала главы 16 вы узнаете, как можно использовать отладчик для остановки в самом конце выполнения программы. А далее в этой главе описано, какие коды необходимо добавить, чтобы программа в нужном месте остановилась и ожидала, пока пользователь не даст ей сигнал продолжать работу. По мере приобретения опыта программирования вы оцените полезность и универсальность этого приема.
Ну а пока выполните следующее.
Результат выполнения программы вы можете увидеть на рис. 3.3.
Рис. 3,3. В окне для ввода команд отображается надпись Неllо World
Теперь, когда вы видели результат выполнения программы, давайте посмотрим, каким
int main(void)
образом все это происходит. Для начала компьютер должен определить, с какой строки нужно начинать выполнение программы. Вместо того чтобы нумеровать все строки (как это делалось в старые добрые времена), нужно просто поместить первую строку программы в функцию, именуемую main. С первой строки этой функции начинается выполнение любой программы. Например, вот код простой программы, которая ничего не делает:
{
Выполнение этой программы, как и всех остальных, начинается с функции main.
Поскольку функция main (как и любая другая функция) может использовать в своей работе значения параметров, после ее названия следует пара круглых скобок. (В среде .NET функции обычно используются без каких-либо параметров, поэтому вместо них постоянно набирают слово void, обозначающее факт их отсутствия.) Далее следует открывающая фигурная скобка, которая указывает компьютеру, что за ней идут строки функции main. Закрывающая фигурная скобка говорит о том, что на этом выполнение функции заканчивается.
Вам может показаться непонятным значение слова int , стоящего перед названием функции. Более подробно это рассматривается в главе 12, а пока напомним, что функция— это отдельная подпрограмма, которая может выполнять какие-то действия (например, выводить что-то напечатать), обрабатывать данные или запрашивать какую-либо информацию. Функции могут также возвращать в качестве результата какое-то значение. В С++ main также является функцией, а следовательно, может возвращать какое-нибудь число (integer).
Начало функций main всех управляемых программ C++, коды которых вы встретите в этой книге, выглядит несколько сложнее:
#ifdef _UNICODE
int wmain(void)
#else
int main(void)
#endif
Слово _UNICODE обозначает, что будет использоваться стандарт, предусматривающий ввод с клавиатуры букв и символов других языков, включая азиатские. При компиляции программы может быть выбрана опция, указывающая на то, что программа должна быть откомпилирована с учетом этой возможности.
Конечно, можно создавать программы, которые ничего не будут делать. Но все же лучше, если программа будет в состоянии отобразить что-либо на экране и принять какую-нибудь информацию от пользователя. Есть миллион способов (ну хорошо, пять или чуть больше) сделать это в C++ .NET. Самый простой— использовать для этого функции Console. Они позволяют считывать и отображать сообщения в окне консоли (это то черное окно, которое вы видели при выполнении вашей первой программы). Чтобы отобразить сообщение на экране, используйте команду Console::WriteLine. Дайте ей любой текст, и она высветит его в окне консоли. Например, показанная ниже строка выводит на экран сообщение Hello World (обратите внимание, что текст взят в кавычки):
Console::WriteLine("Hello World") ;
Допустим, вместо этого сообщения нужно отобразить текст Здравствуйте, я ваша тетя! Делается это аналогичным образом:
Console::WriteLine("Здравствуйте, я ваша т е т я ! " ) ;
Чтобы получить информацию от пользователя, используйте команду Console:: ReadLine. Полученная информация будет воспринята как строка текста. (В главе 7 рассматривается, как преобразовать эту информацию к какому-нибудь полезному виду.) Например, приведенная ниже строка заставит компьютер ждать, пока пользователь не введет какой-нибудь текст:
Console::ReadLine();
Console::WriteLine(L"Нажмите Enter, чтобы завершить выполнение программы");
Console::ReadLine();
Функции Console являются частью .NET библиотек CLR, Поэтому, перед тем как их использовать, нужно указать Visual C++ .NET, в каком месте их искать. Сделать это можно с помощью ключевого слова #using. Все функции CLR разбиты на множество динамических библиотек (файлы с расширением DLL). Строки со словом #using сообщают компьютеру, функции каких именно библиотек будут использованы в данной программе.
CLR является аббревиатурой от Common Language Runtime (переводится приблизительно как общий язык выполнения программ), но, как вы уже знаете, представляет собой нечто иное, а именно совокупность библиотек с различными полезными функциями. Название Common Language Runtime было выбрано исходя только лишь из маркетинговых соображений. Кстати, сокращенное название CLR впервые упоминается только в этой книге, так что, если вы произнесете его в разговоре со своими друзьями-программистами и они не поймут, о чем речь, просто посмотрите на них свысока и скажите, что они отстали от жизни.
Большинство основных функций .NET, включая функции Console, расположены в библиотеке mscorlib. Ее название происходит от слов Microsoft core library, что переводится как “корневая библиотека”. Возможно, это поможет вам запомнить ее название. Если в своей программе вы захотите использовать функции библиотеки mscorlib.dll, наберите такую строку:
#using <mscorlib.dll>
Все функции CLR разбиты на отдельные группы, обозначаемые термином namespace (пространство имен). Эти группы состоят из классов (более подробно классы описаны в главе 17). А классы, в свою очередь, содержат функции. Например, функции ReadLine и WriteLine принадлежат классу Console. Класс Console относится к группе System. Таким образом, полное имя функции ReadLine будет выглядеть так:
System: :Console::ReadLine.
Ключевые слова using namespace могут избавить вас от необходимости каждый раз при вызове функции набирать название ее группы. Например, в кодах программы HelloWorld вы могли видеть такую строку:
using namespace System;
Именно благодаря ей далее по тексту программы можно набирать Console::ReadLine вместо System::Console::ReadLine.
Только вы можете точно знать, для чего вами была набрана та или иная команда. Но если коды вашей программы должен будет смотреть еще кто-то, он этого, скорее всего, не поймет. Или, если спустя несколько лет вы захотите внести в программу некоторые изменения, вы уже вряд ли сможете вспомнить, как это все работает. Вот почему так важно использовать комментарии. Комментарии объясняют простым русским языком (или не русским, но обязательно тем, на котором вы привыкли разговаривать), что вы пытались сделать, набирая все эти коды.
В кодах программ, приводимых в этой книге, вы уже сталкивались с комментариями. Распознать их помогут две косые черты (//). Как вы уже могли догадаться, весь текст строки, следующий за ними, является комментарием. (Прочитайте раздел "Старый формат комментариев", чтобы знать, как еще можно создавать комментарии.)
Комментарий может быть выделен в отдельную строку:
//Это строка комментариев.
Также комментарий может завершать собой какую-то строку:
a = 10; //Присвоение переменной значения 10.
Старый формат комментариев
В языке C++ для обозначения комментариев используются две косые черты (//). Ранее в языке С комментарии выделялись несколько иначе; начало комментария обозначалось символами /*, окончание - */. Этот же способ по-прежнему можно использовать в языке C++. Например:
/*Переменной а*/ а = 10; /*присваивается значение 10*/
/* Это старый способ выделения комментариев */
а = 10; /*Присвоение переменной значения 10*/
При использовании старых комментариев самое главное - не забыть обозначить их окончание! Если вы забудете набрать в конце комментария символы */, компилятор проигнорирует все, что было набрано после открытия комментария символами /*.
Обратите внимание, что, когда для создания комментария используются две косые черты (//), никакими специальными символами заканчивать строку не нужно. Две косые черты говорят компилятору, что далее вся строка (и только эта строка) является комментарием. Однако, в отличие от старого формата, если комментарий занимает несколько строк, каждую новую строку должны предварять две косые черты (//).
Теперь, когда вы уже достаточно знаете о принципах создания программ Visual C++ .NET, посмотрите на исходный код созданной ранее в этой главе программы HelloWorld. Он должен быть вам понятен (в нем действительно нет ничего сложного).
//Это код исходного файла приложения VC++
//Программа была создана с использованием мастера
#include "stdafx.h"
#using <mscorlib.dll>
using manespace System;
//С этой строки начинается выполнение программы
#ifdef _UNICODE
int wmain(void)
#else
int main(void)
#endif
{
Console::WriteLine("Hello World");
return 0;
}
Как видите, программа начинается с комментариев. Далее следуют строки с исключевыми словами #using и using namespace, определяющие способ использования CLR. Затем, после еще одного комментария, следуют коды функции main, с которых, собственно, и начинается выполнение программы. На экране будет отображена надпись Hello World, сразу после чего выполнение программы прекратится. Строка return 0 говорит о том, что функция main возвращает нулевое значение. Вы можете пока не обращать на нее внимания.
Строки бывают разными
В компьютерной терминологии текстовое значение, такое как "Hello World", называется строкой (string). При использовании строк перед ними можно добавлять специальные буквы, предоставляющие компьютеру дополнительную информацию. Например, если строка должна быть интерпретирована как набор международных символов (Unicode), наберите перед ней букву L:
Console::WriteLine(L"Hello World");
Строки Unicode могут содержать в себе любые международные символы, включая символы японского алфавита. Однако в языках .NET, если вы не укажете, что строка содержит символы других алфавитов, она все равно будет преобразована к строке Unicode в процессе выполнения программы. Поэтому самостоятельно указывать, что строка является строкой Unicode, особого смысла не имеет.
Намного разумнее набрать перед текстовым значением букву s:
Console::WriteLine(S"Hello World");
Это будет сигналом компьютеру использовать встроенный класс string, что предоставит вам дополнительные возможности по обработке этих данных.
Теперь добавим некоторые изменения к программе HelloWorld. Для начала обозначьте все строки как строки .NET (поставьте перед ними буквы S). Затем добавьте в конце программы несколько команд, которые позволят выполнять ее, находясь в среде разработки Visual С++ .NET:IDE, и видеть результат выполнения до того, как окно исчезнет с экрана. Итак, окончательный код программы должен выглядеть следующим образом:
Console::WriteLine(S"Hello World");
//Ожидание. Пока пользователь не решит продолжить программу
Console::WriteLine(S"Hit the enter key to stop the program");
Console::ReadLine();
Однако, перед тем как приступить к программированию, познакомьтесь еще о некоторыми тонкостями терминологии. В среде .NET доступ к встроенным функциям обеспечивает CLR. В обычном C++ функции расположены в различных библиотеках. В .NET нужно использовать ключевое слово #using, чтобы получить доступ к функциям CLR. В C++ для использования других функций нужно подключить заголовочный файл (header file). Заголовочным файл сообщит компьютеру названия и характеристики подпрограмм из других файлов или библиотек, которые вы намериваетесь использовать. Например, предположим, что вы хотите использовать функцию foo, хранящуюся в библиотеке. Для этого необходимо подключить заголовочный файл, который сообщит компьютеру, что foo— это подпрограмма, и укажет, данные каких типов потребуются для ее выполнения.
Если вы создаете подпрограмму в одном файле и хотите использовать ее затем в другом файле, нужно создать заголовочный файл, описывающий эту подпрограмму. Подключая этот файл к другим файлам, вы можете повторно использовать созданную подпрограмму в других программах.
Для чего нужен компоновщик
Когда вы определяете внешнюю функцию в заголовочном файле, вы указываете только ее название и параметры, но не название самой библиотеки или исходного файла, в которых она может храниться. Компилятор генерирует список всех используемых программой функций, куда входят названия как внешних функций, так и функций, созданных в самой программе. После компилятора в действие вступает компоновщик (linker).
Помимо прочего, компоновщик проверяет список названий всех требующихся для выполнения программы функций и ищет сами функции в других файлах и библиотеках. Если функция найдена, она используется автоматически. Если компоновщик не может найти функцию, он выдает сообщение об ошибке.
Если вы хотите сообщить какую-то информацию пользователю, ее нужно отобразить на
экране монитора. Работая с .NET, мы использовали для этого команду
Console: :WriteLine. В неуправляемых программах вместо нее используется выражение cout (читается как see-out— "вижу-вывожу"). Если вы даете выражению cout какое-нибудь значение, оно с радостью выводит его на экран. Чтобы передать выражению cout значение, используется команда <<.
Как и в случае создания программ .NET, текстовые значения должны быть взяты в кавычки.
Ниже приведено несколько примеров. В каждом случае все, что следует за командой
cout<< будет выведено на экран.
// Отображается Apollo 16
// Отображается Hello World
cout << "Hello World";
cout << "Apollo 16";
Можно также одной командой отобразить сразу несколько значений, как это сделано в следующих двух примерах. В первом примере отображается текст "Меня зовут " и "Мишель" (это две разных строки). Во втором примере отображается одновременно текст "Apollo " и число 16.
//Отображается Apollo 16
//Отображается текст Меня зовут Мишель
cout << "Меня зовут " << "Мишель";
cout << "Apollo " << 16;
Как видите, комбинировать текст и числа очень легко. Обратите также внимание, что каждое выражение заканчивается точкой с запятой.
Ну как? Не правда ли, в C++ отображать информацию на экране еще проще, чем в
среде .NET?
Специальные символы
Есть целый набор специальных символов, определяющих параметры печати.
\n Продолжить со следующей строки
\t Табуляция
\b Вернуться на один знак назад
\f Продолжить со следующей страницы
\\ Отобразить символ \
\' Отобразить символ '
\" Отобразить символ "
Например, нужно отобразить на экране сообщение "И снова "Здравствуйте!"".
Для этого наберите такую команду :
cout « "И снова \"Здравствуйте!\"\n";
Как видите, специальных символов не так уж мало. Наиболее часто используемым среди них является символ \n, который выполняет переход на новую строку. (Его иногда так и называют — символ новой строки.) Например, если вы хотите, чтобы выводимый текст отображался в разных строках, наберите такие команды:
//Отображается Apollo 16
//Отображается текст Меня зовут Мишель
cout << "Меня зовут " << "Мишель\р.";
cout << "Apollo " << 16 << " \ n " ;
Символ \n интерпретируется так же, как и обычные символы. Другими словами, вы можете использовать его отдельно (как во втором примере: 16 << "\n”) либо в любом сочетании с другими символами (как в первом примере: Мишель \n). Можно набрать нечто вроде Мишель, в результате чего в одной строке будет отображено "Миш", а во второй строке “ель". В отличие от обычных символов, \n не отображает ничего на экране; он используется только для перехода на новую строку.
Поначалу использование всех этих стрелочек (<<) и всяких специальных символов может показаться крайне неудобным и слишком запутанным, но вскоре вы сами удивитесь, насколько быстро к ним привыкнете.
cout << "Меня зовут Джимми" « endl;
cout « "Мой номер " << 12 << endl;
В отличие от \n, функцию endl нельзя использовать в конце или в середине строки. Поэтому при необходимости нужно просто разделить строку на две части, как показано ниже:
Cout « "Меня зовут " << endl << "Джимми" « endl;
Хотя использовать функцию endl несколько сложнее, чем символ \n, код с ее участием намного проще для чтения и понимания.
Считывать информацию, набранную пользователем, так же просто, как и отображать данные на экране. Для этого используются функция cin и команда >>. (название функции произносится как "sin", что означает "see-in" — "вижу-получаю"). Например, если нужно, чтобы пользователь указал свой номер телефона, наберите;
cin » НомерТелефона;
Обычно информация, поступающая от пользователя, сохраняется как значение какой-
нибудь переменной. Об использовании переменных речь идет в главе 8.
Полученных вами знаний уже почти достаточно, чтобы вы могли приступить к созданию своей первой неуправляемой программы. Однако функции cout и cin являются частью библиотеки, и, как отмечалось ранее в главе, чтобы использовать функции библиотек, нужно подключить к программе заголовочный файл. Делается это с помощью команды #include.
Все команды, которые начинаются с символа #, называются директивами препроцессора.Этим длинным названием обозначаются команды, дающие указания компилятору. Директивы препроцессора не преобразуются в коды программы, они лишь управляют процессом компиляции.
Например, директива #include указывает компилятору, какой файл нужно подключить
к программе. Описания функций cin и cout хранятся в файле, именуемом iostream.h.(Расширение .h является стандартным для заголовочных файлов.) Чтобы эти описания стали доступными, наберите в начале программы такую строку:
#include <iostream.h>
Эта команда подключает файл с описаниями cin, cout и многих других функций, являющихся частью библиотеки iostream.
Обратите внимание, что строки с директивами препроцессора не заканчиваются точкой с запятой. Отдельная директива препроцессора может состоять только из одной строки. Поэтому компилятор сам знает, что окончание строки означает окончание директивы.
Почему настоящие хакеры вместо < > чаще набирают""
За командой # include следует название заголовочного файла. Если этот файл является стандартным, т.е. тем, который поставляется вместе с компилятором, возьмите его название в угловые скобки (< >):
#include <iostream.h>
Компилятор знает, где искать свои собственные заголовочные файлы, и сразу переходит к нужной директории. Если вы хотите подключить заголовочный файл, который вы создали сами, возьмите его название в кавычки. Это будет указанием компилятору начать поиск в текущей папке, а в случае необходимости
продолжить в папке со стандартными заголовочными файлами:
#include "foo.h "
Можно также указать полный путь к файлу:
#include "\michael\jukebox\foo.h"
Язык C++ имеет очень мало встроенных команд, но зато очень много библиотечных функций. Многие библиотечные функции доступны всем компиляторам C++, поэтому вы всегда можете получить к ним доступ и использовать их в своей работе. Другие функции являются надстройками (add-ons). Можно, например, приобрести дополнительные библиотеки, содержащие функции, для проведения статистических вычислений или для обработки изображений.
Теперь вы знаете достаточно для того, чтобы создать версию программы HelloWorld, написанню на стандартном C++. А потому приступим.
РИС. 3.4. Мастер Win32 Application Wizard поможет вам создам про-
грамму HelloWorld2
\\ HelloWorld2
\\ Отображение на экране слов Hello World
\\ Неуправляемая
#include "stdafx.h"
#include <iostream.h>
int _tmain(int argc, _TCHAR* argv[])
{
//Write to the screen
cout << "Hello World\n";
return 0;
}
Синтаксические ошибки
Если вы что-то неправильно наберете или неверно используете команду C++, компилятор сообщит, что вы допустили синтаксическую ошибку. Это будет означать, что компилятор либо не может распознать набранное вами слово, либо вы что-то пропустили при использовании команды. Синтаксические ошибки бывают
самых разных видов. Большинство из них, а также способы их устранения описаны в главах 23 и 24.
Вы должны помнить еще по программе HelloWorld, что интегрированная среда IDE не позволила увидеть результат выполнения этой программы. С тех пор ничего не изменилось, поэтому программу HelloWorld2 также придется выполнять через окно ввода команд, предварительно построив ее. Для этого выполните ряд действий.
Рис. З.5. Выполнение программы HelloWorld2 в окне для ввода команд
Назад |
Начало урока |
Вверх |
Вперед
Содержание