Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Программирование

.pdf
Скачиваний:
48
Добавлен:
30.03.2015
Размер:
544.24 Кб
Скачать

{ min=a[i]; k=i;

}

cout<<endl<<”min=”<<min<<” k=”<<k; // вывод результатов getch();

}

Начало

Ввод n

i=0

Ввод a[i]

Вывод a[i]

i<n

Конец

Начало

Заполнение a[i][j]

j=0

s[j]=0

i=0

s[j]+=a[i][j]

Вывод s[j]

i<3

j<4

Конец

Рис. 7 Рис. 8

Пример. Вычислить сумму элементов в столбцах двумерного числового массива а размером [3][4].

Алгоритм показан на рисунке 8.

#include <stdio.h>

// библиотека, содержащая описание

 

// операторов ввода/вывода

# include <conio.h>

// библиотека, содержащая описание

 

// операторов для работы с экраном

# include <stdlib.h>

// библиотека, содержащая описание

 

// генератора случайных чисел

21

void main()

// заголовок главной функции программы

{int a[3][4], i, j, sum[4];

// описание переменных

clrscr();

// очистка экрана

randomize();

// генератор случайных чисел, инициализация

 

// первого элемента ряда

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

// заполнение массива

{for(j=0;j<4;j++)

 

{

 

a[i][j]=random(100);

 

cout<<” ”<<a[i][j];

// вывод матрицы на экран

}

 

cout<<endl;

 

}

 

cout<<endl<<”summa”<<endl;

for(j=0;j<4;j++)

 

{

 

sum[j]=0;

 

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

// поиск минимального элемента

{sum[j]+=a[i][j];

cout<<sum[j]; // вывод результатов

}

getch();

}

Лабораторная работа 5 ОБРАБОТКА СИМВОЛЬНЫХ И СТРОКОВЫХ ДАННЫХ

Символьный тип – это тип данных, используемый для описания отдельных символов (знаков, букв, кодов). Традиционная запись символьного значения представляет собой символ, заключенный в апострофы, например ‘a’.

Строковая константа представляет собой последовательность символов, заключенную в кавычки (“), например, “это моя первая строка”. В конце каждого строкового типа данного компилятором добавляется нулевой символ, представляемый управляющей константой \0.

Строковая переменная описывается как char st[12], в квадратных скобках указывается длина строки. Это означает, что строковая переменная – массив символов, причем нумерация элементов массива начинается с нуля, и число элементов массива равно числу символов плюс единица.

Операция конкатенации строк обозначается обратной косой чертой:

22

“Это очень длин\ ная строка символов”

Для описания строковой переменной можно воспользоваться понятием массива символов или указателя (ссылки) на массив символов, например:

char mas[15]; char*st;

Для ввода/вывода символьных/строковых типов данных можно воспользоваться не только функциями printf() и scanf(), но и рядом других функций, прототипы которых описаны библиотечном файле stdio.h:

-функция int putchar(char c) выводит одиночный символ в стандартный выходной поток stdout без последующего перехода к новой строке.

-функция int getchar() применяется для ввода очередного символа из стандартного входного потока stdin. Эта функция не требует задания параметра

ипринимает значение целого типа, например:

char ch; ch=getchar(); putchar(ch);

-функция int puts(char *st) используется для вывода строки символов в стандартный выходной поток. Строка символов дополняется символом конца строки ‘\n’, и после вывода строки символов функцией puts() переход к новой строке происходит автоматически.

Пример. #include<stdio.h> void main() {char mas[15], *st; ….

puts(mas); puts(st);

}

-функция char *gets(char *st) выполняет считывание из стандартного входного потока. Ввод продолжается до тех пор, пока не будет нажата клавиша Enter. Эта функция дополняет строку введенных символов символом ‘\0’.

Пример. #include<stdio.h> void main() {char mas[15], *st; ….

gets(mas); gets(st);

}

Если число представлено в виде строки символов, то можно воспользоваться функциями int atoi (строка символов), long atoll (строка символов), double atof

23

(строка символов) для преобразования строки, соответственно в целое, длинное целое или вещественное число. Прототипы этих функций описаны в библиотечном файле stdlib.h. Если строка не может быть преобразована в число, то возвращается нуль.

В языке С++ существует группа операторов для работы с символьными переменными (табл. 8), которые описаны в загрузочном файле ctype.h.

 

 

Таблица 8

 

Операторы, для работы с символьными переменными

 

 

 

Синтаксис

 

Описание

isalpha(c)

 

Функция проверяет, является ли символ с буквой

isdigit(c)

 

Функция проверяет, является ли символ с цифрой

islower(c)

 

Функция проверяет, является ли символ с строчной буквой

isspace(c)

 

Функция проверяет, является ли символ с пустым символом

 

 

(пробел, табуляция или новая строка)

 

 

 

isupper(c)

 

Функция проверяет, является ли символ с прописной буквой

isalnum(c)

 

Функция проверяет, является ли символ с алфавитноцифром

 

 

(буква или цифра)

 

 

 

isascii(c)

 

Функция проверяет, является ли символ с кодом ASCII(0-127)

iscntrl(c)

 

Функция проверяет, является ли символ с управляющим

 

 

символом

 

 

 

ispunct(c)

 

Функция проверяет, является ли символ с знаком пунктуации

toupper(c)

 

Функция преобразует символ с в прописную букву

tolower(c)

 

Функция преобразует символ с в строчную букву

Для работы со строкой символов в файле string.h описаны прототипы ряда функций. Библиотека представляет возможности копирования (strcpy, strncpy),

сравнения (strcmp, strncmp), объединения строк (strcat, strncat), поиска подстроки (strstr), поиска вхождения символа (strchr, strrchr, strpbrk),

определения длины строки (strlen) и т.д., а также содержит специальные функции ввода строк и отдельных символов с клавиатуры и из файла.

Пример. #include <stdio.h> #include <string.h> void main()

{char s[80], passw[]}=”kuku”; // passw – эталонный пароль. // Можно описать как *passw=”kuku”

int i, k=0;

for(i=0;!k && i<3; i++) {printf(“Введите пароль: \n”);

24

gets(s);

// функция ввода строки

if (strstr(s,passw)) k=1;

// функция сравнения строк

}

if (k) printf(“\n Пароль принят”); else printf(“\n Пароль не принят”); return 0;

}

Следует помнить, что операция присваивания одной строки другой не определена (поскольку строка является массивом) и может выполняться с помощью цикла или функции из стандартной библиотеки. Процесс копирования строки scr в строку dest проиллюстрируем на следующем примере: char scr[10], dest[10];

for(int i=0;i<=strlen(scr); i++) dest[i]=scr[i];

Лабораторная работа 6 УКАЗАТЕЛИ

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

Пример.

int *rt; float *s; void *s_p;

указатель типа void («пустой») может указывать на объект любого типа. Наиболее важными операциями, связанными с указателями, являются операция обращения по адресу * (разыменования или снятия ссылки) и операция определения адреса &. Первая операция служит для присваивания или считывания значений переменной, на которую ссылается данный указатель. Вторая операция возвращает адрес памяти своего операнда. Размер возвращаемого адреса зависит от применяемой модели динамической памяти. Пример.

#include <stdio.h> void main ()

{int i=10, s, *x, *f, *v=&i, *x=9,s=5,f=&s;

25

printf (“\n Размер x=%d”, sizeof(x));

printf (“\n Значение указателей x=%u v=%u &i=%u”, x, v, &i); printf (“\n Значение по адресу x=%d”, *x);

printf (“\n Адрес s=%u”, &s);

}

При работе с динамическими переменными типа указатель распространенной ошибкой является то, что при описании указатель не инициализируется, что приводит к тому, что компилятор резервирует память только для хранения адреса. В примере, приведенном выше, под переменные *х и *f отводится только два байта под хранение адреса и не отводится два байта под хранение переменной типа int. Что может привести к попытке размещения в процессе выполнения программы значения переменной по начальному адресу, связанному с какой-либо частью операционной системы.

При работе с переменными типа указатель следует придерживаться следующего алгоритма:

1.Предварительно инициализировать указатель, т.е. присвоить указателю адрес предварительно инициализированной переменной, как это выполнено в примере для указателя *v.

2.Использовать функции распределения динамической памяти – «кучи», описанные в библиотечном файле alloc.h:

-void *malloc(unsigned s) – выделение памяти размером s байт;

-void *calloc (unsigned nel, unsigned els) – выделение памяти для nel

элементов, для которых размер каждого элемента определяется переменной els,

-void *realloc(void *blok, unsigned s) – изменение размера ранее выделенной памяти для блока *block до величины s байт;

-void far *farcalloc(unsigned long nel, unsigned long els) – выделение памяти для дальней ее модели из nel элементов, где размер каждого элемента els;

-void free (void *blok) – освобождение ранее выделенной памяти. Все функции имеют тип void, поэтому они совместимы с указателями

любого типа и справедлива запись x=(int*)malloc(sizeof(int)), т.е. адрес, выдаваемой функцией malloc, связывается с типом int. Данные функции гарантируют, что переменной-указателю не присваивается адрес, используемой системой.

Пример. Вычислить сумму n элементов массива вещественного типа.

#include <stdio.h>

#include <alloc.h> void main()

{float *a, s=0, *prn, f;

26

int i, n;

printf (“Введите размер массива а \n”); scanf(“%d”,&n);

a=(float *)malloc(n*sizeof(float));

if (a==0) {printf (“No memory”); exit (1);} else {ptr=a; printf(“Input array a \n”);

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

{scanf(“%f”, ptr); f=*ptr; s+=f; ptr++;} printf (“s=%e\n”, s);

}

free(a);

}

Лабораторная работа 8 ПРОГРАММИРОВАНИЕ С ИСПОЛЬЗОВАНИЕМ ФУНКЦИЙ

В структуре С-программ основной структурной единицей является функция. С-программа содержит главную функцию main, а также может включать одну или несколько подпрограмм-функций.

Различают описание и представление функций. Описание делает возможным доступ ку функции (помещает ее в область видимости), информирует компилятор о типе возвращаемого значения, о типе передаваемых ей значений . Описание часто называют прототипом функции. Использование прототипа обязательно, если функция описана после того, как она вызывается , например, после main-функции, причем прототип предваряется служебным словом extern.

Представление функции включает:

-тип значения, возвращаемого функцией;

-число и тип формальных параметров;

-код (тело) функции, который должен выполняться при вызове функции;

-локальные переменные.

Определение функции является его прототипом, если функция описана до того, как будет вызвана.

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

27

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

Пример. Определить максимальный и минимальный элементы массива с использованием подпрограммы-функции.

# include <stdio.h>

 

# include <stdlib.h>

 

# define m 8

// макропеременная m

typedef float mas[m]

// пользовательский тип данных

float a[m], amax, amin;

// глобальные переменные

float ma()

// процедура-функция

{int i, amax=a[0];

 

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

 

if (a[i]>amax) amax=a[i];

 

return amax;}

// возврат значения

void main()

// главная функция программы

{

 

extern float mi(float d[], int i);

// заголовок функции

int i; float c[m];

 

randomize();

// генератор случайных чисел

printf(“Array c \n”);

 

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

// заполнение массива

{c[i]=0.1*random(20); printf(“%5.2f”,c[i]);}

printf(“\n max=%f min=%f\n”,ma(c,m),mi(c,m)); // вызов функций

}

 

float mi(mass d, int i)

// тело подпрограммы-функции

{ int i; float dmin=d[0];

 

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

 

if (d[i]<dmin) dmin=d[i];

 

return dmin;}

 

Лабораторная работа 9 СТРУКТУРЫ И ОБЪЕДИНЕНИЯ

28

Помимо массивов к структурированным или агрегатным типам относятся структуры и объединения, которые заключают в себе данные разного типа. Структура описывается следующим образом:

struct <имя структуры>

{

тип <имя_поля1>; тип <имя_поля2>;

тип <имя_поляN>;

};

Определение структуры является оператором, поэтому заканчивается точкой с запятой. Переменные, которые объединяются структурой, называются членами, элементами или полями структуры.

Пример. Определения структуры STUDENT (сведений о студенте) struct STUDENT {

сhar Name[30]; char Groupe[5]; int Age;

};

Такая запись не задает никакой переменной и выделения памяти не происходит. Под именем STUDENT задается частный вид структуры или шаблон структуры, т.е. определен новый тип struсt STUDENT. Для объявления конкретных переменных этого типа можно написать:

struct <имя структуры> <список переменных>;

Пример. struct STUDENT stud1, stud2;

Переменные также могут задаваться одновременно с шаблоном struct STUDENT {

сhar Name[30]; char Groupe[5]; int Age;

} stud1, stud2;

Теперь объявлены две переменные и компилятор автоматически выделит под них память (под каждую переменную непрерывный участок).

Внешние статические структуры можно инициировать, помещая следом за определением список начальных значений элементов:

struct stud1="Иванов И.","А-319", 21;

Как и для других типов, структурам можно давать имена с помощью оператора typedef, т.е.

typedef struct <имя структуры>

29

{

тип <имя_поля1>; тип <имя_поля2>;

тип <имя_поляN>; } <имя типа>;

Обращение к элементу структуры осуществляется через селектор, т.е. сначала пишется имя переменной структурного типа, а затем через точку – имя элемента.

<имя_переменной_стр>.<имя_поля>

Структура операции доступа к полю по указателю:

переменная_указатель -> имя_поля;

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

Пример. (*uk).a или uk->a; // получение значения поля а переменной uk Пример. Сформировать таблицу, содержащую следующую информацию

о студентах: ФИО, год рождения, группа, адрес. Вывести студентов,

проживающих в городе Омске.

 

#include <stdio.h>

 

#include <string.h>

 

#include <conio.h>

 

typedef struct address

// создание пользовательского типа adress

{char city[30];

 

char street_house_flat[60];};

 

typedef struct data

// создание пользовательского типа

 

//информация о студентах

{char fio[60]; int year_birthday; char group[10];

address st_adress; }; void main()

{data st_group[25]; char st_fio[30], num_group[10], st_city[20], st_adr[60]; clrscr();

cout<< “Input data”<<endl;

for (int i=0; i<25; i++) // заполнение сведений о студентах

{ cout<< “Input FIO”; gets(st_fio); strcpy(st_group.fio,st_fio); cout << “Input year_birthday”; cin>> st_group.year_birthday;

cout<<”Input group”; gets(num_group); strcpy(st_group.group,num_group); cout<<”Iput city”; gets(st_city); strcpy(st_group.st_adress.city,st_city);

30