Главная Обратная связь

Дисциплины:

Архитектура (936)
Биология (6393)
География (744)
История (25)
Компьютеры (1497)
Кулинария (2184)
Культура (3938)
Литература (5778)
Математика (5918)
Медицина (9278)
Механика (2776)
Образование (13883)
Политика (26404)
Правоведение (321)
Психология (56518)
Религия (1833)
Социология (23400)
Спорт (2350)
Строительство (17942)
Технология (5741)
Транспорт (14634)
Физика (1043)
Философия (440)
Финансы (17336)
Химия (4931)
Экология (6055)
Экономика (9200)
Электроника (7621)


 

 

 

 



Более сложные элементы языка



Оператор switch (переключатель)

Часто бывает необходимо выбрать из многих альтернатив одну. Чтобы не строить длинные конструкции типа if...else, в Си имеется специальный оператор-переключатель. Его формат:

switch(выбор) {

case знач1: оператор1; break;

case знач2: оператор2; break;

.............................

case значN: операторN; break;

default : операторK;

}

Оператор switch получает значение “выбор” и сравнивает его с каждым значением “ЗначN” метки case. Если они совпадают, начинается выполнение операторов данной метки, которое продолжается либо до ближайшего оператора break, либо до конца оператора switch. Если ни одна из меток не совпадает, и в оператор включена метка default, то будут выполняться операторы этой метки, если меткиdefault нет, то оператор switch целиком игнорируется.

Значение “выбор”, используемое в операторе должно быть приведено к целому значению. Кроме того, необходимо помнить, что для завершения данного выбранного case необходимо в конце использовать оператор break. В противном случае будут выполняться последовательновсе операторы, относящиеся к другим меткам (до тех пор пока не встретится оператор break).

Команды передачи управления

Это команды, предназначенные для использования в управляющих операторах или для моделирования других управляющих структур.

Оператор return

Существует два основных способа использования оператора return. Во-первых, в том случае, когда функция возвращает значение и его необходимо использовать в зависимости от того, какое значение возвращается в вызывающую программу, например:

int imax(int a, int b)

{

if (a > b) return (a);

else return (b);

}

Здесь функция использует оператор return для возвращения максимального из двух переданных ей значений.

Во-вторых, оператор return используется для выхода из функции в некоторой точке до ее завершения. Например, функция может определять условие, по которому происходит прерывание. Вместо того, чтобы помещать все основные операторы внутрь оператора if, для выхода можно использовать return.

Оператор break

Оператор break используется для выхода из цикла до его завершения. При этом цикл прерывается и управление передается оператору, следующему за циклом. Такую же функцию оператор break выполняет в конструкции switch (см. 11.1).

Оператор continue

Иногда нужно не выходить из цикла, а пропустить ряд операторов в теле цикла и начать его заново. В этом случае можно применить оператор continue, предназначенный специально для этого.

Оператор goto

В Си действительно есть оператор goto. Его формат достаточно

простой:

goto метка

где “метка” - любой идентификатор, связанный с определенным выражением. Однако наиболее разумное решение при программировании на Си - обойтись без оператора goto. Для замены этого оператора есть другие средства: три оператора цикла, операторы break, return.

Указатели и их использование

Указатели и память ПЭВМ

Ранее в разделе 7.1.5.2 было рассмотрено определение указателей. Здесь будут приведены некоторые примеры и возможности работы с указателями. Рассмотрим небольшую программу:

main()

{

int ivar,*iptr;

iptr = &ivar;

ivar = 421;

printf(“Размещение ivar: %p\n”,&ivar);

printf(“Содержимое ivar: %d\n”, ivar);

printf(“Содержимое iptr: %p\n”, iptr);

printf(“Адресуемое значение: %d\n”,*iptr);

}

В ней объявлены две переменные: ivarи iptr. Первая - это целая переменная, т.е. содержащая значение типа int, вторая - это указатель на целую переменную, следовательно она содержит адрес значения типа int. В основном эта программа делает следующее:

· адрес переменной ivar присваивается iptr,

· целое значение 421 присваивается ivar.

Адресный оператор, как это было показано ранее, позволяет получить адрес по которому размещено значение переменной ivar.

Результат работы программы будет вывод следующих строк:

Размещение ivar: 166E

Содержимое ivar: 421

Содержимое iptr: 166E

Адресуемое значение: 421

Несколько видоизменим программу:

main()

{

int ivar,*iptr;iptr = &ivar;

*iptr= 421;

printf(“Размещение ivar: %p\n”,&ivar);

printf(“Содержимое ivar: %d\n”, ivar);

printf(“Содержимое iptr: %p\n”, iptr);

printf(“Адресуемое значение: %d\n”,*iptr);

}

Отличие этой программы от предыдущей состоит в том, что вместо присваивания 421 переменной ivar, это значение присваивается по указателю *iptr. Но результат будет точно такой же, как и при работе первой программы, так как ivar и *iptr суть одна и та же ячейка памяти.

Третья модификация этой программы будет выглядеть так:

#include <alloc.h>

main()

{

int *iptr;

iptr = (int *)mаlloc(sizeof(int));

*iptr = 421;

printf(“Содержимое iptr: %p\n”, iptr);

printf(“Адресуемое значение: %d\n”,*iptr);

}

Эта версия позволяет обойтись без описания переменной ivar, которое фигурировало в предыдущих версиях программы. Вместо адреса этой переменной iptr присваивается значение (тоже адрес некоторой ячейки памяти), возвращаемое некоторой функцией, которая называется malloc, и описана в библиотеке alloc.h (отсюда появление директивы #include в начале программы). Затем по этому адресу присваивается значение 421 и переменная *iptr вновь, как и в предыдущем примере, принимает значение 421.

Разберем оператор:

iptr = (int *)malloc(sizeof(int));

· выражение sizeof(int) возвращает количество байтов, требуемое для хранения переменной типа int; для Турбо-Си это значение равно 2.

· функция malloc(num) резервирует num последовательных байтов доступной (свободной) памяти в ПЭВМ, а затем возвращает начальный адрес размещения в памяти этой последовательности байтов.

Выражение (int *)указывает, что это начальный адрес есть указатель на данные типа int. Это выражение известно как выражение приведения типа.

Наконец, адрес, полученный с помощью функции malloc, запоминается в iptr. Таким образом, получена динамически созданная целая переменная, к которой можно обращаться при помощи идентификатора *iptr.

Весь этот блок можно описать следующими словами: “выделить в памяти ПЭВМ некоторый участок для переменной типа int, затем присвоить начальный адрес этого участка переменной iptr, являющейся указателем на эту переменную".

Все эти манипуляции совершенно необходимы, так как без этого нет гарантии, что iptr указывает на свободный участок памяти.

Т.е. правило использования указателей простое: УКАЗАТЕЛЬ ВСЕГДА ДОЛЖЕН ИМЕТЬ АДРЕС ДО СВОЕГО ИСПОЛЬЗОВАНИЯ В ПРОГРАММЕ.

Массивы и указатели

Существует определенная связь между массивами и указателями. Имя массива можно использовать как указатель, более того, можно определить указатель как массив. Рассмотрим важные тождества:

(list + i) == &(list[i])

*(list + i) == list[i]

В обоих случаях выражение слева эквивалентно выражению справа, и их можно использовать одно вместо другого, не принимая во внимание, описан лиlist как указатель или как массив.

Единственное различие между описанием list как указателя или как массива состоит в размещении самого массива. Если list описан как массив, то программа автоматически выделяет требуемый объем памяти. Если же list описана как указатель, то необходимо самостоятельно выделить память под массив, используя функцию malloc или сходную с ней.

Структуры и указатели

Можно описывать указатели на структуры точно также, как и указатели на другие типы данных. Фактически, указатели на структуры так часто используются в Си, что существует специальный символ для ссылки на элемент структуры, адресованный указателем.

Рассмотрим вариант программы с описанием структуры звезд (см.5.5.8).

 

#include <alloc.h>

main()

{

star *mystar;

mystar = (star *)malloc(sizeof(star));

strcpy(mystar -> name,”Епсилон Лебедя”);

mystar -> class = ‘N’;

mystar -> subclass = 2;

mystar -> decl = 3.5167;

mystar -> RA = -9.633;

mystar -> dist = 0.303;

/* конец функции main() */

}

 

В этом варианте mystar объявляется как указатель типа star, а не как переменная типа star. Память для mystar теперь резервируется путем обращения к функции malloc. Теперь при ссылке на элементы mystar, нужно использовать выражение: ptrname -> memname. Символ -> означает: ”элемент структуры направлен в ...”.

Операции с указателями

Несмотря на то, что содержимое указателя является целым числом без знака, с указате­лями нельзя выполнять все операции, которые выполнимы с целыми числами, а только те, которые имеют некоторый смысл при работе с указателями.

Первая операция, с которой обычно начинают работу с указателями, это операция при­своения значения, с помощью которой в указатель можно заложить адрес информации. При этом компилятор будет следить за тем, чтобы справа от этой операции был указан ад-

рес информации, соответствующей типу указателя.

р = &а ; // 1

р = mas ; // 2

р = 0x100 ; // 3

В первом случае в указатель закладывается адрес переменной а, во втором случае адрес начала массива (адрес самой первой переменной массива). И то и другое совпадает с ти­пом указателя. В третьем случае компилятор может выдать предупреждение или ошибку, так как константа 100 относится к типу int, но не является адресом информации этого типа. В таких случаях нужно применить операцию приведения к типу указателя, как пока-

зано ниже:

р = (int *) 0x100 ; // 3

Тип указателя - это тип, с которым он декларировался и звездочка, которая отличает указатели от обычных переменных при декларации.

Указателю можно задать нулевое значение, присвоив ему 0.

p= 0 ;_

Для обозначения числа 0 при работе с указателями во многих заголовочных файлах языка Си определяется макроконстанта NULL. Считается, что если указатель содержит та­кое значение, то он не готов к работе. Поэтому часто можно встретить декларацию указа­теля и инициализацию его значением NULL, для того, чтобы впоследствии определить, был ли заложен в указатель реальный адрес или нет.

Вторая операция, ради которой и используют в программах указатели, это операция *, реализующая доступ к информации, адрес которой хранится в указателе. Ее любят называть операцией разыменовывания указателя.

р = &а ; // 1

*р = 25 ; // 2

а = 25 ; // 3

Второй и третий операторы приводят к одному и тому же, в переменную а будет за­ложено значение 25.

С указателями можно применять шесть операций, с помощью которых к указателю можно прибавить, или вычесть с него целое число. При работе с указателями их называют операциями адресной арифметики, поскольку они работают не так, как с числами. К ним относятся следующие операции: +, -, ++, —, += и -=. Эти операции применяются, когда указатель содержит адрес массива, и дают возможность вычислять адреса нужных эле­ментов массива, не обращая внимания на тип массива.

р = mas ;

*р = 5 ; // 1

р++ ; или р += 1; или р = р + 1 ; //2

*р = 5 ; // 3

В примере, показанном выше, первый оператор занесет число 5 в переменную массива с номером 0. После выполнения одного из операторов, указанных во второй строке, тре­тий оператор приведет к изменению значения переменной массива с номером 1, т. к. при­бавление целого числа к содержимому указателя приведет к изменению его значения на число, умноженное на размер типа, с которым декларировался указатель. Сделано это для того, чтобы через указатель было удобно работать с массивами. Поэтому, прибавление к указателю числа 1, приведет к получению адреса следующей переменной в памяти.

Вместо операции *, для получения доступа к элементам массива, адрес которого со­держит указатель, можно применять операцию [ ], которая с указателями будет работать так же, как и с массивами. Можно и наоборот, к массиву применить операцию *.

р = mas ;

р[3] = 5 ; // 1

*(mas+3) = 5 ; //2

Эти операторы приведут к одному и тому же, в элемент массива с индексом 3 будет занесено число 5. Однако с массивами принято использовать квадратные скобки, а с ука­зателями операцию *.

Применение указателей

Правильное понимание и использование указателей имеет большое значение в языке Си, т. к. дает возможность создавать более эффективные программы. Обычно указатели используются в следующих случаях:

1. Для повышения эффективности работы функций.

• Для передачи больших объемов информации в функции, т. к. в этом случае вместо передачи самой информации в функцию передается ее адрес в оператив­ной памяти. В связи с этим, в языке Си различают два варианта передачи в функцию информации. Первый - передача информации по значению, при этом происходит копирование указанной в вызове функции информации в парамет­ры функции. Второй вариант - передача по адресу, когда функции указывается адрес информации, при этом в параметр функции происходит копирование ука­занного адреса, которые намного меньше занимает места, нежели сама инфор­мация. Для приема адреса у функции должен быть параметр указатель. В практике, когда объем информации превышать 16-20 байт, такую информа­цию стараются передавать в функцию по адресу.

• Для получения из функции нескольких результатов, т. к. оператором return функция может вернуть только один результат. В этом случае действуют по принципу функции scanf, которая может вернуть сколько угодно результатов, зная адреса переменных, куда она должна положить информацию, получаемую от пользователя.

2. Для организации в памяти различных динамических структур, предназначенных для хранения и обработки информации. К таким структурам относятся: динамиче­ские массивы, линейные списки, построенные на динамических массивах, связан­ные списки и др.

Несмотря на то, что задачи, перечисленные в первом пункте, могут быть решены с по­мощью глобальных переменных, в глобальную область выходят только в том случае, если другие пути получаются неэффективными и усложняют построение программы.

Ниже показан пример использования указателя для передачи в функцию массива типа double. Для этих целей в функции создают два параметра. Один параметр - указатель, который будет содержать адрес начала массива, другой параметр - переменная целого ти­па, которая получит размер массива или количество обрабатываемых переменных, начиная с указанного адреса.

// Подсчет суммы чисел в массивах типа double

double sum mas(double *pm, int size)

 

int i ; I адрес массива J I размер массива I

double sum = 0 ;

£or(i = 0; i < size; i++) sum += * (pm + i) ; return sum ; }

double m[10], s ;

s = sum_mas(m, 10); // Вызов функции

При вызове функции в первом параметре необходимо указать адрес начала массива типа double, во втором размер этого массива. Вместо адреса начала, можно указать ад­рес любой переменной массива, а вместо размера - количество переменных, которые не­обходимо обработать, начиная с указанного адреса.

Ниже показаны еще два варианта описания параметров функции для передачи в нее массива.

double sum_mas(double pm[], int size) // 1

double sum_mas(double pm[10]) //2

Первый вариант ничем не отличается от варианта, использованного ранее, т. к. пара­метр функции, являющийся указателем, можно описать с пустыми квадратными скобка­ми, вместо звездочки, тем самым подчеркнуть, что это будет указатель на массив. Во вто­ром варианте параметр описан как массив из 10-ти элементов. Второй параметр в этом случае не нужен. Но сам параметр pm по-прежнему будет являться указателем, но переда­вать ему нужно будет адрес начала массива типа double, содержащего 10 элементов. В результате такая функция становится менее универсальной.

В языке Си передать массив в функцию, можно только указав его адрес, по значению массивы не передаются. Поэтому, имея в распоряжении адрес массива, функция может с массивом делать что угодно, в том числе и изменять содержимое массива.

При передаче строки, в функции создается параметр-указатель типа char или wchat_t. Размер массива в этом случае передавать не нужно, т. к. окончание строки в массиве определяется символом с номером 0.

// Перевод символов строки в верхний регистр

void strupr(char *str)

while (*str) Указатель на строку *str++ = toupper(*str) ;

}

Функция toupper возвращает латинскую букву в верхнем регистре, если в параметре указан номер латинской буквы в нижнем регистре, в противном случае возвращается тот же номер. Цикл while в функции будет выполняться до тех пор, пока не будет обнару­жен символ с номером 0.

При передаче в функцию двухмерных и n-мерных массивов, можно поступать так же, как и с одномерными массивами, передавая адрес начала массива, количество строк и столбцов. В этом случае вычисление положения переменной по номеру строки и столбца приходится брать на себя, но функция получится более универсальной.

Пример функции, которая реализует отражение массива слева на право (можно ис­пользовать в графике):

void ltor(short *pm, int rows, int cols)

{

int i, j ;

short с ;

for(i =0; i < rows; i++)

for(j =0; j < cols/2; j++)

{ // Перестановка элементов массива

с = *(pm+i*cols+j) ;

*(pm+i*cols+j) = *(pm+i*cols+cols-j-l) ;

*(pm+i*cols+cols-j-l) = с ;

}

}

short image[50][40] ;

1tor((short*) image, 50, 40) ; // Вызов функции и различные ltor(image[0], 50, 40) ; // варианты указания адреса

ltor(&image[0][0], 50, 40) ; // начала массива

Благодаря возможности в языке Си создавать указатели на двухмерные и п-мерные массивы, параметры такой функции можно описать по другому и работать придется про-ще, но функция будет привязана к массивам, имеющим одно и то же количество столбцов:

void ltor2(short (*pm) [40], int rows)

{

int i, j ; short с ;

£or(i = 0; i < rows; i++)

for(j =0; j < 40/2; j++)

{ // Перестановка элементов массива

с = pm[i] [j] ;

pm[i][j] = pm[i][cols-j-1] ;

pm[i][cols-j-1] = с ;

}

}

short image[50][40] ;

В функции ltor2 параметр pm описан как указатель на двухмерный массив, содер­жащий в каждой строке 40 переменных (имя указателя и звездочка должны быть заключе­ны в круглые скобки). При добавлении к такому указателю 1 его содержимое увеличится на 40*sizeof (short) = 80 для перехода на следующую строку двухмерного мас­сива. Через такие указатели удобно работать с массивами используя операцию [ ], как по-казано в функции. Таким образом, можно создать указатель на любой n-мерный массив:

int (*pm3)[5][10] ;

Указатель на трехмерный массив, содержащий таблицы размером 5 строк и 10 столб­цов. При добавлении к такому указателю 1 его содержимое увеличится на 5*10*sizeof (int) = 200 для перехода на следующую таблицу трехмерного масси­ва.

Для получения из функции нескольких результатов в функции предусматривают нуж­ное количество параметров - указателей, которым при вызове функции указывают адреса переменных, куда функция должна заложить результаты.

// Вычисление корней квадратного уравнения

int sqr(double a,double b,double с, double *pxl, double *px2)

{параметры-указатели

double d = b*b-4*a*c;

if (d< 0) return 0; // Корней нет

if(a= 0) return 0 ; //Heквадратное уравнение

*pxl s= (-b + sqrt(d))/2/a ; // <- 1-й корень по адресу в pxl

*px2 = (-b - sqrt(d))/2/a ; // <- 2-й корень по адресу в рх2

return 1 ; // Корни получены

}

double xl, x2 ; [___адреса переменных

if(sqr(1, 2, -3, &xl, &x2)) // Вызов функции printf("xl = %lg, x2 = %lg\n", xl, x2) ;

else

printf("Корней нет!\п") ;

Функция sqr вычисляет корни квадратного уравнения, получая коэффициенты а, b и с, при этом в качестве результатов возвращает три числа. Первое число типа int возвра­щается оператором return, которым функция сообщает о полученных результатах, а по адресам переменных, которые должны содержаться в указателях pxl и рх2 закладывают­ся значения двух корней квадратного уравнения.

Для создания в памяти различных динамических структур хранения информации нуж­но использовать стандартные функции, с помощью которых можно выделить память под эти структуры и их элементы. К таким функциям относятся:

malloc(кол-во_байтов)

calloc(размер_одной_переменной, кол-во_переменных)

realloc(адрес_выделенного_участка, кол-во_байтов)

Функции malloc необходимо указать размер требуемого участка памяти в байтах. Функции calloc указывается размер в байтах одной переменной и количество требуе­мых переменных. Функция realloc является более универсальной, т. к. с ее помощью можно выделить память, указав для первого параметра значение NULL, а впоследствии изменять размеры имеющихся участков (независимо от того, какой функцией было сдела­но выделение), указывая для первого параметра адрес начала выделенного участка, а во втором параметре новый требуемый размер в байтах.

Все три функции, в случае успешного выделения памяти или изменения размера ранее выделенного участка (realloc), возвращают адрес начала полученного или измененного участка. При этом гарантируется, что будет получен непрерывный участок памяти разме­ром не менее запрошенного объема, кроме того, пользоваться этим участком будет только та программа, для которой участок был выделен.

Если не удастся подобрать для программы свободный участок памяти указанного раз­мера, все три функции возвращают нулевой адрес NULL, как признак ошибки. Кроме того, функция calloc после выделения памяти обнуляет все байты на этом участке, поэтому работает медленнее. При выделении памяти функциями malloc и realloc участки па­мяти будут с мусором.

Если изменять размер участка функцией realloc, вся информация, находящаяся на участке, будет скопирована в новый участок при изменеии его положение, правда, если при этом функции не удастся изменить размер участка, она возвратит NULL, но участок с прежним адресом останется в распоряжении программы.

В примере показано, как выделить память под динамический массив, размером 1000 переменных типа double разными функциями.

double *pm ;

pm = malloc(1000*sizeof(double)) ; // или

pm = calloc(sizeof(double), 1000) ; // или

pm = realloc(NULL, 1000*sizeof(double)) ;

Поскольку при выделении памяти нет гарантии, что будет получен участок памяти за­прошенного размера, даже если будет выделяться 1 байт, поскольку вся память уже может быть распределена между программами, после работы каждой функции необходимо де­лать проверку содержимого указателя на значение NULL и только после этого работать с полученным участком.

if (pm = NULL)

{

printf("Для работы нет свободной памяти!!!") ;

exit(l) ; // Если программа дальше продолжаться не может

}

Функция exit используется обычно для аварийного завершения программы. Единст­венному параметру в этой функции указывают код завершения программы: 0 - нормаль­ное завершение, другое значение - ненормальное завершение.

Имея в указателе pm адрес начала непрерывного участка, программа может организо­вывать на этом участке хранение и обработку информации, работая с участком через этот указатель и операции адресной арифметики. Выходить за рамки участка не разрешается. for(i =0; i < 1000; i++)

*(pm+i) = rand() ; // Заполнение массива случайными числами

Если при работе окажется, что размер участка необходимо изменить, это можно сде­лать функцией realloc, указав в первом параметре адрес начала выделенного участка, во втором параметре новый размер участка в байтах.

pm = realloc(pm, 2000*sizeof(double)) ;

В примере показано, как увеличить динамический массив, адрес которого содержится в pm, в два раза, и довести его до 2000 переменных. После попытки изменить размер уча­стка, необходимо сделать проверку содержимого указателя pm, как было показано выше. При таком варианте работы с функцией realloc будет потерян адрес начала имеющего­ся участка, если в процессе изменения размера функция вернет NULL.

Поэтому, если необходимо продолжить работу программы без потери выделенной па­мяти, перед изменением размера, необходимо предварительно сохранить адрес начала вы-деленного участка в другом указателе, или присваивать значение другому указателю.

pm2 = realloc(pm, 2000*sizeof(double)) ;

if (pm2 = NULL)

printf("Для работы нет свободной памяти!!!") ;

else pm = pm2 ; // Запоминаем новый адрес

Когда все задачи будут решены, для которых понадобилось выделять участок памяти, он должен быть освобожден функцией free, которой необходимо указать адрес начала ранее выделенного участка памяти.

free (pin) ;

После освобождения участка памяти, несмотря на то, что в указателе останется его ад­рес, обращаться к нему нельзя.


12. Рабочие области и проекты Visual C++

Программные задачи в Visual C++ оформляются в виде проектов, причем для каждой отдельной программы создается свой проект. Проект (ргoject) представляет собой набор файлов, которые совместно используются для создания одной программы.

Кроме того, сами проекты размещаются в рабочих областях (workspaces) причем одна рабочая область может содержать несколько проектов (активный проект задается в С++ командой Project -->Set Active Project). Visual С++ автоматически создает их для каждого нового проекта, поэтому в первую очередь нас интересуют проекты, а не рабочие области. Все же необходимо помнить о том, что вы работаете в рабочей области Visual С++, а проект принадлежит ей.

Давайте создадим и запустим первый проект:

1. Выполните команду File|New в Visual C++; на экране появляется окно New.

2. Перейдите на вкладку Projectsи выберите из списка строку Win32 Console Application.

3. Введите в текстовом полеProject nameимя проекта first, а в поле Locationукажите каталог для проекта, лучше оставить каталог по умолчанию.

4. Нажмите кнопкуОКв диалоговом окне New. На экране появляется новое диалоговое окно с именем Win32 Application.

5. Нажмите кнопку Finish- Visual C++ создаст новую программу с именем first. В нее входят два важных файла: first.dswопределяет параметры новой рабочей области, a first.dsp — параметры нового проекта.

ПОДСКАЗКА: Чтобы продолжить работу над программой, над которой вы трудились раньше, воспользуйтесь командой Visual C++ File |Open Workspaces,и откройте файл рабочей области программы (с расширением .dsw).

Итак, мы создали новую рабочую область, а в ней - проект с именем first. Теперь нужно ввести исходный текст программы; нам нужно, чтобы программа выводила строку "Welcome to C++".

Создание файла с исходным текстом

Для текста программы нам понадобится новый файл first.cpp. Расширение .срр присваивается файлам с текстами программ на C++.

ПРИМЕЧАНИЕ: Помимо файлов с исходными текстами в программахна C++ часто встречаются заголовочные файлы с расширением .h. Как мы увидим далее, заголовочные файлы содержат объявления переменных и функций.

Давайте создадим файл first.cpp и включим его в проект:

1. Снова выполните команду File|New, только на этот раз перейдите на вкладку Files(рис. 1.3).

2. Выберите из списка строку C++ Source File и введите имя файла first.cppв текстовом поле File name.

3. Проследите, чтобы флажок Add to projectбыл установлен. Нажмите кнопку ОК.

4. Файл first.cpp создается и открывается в среде Visual C++.

Среда Visual C++ состоит из трех основных окон: слева расположено окно просмотра с корешками вкладок в нижней части (Class Viewи FileView). Справа от него находится окно редактора, в котором происходит редактирование документов (в настоящий момент в нем открыт пустой файл first.cpp). Внизу расположено окно результатов со вкладками Build, Debugи Find in Files.

В окне просмотра выводится общая структура проекта, но ее конкретное представление зависит от выбранной вкладки — ClassViewили FileView(о других вкладках мы поговорим позже). На вкладке ClassViewпоказана иерархия классов C++ в рабочей области; вскоре мы узнаем, что такое классы. На вкладке FileViewпоказана иерархия файлов в рабочей области (на рис. 1.4 она состоит из рабочей области, проекта и файла first.cpp).

ПРИМЕЧАНИЕ: Далее, когда мы начнем работать с полноценными программами на Visual C++, в окне просмотра появится еще одна вкладка — Resources. Такие объекты как меню, диалоговые окна и панели инструментов/ в программировании для Windows являются ресурсами.

В окне редактирования отображаются открытые документы. Обычно в нем работает текстовый и другие редакторы, например, редактор меню или диалоговых окон.

В окне результатов в нижней части выводится информация о ходе компиляции программ. Кроме того, это окно используется для отладки и других целей, о которых будет рассказано далее.

Добавление кода на C++

Теперь мы добавим программный код в файл first.cpp, который в настоящий момент открыт в окне редактирования Visual C++. Чтобы создать свою первую программу на C++, введите следующий текст:

#include <iostream.h>

void main()

{

cout << "Welcome to C++ \n";

}

Так выглядит наша первая программа. В ней мы воспользовались стандартными средствами C++ для вывода текстовой строки, в нашем случае — "Welcome to C++". Сначала мы включаем (#include) в программу файл iostream.h. Это позволит нам работать со стандартными средствами экранного вывода C++ (содержимое включенного файла просто вставляется в исходный текст программы).

Затем мы определяем функцию с именем main(). Эта функция вызывается при запуске программы. Другими словами, когда вы запускаете файл (например, first.exe), Windows ищет в нем функцию main() и выполняет содержащийся в ней код; поэтому мы и включили в нее тот код, который необходимо выполнить. Вскоре мы рассмотрим функцию main() более подробно.

ПРИМЕЧАНИЕ: В программах далее функция main() не используется: ее место занимает функция WinMain().

Выяснив, с чего начинается выполнение программы, давайте рассмотрим то, что она делает — а именно отображение строки на экране при помощи средств ввода/вывода языка C++.

Что такое потоки C++?

Мы записываем данные в поток C++ с именем cout, для чего используется оператор cout <<"Welcome to C++ \n";:

Текст "Welcome to C++ \n" отправляется в выходной поток C++ и попадает прямо на экран. Потоки C++ можно рассматривать как каналы для пересылки данных в различные места; поток cout посылает текст на экран.

Символ \n в конце строки представляет собой служебный символ, который переводит курсор на следующую строку после вывода текста. Приведенная выше строка программы выводит сообщение на экране, посылая его в поток cout.

Мы не будем надолго останавливаться на специфике работы с cout, потому что в стандартных Windows-программах вывод текста происходит без участия потоков; мы воспользовались cout лишь для того, чтобы временно облегчить себе задачу. Сейчас он нужен только затем, чтобы мы могли увидеть результаты работы наших классов и объектов при запуске программы.

ПОДСКАЗКА Кроме потока coutв консольных программах также можно —пользоваться потоком cinдля получения символов с клавиатуры.

На этом наше знакомство с кодом программы first.cpp завершается. Предварительная подготовка закончена, пора посмотреть, как работает наша программа.

Запуск первой программы

Для того, чтобы запустить нашу первую программу, сначала необходимо ее откомпилироватьто есть преобразовать в выполняемый файл first.exe. Выполните команду Build -->Build First.exe, и исходный файл first.cpp будет скомпилирован в first.exe.

Во время компиляции в окне результатов Visual C++ (в нижней части окна Developer Studio) отображается следующий текст:

--Configuration: first - Win32 Debug—

Compiling... first.cpp

first.ехе - 0 error(s), 0 warning(s)

Теперь запустите программу командой Build > Execute first.exe.

В окне виден текст сообщения Welcome to C++ и подсказка Press any key to continue,вставленная Visual C++. Если нажать любую клавишу, окно исчезнет с экрана.

На примере этой маленькой программы мы познакомились с проектами и рабочими областями Visual C++, с компиляцией программ и с редактированием текстов. Теперь можно заняться собственно программированием на С.

 

Литература:

1. Т. Павловская C/C++. Программирование на языке высокого уровня: Учебник для вузов,1-е издание, Спб, "Питер", 2005.

2. С. Холзнер Visual C++ 6. Учебный курс, 2-е издание, Спб, "Питер", 2005.

3. А. Крупник Самоучитель C++ , 1-е издание, Спб, "Питер", 2004.

4. Гилберт А., Маккарти Р. Программирование на Visual C++ 6. Этюды профессионалов, М.: "Диафсофт", 2004.

 

 



Просмотров 741

Эта страница нарушает авторские права




allrefrs.su - 2025 год. Все права принадлежат их авторам!