- •Понятие программы и языка программирования
- •Функция как компонент структуры программы
- •Примеры простых программ
- •Вычисление значения функции в заданной точке
- •Вычисление суммы и количества целых чисел, введенных пользователем с клавиатуры
- •Демонстрация работы со строками на основе использования класса string
- •Представление программы и данных
- •Процесс компиляции программы
- •Классическая схема подготовки исполняемой программы
- •Технологический цикл обработки программы
- •Особенности внутреннего представления программы и ее исполнения
- •Организация памяти компьютера
- •Сегментация программы
- •Процесс исполнения программного кода
- •Структура текстового файла программы
- •Структура программы из двух текстовых файлов
программы в большей степени соответствует блок-схеме, имеющей те же самые составные элементы – действие, проверка условия и переход. В языках программирования используются более абстрактные и более удобные системы представления, но в процессе трансляции они все равно превращаются в линеаризованную блок-схему, элементы которой размещены в линейной памяти.
Структура текстового файла программы
Текст программы может быть размещен в одном или нескольких текстовых файлах (модулях). Модули взаимодействуют друг с другом посредством вызовов функций, которые они содержат, доступа к глобальным переменным, определениям типов и константам. Важным элементом проектирования программы является возможность раздельной трансляции модулей: файлы компилируются по отдельности и объединяются на этапе компоновки.
В строгой интерпретации, в C/C++ физическим модулем является отдельный сегмент компиляции, т. е. объектный файл. Физическому модулю соответствует файл с исходным текстом C/C++, к которому подключены необходимые заголовочные файлы, образующие инт ерфейс между модулями. Поэтому часто (с некоторой долей условности) модулем называют также файл с исходным текстом. Язык С и первые реализации языка С++ не предоставляли других механизмов реализации модульности, поэтому физический модуль являлся одновременно и логическим модулем.
Пример структуры текстового файла программы, включающей функции main(), f1() и f2(): //имя файла
//директивы препроцессора
#include <стандартный файл> //подключение стандартных заголовочных файлов
#include ”файл пользователя” //подключение заголовочных файлов пользователя //определение глобальных переменных
//прототипы функций |
|
void f1(); |
// прототип функции f1 |
int f2 (int, char); |
//прототип функции f2 |
//определение функции main() |
|
int main () { |
//заголовок функции |
|
//тело функции (операторы) |
//операторы, содержащие вызов функций f1 и f2, например: f1();
//например: cout << f2(4, ‘a’) << endl; выведет то, что вернет вызов функции, т.е. выражение return 0; // завершает тело функции с заголовком int main ()
}
//определение функции f1() |
|
void f1() { |
//заголовок функции |
|
//тело функции |
return; |
// завершает тело функции с заголовком void f1() |
} |
|
//определение функции f2() |
|
int f2 (int k, char c) { |
//заголовок функции |
//тело функции f2 |
// завершает тело функции с заголовком int f1(int k, char c)!!! |
return выражение; |
|
} |
|
Программирование – лекция 1 (лекции Стрикелевой Л.В.) |
17 |
|
Если функция main() получает аргументы, то она определяется так:
int main (int argc, char *argv[]) |
//или |
int main(int argc, char **argv) |
{ |
|
|
//тело функции |
|
|
return 0; |
|
|
}
где: int argc – число слов, переданное в программу при ее запуске, char *argv[ ] – массив из argc строк;
аргумент argv[0] является именем запускаемого на выполнение файла; argv[1] – первое переданное слово;
argv[2] – второе переданное слово ….. и т.д.
Стандарт языка С++ требует, чтобы функции были объявлены до первой ссылки на них: их прототипы размещаются в начале программы. Компилятор выполняет строгую проверку числа параметров и соответствия типов в прототипе, в вызове функции и в ее определении, а в ряде случаев выполняет и неявное преобразование типов.
Имена функций – это глобальные имена, видимые по умолчанию из всех файлов одного проекта. Однако прототип функции действует только в пределах одного файла. Из-за этого, в частности, приходиться помещать во все совместно компилируемые файлы директивы препроцессора, связанные с подключением .h-файлов, содержащих прототипы библиотечных функций. Как мы видели, прототипы функций помещаются в заголовочный файл, подключаемый директивой #include к тексту файла программы.
Структура программы из двух текстовых файлов
Рассмотрим модель программы из двух текстовых файлов (Рис.1.7). Линии 1-3 указывают область действия глобальных переменных (ниже точки определения): массива array, переменных ext_ch и ext_pp. В пределах области определения их можно использовать во всех функциях без дополнительного объявления как extern (линия 1 для массива array; линия 2 для переменной ext_ch; линия 3 для переменной ext_pp). Чтобы использовать переменные ext_ch и ext_pp в функции main(), т.е. выше точки определения, их надо объявить как extern (внешние) (например, линия 6 для переменной ext_pp).
Во всех функциях, за исключением function3() из файла File2.cpp , описана внутренняя переменная a, которой соответствует своя память, доступ к которой возможен только из пределов функции, но не из других функций.
Область определения глобальных переменных ограничена пределами одного файла (File1.cpp), и, следовательно, эти переменные невидимы в другом файле (File2.cpp). Для их использования требуется также объявление extern (например, линия 5 для массива array; линия 7 для переменной ext_ch; только функция function3() для переменной ext_pp).
Программирование – лекция 1 (лекции Стрикелевой Л.В.) |
18 |
|
File1.cpp |
|
File2.cpp |
|
|
|
Рис.1.7. Структура программы из двух файлов и область действия переменных в программе
Программирование – лекция 1 (лекции Стрикелевой Л.В.) |
19 |
|
Пример более сложной программы на С++ (сортировка строк)*1
Программа сортирует строки в лексикографическом порядке, возрастающем или убывающем в зависимости от признака, передаваемого функции main() через аргумент argv, и выводит их на экран.
Исходный текст программы представлен в текстовых файлах (main.cpp, bblsort.cpp) и в заголовочных файлах (Рис.1.8):
•стандартном заголовочном файле stdafx.h
•файле bblsort.h (подключаемом в начале каждого из текстовых файлов в рамках файла stdafx.h).
файл bblsort.h
#define MAXLINES 10
#define LINESIZE (12+1)
файл stdafx.h
#include <iostream>
#include <conio.h>
#include <cstring>
#include "bblsort.h"
int rdlines(void); void wrlines(int);
int lexcmp(int, int); void swap(int, int); void bblsort(int);
using namespace std;
файл main.cpp
#include "stdafx.h"
char Line[MAXLINES][LINESIZE]; int Revflg;
int main (int argc, char **argv)
{int numlines;
Revflg = (argc>1 && argv[1][0] =='-'); numlines = rdlines();
cout << "\n----------------- |
\n" ; |
bblsort(numlines); |
|
wrlines(numlines); |
\n" ; |
cout << "\n----------------- |
|
_getch(); |
|
return 0; |
|
} |
|
static int rdlines() {int i;
for (i=0; i < MAXLINES; i++)
if (!cin.getline(Line[i], LINESIZE)) break;
}return i;
static void wrlines(int n) {unsigned i;
for (i=0; i<n; i++)
cout << Line[i] << endl;
} return;
файл bblsort.cpp
#include "stdafx.h"
extern char Line[ ][LINESIZE];
void bblsort( int n) {unsigned i, j;
for (i=1; i<n-1; i++)
for (j=n-1; j>=i; j--) if (lexcmp(j-1, j))
swap(j-1, j);
}return;
static int lexcmp (int i,int j) {extern int Revflg;
int lc;
lc= strcmp(Line[i], Line[j]); return ((lc<0 && Revflg) ||
(lc > 0 && !Revflg));
}
static void swap( int i, int j) {char temp [LINESIZE]; strcpy_s(temp, Line[j]); strcpy_s(Line[j], Line[i]); strcpy_s(Line[i], temp);
} return;
Рис.1.8. Структура программы сортировки строк
Программа с комментариями и подробное описание действий, выполняемых каждым фрагментом (А, B, C, D, …), представлены ниже.
//bblsort.h – заголовочный файл
А#define MAXLINES 10
#define LINESIZE (12+1)
//stdafx.h – стандартный заголовочный файл
B |
#include <iostream> |
//для ввода/вывода |
#include <conio.h> |
//для _getch() |
|
|
#include <cstring> |
//для strcmp(), strcpy_s() |
1 *Программа не для всех
Программирование – лекция 1 (лекции Стрикелевой Л.В.) |
20 |
|
#include "bblsort.h" |
//для MAXLINES, LINESIZE |
int rdlines(void); |
//прототипы функций, определенных в файле main.cpp |
void wrlines(int); |
|
int lexcmp(int, int);//прототипы функций,определенных в файле bblsort.cpp |
|
void swap(int, int); |
|
void bblsort(int); |
|
using namespace std; |
|
//main.cpp – программный файл
C |
#include "stdafx.h" |
//подключение стандартного заголовочного файла |
||
D |
char |
Line[MAXLINES] [LINESIZE]; |
//глобальные переменные |
|
|
//буфер строк |
|||
|
int |
Revflg; |
|
//признак направления сортировки |
E |
|
|
//определение функции main() |
|
|
int main (int argc, char **argv) |
//аргументы вызова программы |
||
// argc - число аргументов, argv – указатель на строки-аргументы
{
F
G
int numlines; |
//локальная переменная функции main() |
Revflg = (argc>1 && argv[1][0] =='-'); |
|
numlines = rdlines(); |
//вызов функции ввода строк |
cout << "\n---------------------- |
\n" ; |
bblsort(numlines);//вызов функции сортировки,аргумент – количество строк |
|
wrlines(numlines);//вызов функции вывода строк,аргумент – количество строк |
|
cout << "\n---------------------- |
\n" ; |
_getch(); |
//функция _getch(); ожидает нажатия клавиши |
return 0; |
|
} |
|
H |
//определение функции rdlines() ввода строк с клавиатуры |
||
I |
static int rdlines() |
//функция доступна только в данном файле main.cpp |
|
{ int i; |
//локальная переменная функции rdlines() |
||
|
for (i=0; i < MAXLINES; i++) |
||
|
if (!cin.getline(Line[i], LINESIZE) ) |
||
|
} return i; |
|
break; |
|
|
//функция возвращает количество введенных строк |
|
J |
//определение функции wrlines() вывода n строк на экран |
||
|
static void wrlines(int n) //функция доступна только в файле main.cpp |
||
|
{ |
|
|
|
unsigned i; |
//локальная переменная функции wrlines() |
|
for (i=0; i<n; i++) |
|
|
cout << Line[i] << endl; |
|
} |
return; |
//функция выводит строки и ничего не возвращает |
|
|
|
Программирование – лекция 1 (лекции Стрикелевой Л.В.) |
21 |
|
//bblsort.cpp – программный файл
K#include "stdafx.h" //подключение стандартного заголовочного файла
Lextern char Line [][LINESIZE]; //объявление массива Line,
//определенного в файле main.cpp
M |
|
//определение функции bblsort()сортировки строк |
|
|
void bblsort( int n) |
// n - число строк |
|
|
{ |
unsigned i, j; |
//локальные переменные функции bblsort() |
|
|
||
|
|
for (i=1; i<n-1; i++) |
|
|
|
for (j=n-1; j>=i; j--) |
|
|
|
if (lexcmp(j-1, j)) swap(j-1, j); |
|
|
} |
return; |
//функция сортирует строки и ничего не возвращает |
|
|
|
|
N |
|
// определение функции lexcmp() сравнения строк |
|
|
|
|
//аргументы i, j – номера строк для сравнения |
|
static int lexcmp (int i, int j) |
||
|
{ |
|
//функция доступна только в файле bblsort.cpp |
|
extern int Revflg; |
//объявление Revflg, определение в файле main.cpp |
|
int lc;
lc= strcmp(Line[i], Line[j]); //библиотечная функция сравнения строк
return ((lc<0 && Revflg) || (lc > 0 && !Revflg));
}//функция lexcmp() возвращает 1 или 0 в зависимости от результата //сравнения строк lc и признака Revflg направления сортировки
O |
//определение функции swap() обмена строк |
|
|
// аргументы i, j – номера строк для обмена |
|
static void swap( int i, int j) //функция доступна только в этом файле |
||
{ |
|
|
char temp [LINESIZE]; |
//библиотечная функция копирования строк |
|
strcpy_s(temp, Line[j]); |
||
strcpy_s(Line[j], Line[i]); |
|
|
strcpy_s(Line[i], temp); |
|
|
return; |
//функция swap() меняет строки и ничего не возвращает |
|
} |
|
|
А – заголовочный файл bblsort.h с препроцессорными константами MAXLINES и LINESIZE. Препроцессорные константы обычно помещаются в заголовочный файл, включаемый в другие файлы программы, по мере необходимости. При изменении значений констант изменения затронут только файл bblsort.h.
B – стандартный заголовочный |
файл stdafx.h. Содержит директ ивы препроцессора для |
|
подключения |
стандартных заголовочных файлов с прототипами библиотечных функций (для |
|
работы со строками и другими функциями, вызываемыми в файле); директ иву препроцессора для |
||
подключения |
пользовательского |
заголовочного файла bblsort.h с препроцессорными |
константами MAXLINES и |
LINESIZE; |
прототипы |
функций rdlines(), |
wrlines(), |
определенных в файле main.cpp, и |
lexcmp(), swap(), bblsort(), |
определенных в файле |
bblsort.cpp |
|
программы, а также директиву using namespace std; определяющую для данной программы в качестве пространства, в котором распознаются ее имена, стандартное пространство имен std (за пределами его имена будут неизвестны).
Программирование – лекция 1 (лекции Стрикелевой Л.В.) |
22 |
|
Блоки от С до J включительно представляют содержание файла main.cpp с головной функцией main() и вызываемыми в ее теле функциями rdlines() и wrlines().
С – подключение к файлуmain.cpp стандартного заголовочного файла stdafx.h.
D – определение глобальных переменных, доступных во всех файлах программы при объявлении их в этих файлах как extern.
В блоках от E до G представлено определение головной функции main(), обязательной для программы на С++ и получающей управление первой после запуска программы на выполнение. Функции main() могут передаваться аргументы. Одна из возможных форм описания формальных
параметров функции main() представлена в блоке E.
E – заголовок функции main(): int argc – число строк-аргументов переданное в программу; char** argv – указатель на строки-аргументы; аргумент argv[0] является именем запускаемого на выполнение файла; argv[1] – это первый аргумент-строка; argv[2] – это второй аргумент-строка и т.д. Количество строк-аргументов равно argc.
Если при выполнении программы задать в качестве аргумента символ +, то строки будут упорядочены по возрастанию (от a к z). Если при выполнении программы задать в качестве
аргумента символ -, то строки будут упорядочены по убыванию.
Задание аргумента при выполнении программы в среде Microsoft Visual C++ 2005 осуществляется в поле Command arguments подкоманды Debugging команды Project
имя_проекта Properties…( Project имя_проекта Properties… окно имя_проекта Property Pages Configuration Properties Debugging поле Command arguments).
F – определение локальной целой переменной numlines.
G – перед обращением к argv[1][0] проверяется число аргументов argc, т.к. при отсутствии второго аргумента выражение argv[1][0] не имеет смысла.
Блок содержит последовательные вызовы функций ввода – rdlines(), сортировки – bblsort() и вывода – wrlines() строк. При этом функции rdlines() и wrlines() определены в файле main.cpp, а функция bblsort() – в файле bblsort.cpp.
В блоках H и I представлено определение функции rdlines(), возвращающей целое число прочитанных строк. Спецификатор static указывает, что функция используется только в данном файле.
Переменная i определена как локальная в блоке. Если вводится нормальная строка (вызов функции cin.getline(Line[i],LINESIZE) возвращает значение отличное от 0), то функция rdlines() возвращает номер строки; в противном случае (например, при нажатии клавиш Ctrl+Z) , ввод строк завершается.
J – определение функции wrlines(). Функция не возвращает значения, поэтому определена как имеющая тип void.
Блоки от K до O включительно представляют содержание файла bblsort.cpp с функцией сортировки bblsort() и вызываемыми в ее теле функциями сравнения – lexcmp() и обмена – swap() строк.
K – подключение к файлуbblsort.cpp стандартного заголовочного файла stdafx.h.
L – описание глобального массива строк Line, спецификатор extern указывает на то, что определение массива сделано в другом месте (в данном случае в файле main.cpp).
M – определение функции bblsort(). Функция вызывает функции сравнения – lexcmp() и обмена – swap() строк. Функция не описывается как static, потому что она вызывается функцией main(), которая определена в другом файле.
N – определение функции lexcmp(). Возвращаются значения Истина (1) или Ложь (0),
Программирование – лекция 1 (лекции Стрикелевой Л.В.) |
23 |
|
кодируемые целыми значениями. Поэтому функция определена как имеющая тип int. Глобальная переменная Revflg описана как внешняя, так как она определена в другом файле. Прототип функция стандартной strcmp() содержится в заголовочном файле string.h.
O – определение функции swap(). Функция определена как имеющая тип void. Прототип стандартной функция strcpy() содержится в заголовочном файле string.h. Локальная переменная стокового типа temp предназначена для временного хранения строки при выполнении обмена.
Результат выполнения программы в среде Microsoft Visual С++ 2005 в режиме консольных приложений:
При аргументе ”+” |
При аргументе ”-”: |
qwertyui |
qwertyui |
wertyuio |
wertyuio |
ertyuio |
ertyuio |
rtyuiop |
rtyuiop |
rtyu |
rtyu |
tyui |
tyui |
asdfghjk |
asdfghjk |
sdfghjkl |
sdfghjkl |
dfgh |
dfgh |
fghj |
fghj |
---------------------- |
---------------------- |
asdfghjk |
wertyuio |
dfgh |
tyui |
ertyuio |
sdfghjkl |
fghj |
rtyuiop |
qwertyui |
rtyu |
rtyu |
qwertyui |
rtyuiop |
fghj |
sdfghjkl |
ertyuio |
tyui |
dfgh |
wertyuio |
asdfghjk |
Программирование – лекция 1 (лекции Стрикелевой Л.В.) |
24 |
|
