Способы объявления и обращения к элементам массивов



Способы объявления и обращения

К элементам одномерных массивов

 

Объявление одномерного массива с явным указанием количества элементов массива:

<тип_элементов_массива> <имя_массива> [<количество_элементов>];

Обращение к элементам одномерного массива в общем случае можно представить индексированием:

<имя_массива> [<выражение>];

где <имя_массива> – указатель–константа, адрес нулевого элемента массива; <выражение>  определяет индекс элемента массива.

Элементы одномерного массива располагаются в ОП последовательно друг за другом: нулевой, первый и т.д. При объявления массива 

int а[10];

компилятор выделяет массиву ОП для размещения его элементов в размере sizeof(<тип_элементов_массива>)*<размер_массива> байт, т.е. 4 ∙ 10 = 40 байт. Запись &a[i] равносильна записи (а + i). В программе &a[i] или (а + i) определяет  адрес i-го элемента массива. На машинном уровне (в соответствии с определением операций над указателями) адрес i-го элемента массива &a[i] формируется в виде  а + i*sizeof(int) .

В связи с вышеизложенным, будут справедливы соотношения:

 а + 0  &а[0] – адрес нулевого элемента массива а;

а + 2  &а[2] – адрес второго элемента массива а;

а + i  &a[i] – адрес i-го элемента массива а;

 

 *(а + 0)  *(&а[0])  а[0] – значение нулевого

элемента массива а;

*(а+2)  а[2] – значение второго элемента массива;

*(а + i)  a[i] – значение i-го элемента массива;

 

*а + 2  а[0] + 2 – сумма значений а[0] и 2.

Если р – указатель на тип данных, совпадающий с типом элементов массива а и адрес, который содержит указатель р, совпадает с адресом массива а, то а и р взаимозаменяемы. При этом

р  &а[0]  а + 0;

р + 2  &а[2]  а + 2;

*(р + 2)  *(&а[2])  а[2];

*(p + i)  *(&a[i])  a[i].

Способы объявления и обращения

К элементам двухмерных массивов

 

Рассмотрим объявление и связь указателей и элементов двухмерных массивов. Двухмерный массив в языке С++ рассматривается как совокупность одномерных масси­вов (его строк), а строка – совокупность элементов одно­мерного массива.

Объявление двухмерного массива с явным указанием количества элементов массива:

<тип_элементов_массива> <имя_массива>[<кол–во_строк>][<кол–во_столбцов>];

Для обращения к элементам двухмерного массива используется два индекса (индексных выражений):

<имя_массива>[<выражение1>][<выражение2>];

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

Пример объявления двухмерного массива значений типа:

int a[m][n];

Этот массив состоит из m одномерных массивов (строк), каждый из кото­рых содержит n элементов (столбцов). При работе с этим двухмерным масси­вом можно использовать одно или два индекса (индексных выражения), например, а[i][j] содержит 2 индекса. Такая запись используется для обращения к элементу, расположенному на пересечении i-й строки и j-го столбца массива. Для получения значения этого элемента вначале вычисляются индексные выражения, затем опре­деляется адрес элемента массива в ОП и извлекается его значение.

a[i] содержит один индекс: подобная запись определяет адрес одномерного массива, т.е адрес начала i-й строки массива.

Имя массива а не содержит индекса и определяет адрес массива, т.е. адрес его нулевого элемента.

Таким образом, обращение к двухмерным массивам с помощью имени и только одного индекса определяет указатель на начало соответствующей строки массива (адрес ее нулевого элемента). Напомним, что в одномерном массиве адрес i-го элемента массива &a[i] формируется в виде а + i*sizeof(int). Используя это, определим соотношения:

a[0]  &а[0][0]  a + 0*n*sizeof(int);

a[1]  &а[1][0]  а + 1*n*sizeof(int);

a[i]  &а[i][0]  а + i*n*sizeof(int);

Обращение к элементам многомерного массива более детально рассмотрим на примере двухмерного массива:

int a[3][4]; //а – указатель-константа

int *р=&а[0][0]; // р – указатель-переменная

После этого указатель р можно использовать вместо указателя а для обра­щения к строкам или элементам массива. В ОП элементы массива а располагаются таким образом, что быстрее всех изменяется самый правый индекс, т.е. в последовательности: a[0][0] а[0][1] а[0][2] а[0][3] а[1][0] ... а[2][0] а[2][1] а[2][2] а[2][3]

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

 а  &а[0][0]  *а – адрес элемента 0-й строки и 0-го столбца массива а;

*(&а[0][0])  а[0][0] – значение элемента 0-й строки  0-го столбца массива а;

a[i]  (а+i)  *(а+i)  &a[i][0] – адрес начала i-й строки, т.е. адрес элемента i-й строки и 0-го столбца;

*a[i]  *(&a[i][0])  a[i][0] – значение 0-го элемента i-й строки;

a[i][j]  *(*(a+i)+j)  *(a[i]+j)  a[i][j] – значение элемента i-й строки    j-го столбца массива а;

где (а+i)  *(a+i)  a[i] – адрес 0-го элемента i-й строки, т.е. &a[i][0];

(*(a+i)+j) – адрес j-го элемента i-й строки, т.е. &a[i][j];

*(*(a+i)+j) – значение j-го элемента i-й строки, т.е. a[i][j].

Значение адреса начала i-й строки (адреса 0-го элемента i-й строки) на машинном уровне формируется в виде:

a[i]  а+i  (a+i*n*sizeof(int))

где n — количество элементов в одной строке. Таким образом, адрес (i+1)-й строки смещен относительно i-й строки на (n*sizeof(int)) байт, т.е. на одну строку массива. Выражение a[i][j] компилятор С++ переводит в эквивалентное выражение *(*(а+i)+j).

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

Например, после объявления:

int a[m][n], *р = &а[0][0];
*(р+i*n+j) // значение j-го элемента в i-й строке;

где n – количество элементов в строке; i*n+j – смещение элемента a[i][j] относительно начала массива а.

 

Пример 1. Дан одномерный динамический массив. Вычислить среднее арифметическое модулей элементов массива.

 

Ход выполнения работы

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

2. Написать программу, соответствующую алгоритму:

Алгоритм Программа
объявление вещ: *а, sum ; цел: i, n // ввод количества элементов массива ввод n выделить динамическую память под указатель a // ввод элементов массива для i=0 до n-1 шаг 1   ввод ai     все для i //сначала сумма элементов равна нулю sum=0 для i=0 до n-1 шаг 1   // в цикле изменяется номер i   // элемента массива   // нужный элемент добавляется к   // сумме   sum=sum+ai все_для i // находим среднее арифметическое sum=sum/n // печатаем полученное значение печать sum // вывод массива на экран для i=0 до n-1 шаг 1 вывод ai все_для i освободить выделенную под указатель a динамическую память   #include "stdio.h" #include "stdlib.h" int main ( ) { float *а, sum;  int i, n; // ввод n printf ("n=" ); scanf ("%i", &n); a=(float*)malloc(n*sizeof(float)); //ввод одномерного динамического //массива  с  клавиатуры for ( i=0; i<=n-1; i++ ) {       printf(“a%i=”,i);       scanf(“%f”,a+i); } // сначала сумма элементов равна нулю sum=0; // вычисление суммы элементов for ( i=0; i<=n-1; i++ )        sum=sum+*(a+i); // находим среднее арифметическое sum=sum/n; // печатаем полученное значение printf("sred_arif=%f\n", sum); // вывод одномерного динамического // массива на экран for (i=0; i<=n-1; i++)        printf ("%.3f ", *(а+i)); printf("\n"); free(a); return 1; }

Примечание. Для выделения динамической памяти под массив из n элементов использовалась библиотечная функция malloc():

 

 

Для ввода элементов массива как обычно использовалась функция scanf(). Вторым аргументов этой функции является адрес переменной, которая получает вводимое значение. В данном примере это адрес i-го элемента динамического массива a+i. При вычислении суммы значение i-го элемента получали с помощью записи


                                                        

 

Вывод элементов массива осуществляется при помощи функции printf(), где для вывода элементов применялась та же форма записи.

3. Создать проект и реализовать данную задачу в среде                 Visual C++ 6.0.

Пример 2.  Сформировать двухмерный динамический массив по закону .

 

Ход выполнения работы

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

2. Написать программу, соответствующую алгоритму:

Алгоритм Программа
объявление вещ: *а ; цел: i, n // ввод количества строк массива ввод n // ввод количества столбцов массива ввод m выделить динамическую память под указатель a // формирование массива построчно для i=0 до n-1 шаг 1 для j=0 до m-1 шаг 1        aij=i+j     все для j все для i // вывод массива построчно для i=0 до n-1 шаг 1 для j=0 до m-1 шаг 1        вывод aij все для j все_для i освободить выделенную под указатель a динамическую память   #include "stdio.h" #include "stdlib.h" int main ( ) { int *a;  int i, j, m, n; //ввод n printf ("n=" ); scanf ("%i", &n); //ввод m printf ("m=" ); scanf ("%i", &m); //выделение динамической памяти под //целочисленный массив из n строк и //m столбцов a=(int*)malloc(n*m*sizeof(int)); //формирование динамического массива //построчно for ( i=0; i<=n-1; i++ )          for ( j=0; j<=m-1; j++ )          {                *(a+i*m+j)=i+j;           } //вывод динамического массива //построчно for (i=0; i<=n-1; i++) {    for ( j=0; j<=m-1; j++ )            printf ("%i ", *(a+i*m+j));    printf("\n"); } //освобождение выделенной // динамической памяти   free(a); return 1; }

3. Создать проект и реализовать данную задачу в среде                 Visual C++ 6.0.

 

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

 

Ход выполнения работы

1. Решение этой задачи было подробно рассмотрено в разделе «Двухмерные массивы».

2. Написать программу, соответствующую алгоритму:

Алгоритм Программа
объявление вещ: *а,p,*b, цел: i, j, pmin, n, m // ввод количества строк массива ввод n // ввод количества столбцов массива ввод m выделить динамическую память под указатель a выделить динамическую память под указатель b // ввод массива построчно для i=0 до 6-1 шаг 1 // в цикле изменяется номер i строки // массива для j=0 до 4-1 шаг 1        // в цикле изменяется номер        // столбца массива j        // затем элемент вводится       ввод аij все_для j все_для i // вычисление произведений для j=0 до 4-1 шаг 1 // в цикле изменяется номер j столбца // массива //находим произведение j-го столбца p=1 для i=0 до 6-1 шаг 1        // в цикле изменяется номер строки        // массива i        // находим нечетный элемент       если остаток от дел aij на 2 =1               //изменяем произведение               p=p*aij       все_если все_для j  b[j]=p все_для i //находим минимальный элемент //массива b p=b0 //номер минимального элемента pmin=0 для i=1 до 4-1 шаг 1 если p<bi         p=bi         pmin=i все_если все_для i // вывод массива a построчно для i=0 до 6-1 шаг 1 // в цикле изменяется номер i строки // массива для j=0 до 4-1 шаг 1        // в цикле изменяется номер j        // столбца массива        // затем этот элемент выводится на        // экран       вывод аij все_для j все_для i // вывод массива b для i=0 до 4-1 шаг 1 вывод bi все_для i печать pmin #include "stdio.h" #include "stdlib.h" #include "math.h" int main() { float *a, p, *b; int i, j, pmin, n, m; //ввод n   printf ("n=" );   scanf ("%i", &n); //ввод m   printf ("m=" );  scanf ("%i", &m); //выделение динамической памяти под //целочисленный массив из n строк и //m столбцов   a=( float *)malloc(n*m*sizeof(float));   b=( float *)malloc(m*sizeof(float)); // ввод динамического массива a // построчно for(i=0; i<=n-1; i++) {         for (j=0; j<=m-1; j++)         {               printf ("a[%i][%i]=",i,j);               scanf ("%f", a+i*m+j);         } } // вычисление произведений for(j=0; j<=m-1; j++) {            p=1;         for (i=0; i<=n-1; i++)         {               if(fmod(*(a+i*m+j),2)==1)               p=p*(*(a+i*m+j));         }            *(b+j)=p; } //находим минимальный элемент массива //b    p=*b; //нулевой элемент массива b    pmin=0; for (i=0; i<=m-1; i++) {                if(p>*(b+i))            {         p=*(b+i);                pmin=i;            }    } // вывод массива a построчно    for (i=0; i<=n-1; i++) {                for (j=0; j<=m-1; j++)               printf ("%.2f ", *(a+i*m+j));            printf ("\n"); }    printf ("\n"); // вывод массива b    for (i=0; i<=m-1; i++) {             printf ("%.2f ", *(b+i)); }    printf ("\n");    printf ("№min=%i\n", pmin); free(a); free(b);    return 1; }

3. Создать проект и реализовать данную задачу в среде                 Visual C++ 6.0.

 

Л екция 14

Символы и строки

Цели:

ü получить представление о символьном типе данных и познакомиться с функциями, работающими с символами;

ü познакомиться с понятием строки в С++ и строчными функциями;

ü освоить методику написания алгоритмов с использованием символьных и строчных переменных, перевода таких алгоритмов на язык программирования С++ (с и без использования побитовых операций) и разработки соответствующего проекта в среде Visual C++ 6.0.

Символьный тип данных

 

Символьным типом данных на языке С++ является тип char. На машинном уровне символы представляются как целые числа. Для хранения символов и манипулирования ими каждому символу поставлен в соответствие его код – целое число. Существует несколько стандартов, определяющих, какие коды каким символам соответствуют. В С++ для кодировки символов используется стандарт ASCII, определяющий коды от 0 до 127. Для представления русских букв используется стандарт   КОИ-8 или CP-1251. В этих стандартах русские буквы кодируются числами от 128 до 255. Таким образом, все символы могут быть представлены в одном байте. Значением переменных символьного типа может быть либо числовой код символа, либо символьная константа. Присваивание вида  ch=’ab’; приведет к ошибке. Символьная константа – это один символ, заключенный в апострофы. Переменным символьного типа можно присвоить значение целого типа, выходящее за пределы диапазона то 0 до 255, но при этом компилятор преобразует это значение к значению в пределах от 0 до 255.

Объявление переменной символьного типа:

сhar ch; //ch – переменная символьного типа

сh=’а’;  // символы на языке С++ заключаются в апострофы

ch=235; // такое присваивание возможно

Так как значением символьной переменной может быть целое число, то к переменным символьного типа применимы арифметические операции: +, -, *, /. Символьные переменные можно сравнивать при помощи операций отношения: >, <, >=, <=, = =, !=. При этом следует учитывать то, что все эти операции производятся с целыми числами – кодами символов. Таким образом, символьные переменные сравниваются через ASCII-коды соответствующих символов. Чем «старше» символ, тем больший ASCII-код ему соответствует.

Для работы с символами определены библиотечные функции, описанные в файлах conio.h, ctype.h и stdio.h. Некоторые из этих функций описаны в табл.8.

Таблица 8

Функция Форма обращения к функции и её краткое описание

Файл ctype.h

isalnum i = isalnum(int с); i – переменная типа int i не равно нулю, если значение с – код буквы или цифры (A...Z, a...z, 0...9); i = 0 – в противном случае
isalalpha i = isalalpha (int с); i – переменная типа int i не равно нулю, если значение с – код буквы или цифры (A...Z, a...z); i = 0 – в противном случае
isascii i = isascii (int с); i – переменная типа int i не равно нулю, если значение с – код ASCII, т.е. принимает значение от 0 до 127; i = 0 – в противном случае
isdigit i = isdigit (int с); i – переменная типа int i не равно нулю, если значение с – цифра (О... 9) в коде ASCII; i = 0 – в противном случае
toascii i = toascii (int с); i – переменная типа int i принимает значение в диапазоне от 0 до 127, т.е функция преобразует целое число с в символ кода ASCII

Файл stdio.h

scanf scanf ("%c", &ch); Функция форматированного ввода с клавиатуры ch – переменная типа char. Формат ввода "%c" означает, что с клавиатуры будет считываться один символ
printf printf ("%c", ch); Функция форматированного вывода ch – переменная типа char. Формат вывода "%c" означает, что на экран будет выведен один символ
getchar ch = getchar (); Считывает очередной символ, введенный с клавиатуры.  Введенный символ отображается на экране ch – переменная типа char, которая получает введенное с клавиатуры значение
putchar putchar (ch); Выводит символ сh на экран ch – переменная типа char

Файл conio.h

getch ch = getch (); Считывает один символ, введенный с клавиатуры без отображения на экране ch – переменная типа char, которая получает введенное с клавиатуры значение

Строки

 

Строка в языке С++ – это одномерный массив символьного типа char. Массив из n символов на самом деле будет содержать не n, а n-1 значащий символ. Причиной этого является то, что строка всегда содержит маркер или признак конца строки – это символ ’\0’. Строки на С++ заключаются в кавычки.

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

Объявлять строки можно двумя способами:

1. Строка – динамический массив символов:

char * s;

При таком объявлении массива в программе нужно будет обязательно выделить динамическую память под указатель s. Далее можно работать со строкой как с динамическим массивом символов;

2. Строка – статический массив символов:

char s[500];

Обрабатываются строки, содержащие не более 499 символов, со строкой можно работать как со статическим массивом.

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

char s[ ]= “строка”;

В данном случае строка s будет содержать 7 элементов (символов): ‘с’, ‘т’, ‘р’, ‘о’, ‘к’, ‘а’, ‘\0’. Однако невозможно присваивание вида

char s[ 20];

s=“строка”;

так как операция присваивания для строк не определена.

Если приходится работать с несколькими строками, то можно объявить массив строк – двухмерный массив символов.

char st [5][200];

Такой массив может содержать 5 строк, в каждой из которых может быть не более 199 символов.

По причине того что над строками в языке С++ не определены операции отношения, сложения и т.п., для этих целей разработаны библиотечные функции, описанные в головных файлах string.h и stdio.h (табл.9).

 

 

Таблица 9

Файл string.h

Функция Форма обращения к функции и её краткое описание
1 2
atof d = atof(str) ; Преобразует строку str в вещественное число d d – переменная типа double; str – строка, в которой записано вещественное число в виде набора символов–цифр и точки. Переводится часть строки, начиная с крайнего левого символа до первого появления символа, отличного от цифры или точки
atoi i = atoi(str); Преобразует строку str в десятичное целое число i i – переменная типа int; str – строка, в которой записано целое число в виде набора символов-цифр. Переводится часть строки, начиная с крайнего левого символа до первого появления символа, отличного от цифры
atol l = atol(str); Преобразует строку str в длинное десятичное целое число l l – переменная типа long; str – строка, в которой записано целое число в виде набора символов-цифр. Переводится часть строки, начиная с крайнего левого символа до первого появления символа, отличного от цифры
itoa itoa(v,str,baz); Преобразует целое v в строку str. При изображении числа используется основание системы счисления baz (2<=baz<=36) v – переменная типа int; str – строка; baz – переменная типа int
ltoa ltoa(v,str,baz); Преобразует длинное целое v в строку str. При изображении числа используется основание baz (2<=baz<=36) l – переменная типа long; str – строка; baz – переменная типа int
strcat strcat(str1,str2) ; Приписывает строку str2 в конец строки str1 (конкатенация строк) Результат в строке str1
strncat strncat(str2,str1,kol); Приписывает kol символов строки str1 в конец строки str2 (конкатенация) kol – переменная типа int
strchr str2 = strchr(str1,сh); Ищет в строке str1 первое вхождение символа сh (тип char). В строку str2 записывается часть строки str1, начинающаяся с первого вхождения символа ch. Если такой символ не найден, то str2 равно NULL
strrchr str2 = strrchr(str1,сh); Ищет в строке str1 последнее вхождение символа сh (тип char). В строку str2 записывается часть строки str1, начинающаяся с последнего вхождения символа ch. Если такой символ не найден, то str1 равно NULL
strcmp i = strcmp(strl,str2);   Сравнивает строки strl и str2. Результат заносится в переменную i (тип int) i<0, если strl<str2; i=0, если strl==str2; i>0, если strl>str2 (сравнение беззнаковое посимвольное)

 

Продолжение таблицы 9

1 2
strcpy strcpy(str1, str2); Копирует символы строки str2 в строку str1
strncpy strncpy(str2,str1,kol); Копирует kol символов строки str1 в строку str2 («хвост» отбрасывается или дополняется пробелами) kol – переменная типа int
strlen i = strlen(str); Вычисляет длину строки str без символа ‘\0’. Результат – в переменной i (типа unsigned int)

Файл stdio.h

Функция Форма обращения к функции и её краткое описание
gets gets(str); Считывает строку str как введенную с клавиатуры последовательность символов до первого нажатия клавиши <enter>
puts puts (str); Выводит строку str на экран

Примечание. Строку можно вводить с клавиатуры с помощью функции gets() и функции scanf(). При этом нужно помнить, что если первая функция заполняет строку символами до первого нажатия клавиши <enter>, то вторая записывает в строку введенные с клавиатуры символы до появления первого пробела.

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

Пример 1. Дан текст. Распечатать текст в обратном порядке.

 

Ход выполнения работы

1. Алгоритмы решения задач с использованием строк основаны на алгоритмах обработки одномерных массивов.

2. Написать программу, соответствующую алгоритму:

Алгоритм Программа
объявление симв: *str; цел: i, n, // ввод количества символов текста ввод n выделить динамическую память под указатель str ввод строки str //в цикле проверяется каждый символ, //начиная с последнего для i= strlen(str) до 0 шаг -1 печать stri все для i освободить выделенную под указатель str динамическую память   #include "stdio.h" #include "stdlib.h" #include "string.h" int main ( ) { char *str;  int n; unsigned int i; //ввод n printf ("n=" ); scanf ("%i", &n); //выделяется динамическая память str=(char*)malloc(n); //ввод строки gets(str); for ( i= strlen(str); i>=0; i-- ) {       printf("%c",*(str+i)); } printf("\n"); //освобождение выделенной //динамической памяти free(str); return 1; }

3. Создать проект и реализовать данную задачу в среде                 Visual C++ 6.0.

 

Пример 2. Дан текст. Подсчитать, сколько в нем слов. Словом считать набор символов, не содержащий символов: ‘.’ , ‘!’ , ‘?’ , ‘,’ , ‘;’ , ‘:’, ‘ ’. Подсчитать количество слов, содержащих 5 символов.

 

Ход выполнения работы

1. Для подсчета количества символов, содержащихся в каждом слове текста, необходимо определить начало и конец слова, т.е. определить позиции первого и последнего символов каждого слова. Найдя их разность, сравним её с числом 5. Если нужное слово найдено, то увеличим некоторый счетчик на 1. Первый символ слова определим по правилу: если в позиции i находится один из символов ‘.’ , ‘!’ , ‘?’ , ‘,’ , ‘;’ , ‘:’ , ‘ ’, а в позиции i+1 нет ни одного из них, то, с позиции i+1 начинается слово. Последний символ слова определим по правилу: если в позиции i нет ни одного из символов ‘.’ , ‘!’ , ‘?’ , ‘,’ , ‘;’ , ‘:’ , ‘ ‘, а в позиции i+1 находится один из них, то, начиная с позиции i, слово заканчивается.

2. Написать программу, соответствующую алгоритму:

Алгоритм Программа
объявление симв: *str; цел: i, n, bw, ew, count, count_5 // ввод количества символов текста ввод n выделить динамическую память под указатель str ввод строки str count =0, count_5=0 //в цикле проверяется каждый символ для i=0 до strlen(str) шаг 1 //определяем первый символ слова пока stri=='.' или stri=='!' или stri=='?'           или stri==',' или stri==';'           или stri==':' или stri==' '            и i<=strlen(str)            //пропускаем эти символы            i++ все_пока //запоминаем позицию начала слова bw=i //определяем последний символ слова пока stri!='.' и stri!='!' и stri!='?' и stri!=','           и stri!=';' и stri!=':' и stri!=' '           и i<=strlen(str)            //пропускаем символы слова            i++ все_пока //запоминаем позицию конца слова ew=i-1 если ew-bw>=0          count++ все_если если ew-bw+1==5          count_5++ все_если все для i вывод count вывод count_5 вывод строки str освободить выделенную под указатель str динамическую память   #include "stdio.h" #include "stdlib.h" #include "string.h" int main ( ) { char *str;  int n, bw, ew, count, count_5; unsigned int i; //ввод n printf ("n=" ); scanf ("%i", &n); //выделяется динамическая память str=(char*)malloc(n); //ввод строки gets(str); count =0, count_5=0; for ( i=0; i<=strlen(str); i++ )  {       //определяем первый символ       //слова       while((*(str+i)=='.' || *(str+i)=='!' ||                     *(str+i)=='?' || *(str+i)==',' ||                  *(str+i)==';'  || *(str+i)==':' ||                  *(str+i)==' ')                   && i<=strlen(str))                 //пропускаем эти символы                 i++;       //запоминаем позицию начала        //слова        bw=i;       //определяем последний символ        //слова       while(*(str+i)!='.' && *(str+i)!='!'                  && *(str+i)!='?'&&                  *(str+i)!=',' && *(str+i)!=';'                   && *(str+i)!=':' &&                  *(str+i)!=' '&& i<=strlen(str))                   //пропускаем символы                   //слова                   i++;        //запоминаем позицию конца        //слова       ew=i-1;       if(ew-bw>=0)            count++;        if(ew-bw+1==5)            count_5++;  } //вывод count printf(“количество слов в тексте = %i\n”,count); //вывод count_5 printf(“количество слов из 5 символов             = %i\n”,count_5); //вывод строки str puts(str); //освобождение выделенной динамической памяти free(str); return 1; }

3. Создать проект и реализовать данную задачу в среде                 Visual C++ 6.0.

 

Запишем те же алгоритм и программу с использованием статического массива:

Алгоритм Программа
объявление симв: str[200]; цел: i, bw, ew, count, count_5 ввод строки str count =0, count_5=0 //в цикле проверяется каждый символ для i=0 до strlen(str) шаг 1 //определяем первый символ слова пока str[i]=='.' или str[i]=='!' или           str[i]=='?' или str[i]==',' или            str[i]==';' или str[i]==':' или           str[i]==' ' и i<=strlen(str)           //пропускаем эти символы            i++ все_пока //запоминаем позицию начала слова bw=i //определяем последний символ слова пока str[i]!='.' и str[i]!='!' и str[i]!='?' и           str[i]!=',' и str[i]!=';' и str[i]!=':' и           str[i]!=' ' и i<=strlen(str)            //пропускаем символы слова            i++ все_пока //запоминаем позицию конца слова ew=i-1 если ew-bw>=0          count++ все_если если ew-bw+1==5          count_5++ все_если все для i вывод count вывод count_5 вывод строки str   #include "stdio.h" #include "stdlib.h" #include "string.h" #define n 200 int main ( ) { char str[n];  int bw, ew, count, count_5; unsigned int i; //ввод строки gets(str); count =0, count_5=0; for ( i=0; i<=strlen(str); i++ ) {       //определяем первый символ       //слова       while((str[i]=='.' || str[i]=='!' ||                   str[i]=='?'|| str[i]==',' ||                   str[i]==';' || str[i]==':' ||                   str[i]==' ') && i<=strlen(str))                 //пропускаем эти символы                 i++;        //запоминаем позицию начала        //слова        bw=i;        //определяем последний символ        //слова        while(str[i]!='.' && str[i]!='!' &&                  str[i]!='?'&& str[i]!=',' &&                   str[i]!=';' && str[i]!=':' &&                  str[i]!=' ' && i<=strlen(str))                   //пропускаем символы                   //слова                   i++;        //запоминаем позицию конца        //слова        ew=i-1;        if(ew-bw>=0)            count++;        if(ew-bw+1==5)            count_5++; } //вывод count printf(“количество слов в тексте = %i\n”,count); //вывод count_5 printf(“количество слов из 5 символов             = %i\n”,count_5); //вывод строки str puts(str); return 1; }

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

 

Пример 3. Дан текст. Распечатать текст по предложениям. Предложением считать набор символов, заканчивающийся одним из символов: ‘.’ , ‘!’ , ‘?’.

 

Ход выполнения работы

1. Написать программу, соответствующую алгоритму:

Алгоритм Программа
объявление симв: *str; цел: i, j, n, bp, ep // ввод количества символов текста ввод n выделить динамическую память под указатель str ввод строки str //в цикле проверяется каждый символ для i=0 до strlen(str) шаг 1 //определяем первый символ // предложения пока stri=='.' или stri=='!' или stri=='?'            и i<=strlen(str)            //пропускаем эти символы            i++ все_пока //запоминаем позицию начала // предложения bp=i //определяем последний символ //предложения пока stri!='.' и stri!='!' и stri!='?' и           i<=strlen(str)            //пропускаем символы слова            i++ все_пока  //запоминаем позицию конца //предложения ep=i //печатается очередное предложение для j= bp до ep шаг 1          печать strj все_для j все для i освободить выделенную под указатель str динамическую память   #include "stdio.h" #include "stdlib.h" #include "string.h" int main ( ) { char *str;  int j, n, bp, ep; unsigned int i; //ввод n printf ("n=" ); scanf ("%i", &n); //выделяется динамическая память str=(char*)malloc(n); //ввод строки gets(str); for ( i=0; i<=strlen(str); i++ ) {       //определяем первый символ       // предложения       while((*(str+i)=='.' || *(str+i)=='!' ||                   *(str+i)=='?') &&                    i<=strlen(str))                  //пропускаем эти символы                 i++;        //запоминаем позицию начала        //предложения        bp=i;        //определяем последний символ        //предложения        while(*(str+i)!='.'&&*(str+i)!='!'&&                  *(str+i)!='?'&& i<=strlen(str))                   //пропускаем символы                   //слова                   i++;        //запоминаем позицию конца        // предложения        ep=i;       //печатается очередное        //предложение        for(j=bp;j<=ep;j++)             //выводится j-ый символ             //предложения             printf("%c",*(str+j));        printf("\n"); } //освобождение выделенной //динамической памяти free(str); return 1; }

2. Создать проект и реализовать данную задачу в среде                 Visual C++ 6.0.

 

Пример 4. Дан текст. Распечатать позиции, начиная с которых в тексте встречается заданное слово. Определение слова такое, как и в предыдущих примерах.

 

Ход выполнения работы

1. Написать программу, соответствующую алгоритму

Алгоритм Программа
объявление симв: *text,*slovo; цел: i, j, n, bw, ew, flag // ввод количества символов текста ввод n выделить динамическую память под указатели text, slovo ввод text ввод slovo //в цикле проверяется каждый символ для i=0 до strlen(text) шаг 1 //определяем первый символ слова пока texti=='.' или texti=='!' или           texti=='?' или texti==',' или            texti==';' или texti==':'           или texti==' ' и i<=strlen(text)            //пропускаем эти символы            i++ все_пока //запоминаем позицию начала слова bw=i //определяем последний символ слова     пока texti!='.' и texti!='!' и texti!='?' и           texti!=',' и texti!=';' и texti!=':' и           texti!=' ' и i<=strlen(text)            //пропускаем символы слова            i++ все_пока //запоминаем позицию конца слова ew=i-1 //сравниваем slovo и слово текста если ew-bw+1== strlen(slovo)       flag=1;//длины слов совпадают       для j= 0 до ew-bw шаг 1            если textbw+j !=slovoj                  flag=0;//слова не совпадают                  выход из цикла по j            все_если      все_для j все_если если flag==1          flag=0          печать bw все_если все для i освободить выделенную под указатели text, slovo динамическую память   #include "stdio.h" #include "stdlib.h" #include "string.h" int main ( ) { char *text,*slovo;  int j, n, bw, ew, flag; unsigned int i; //ввод n printf ("n=" ); scanf ("%i", &n); //выделяется динамическая память text=(char*)malloc(n); slovo=(char*)malloc(20); //ввод строк puts("text="); gets(text); puts("slovo="); gets(slovo); for ( i=0; i<=strlen(text); i++ ) {       //определяем первый символ слова       while((*(text+i)=='.' || *(text+i)=='!' ||                   *(text+i)=='?'|| *(text+i)==',' ||                   *(text+i)==';' || *(text+i)==':' ||                   *(text+i)==' ')                    && i<=strlen(text))                 //пропускаем эти символы                 i++;        //запоминаем позицию начала        //слова        bw=i;        //определяем последний символ        // слова       while(*(text+i)!='.'&&*(text+i)!='!'                 && *(text+i)!='?'&&                 *(text+i)!=','&& *(text+i)!=';'                  &&*(text+i)!=':'&&                  *(text+i)!=' '                   && i<=strlen(text))                   //пропускаем символы слова                   i++;        //запоминаем позицию конца        //слова        ew=i-1;   if(ew-bw+1== strlen(slovo))   {         flag=1;         for(j=0;j<=ew-bw;j++)                if(*(text+bw+j)!=*(slovo+j))                {                      flag=0;                      break;                }   }        if(flag==1)   {         flag=0;            printf("pos=%i\n",bw);   }     } //освобождение выделенной //динамической памяти free(text); free(slovo); return 1; }

2. Создать проект и реализовать данную задачу в среде                 Visual C++ 6.0.

Пример 5. Дан текст в виде набора 0 и 1 – некоторое число в двоичной системе счисления. Представить это число в десятичной системе счисления.

 

Ход выполнения работы

1. Алгоритм перевода числа из двоичной системы счисления в десятичную систему счисления поясним на примере.

Наименование

Разряды в двоичной системе счисления

Число

6 5 4 3 2 1 0
Число в двоичной системе счисления, записанное по разрядам 1 1 0 1 0 0 1 11010012
Слагаемые для получения числа в десятичной системе счисления, соответствующие каждому разряду 1·26 1·25 0·24 1·23 0·22 0·21 1·20 10510

Таким образом, 11010012=1·20+0·21+0·22+1·23+0·24+1·25+1·26 =1+8+32+64=10510.

2. Написать программу, соответствующую алгоритму:

Алгоритм Программа
объявление вещ: *num_bin; цел: i, j, n, num_dec // ввод количества символов текста ввод n выделить динамическую память под указатель num_bin ввод num_bin j=strlen(num_bin)-1 num_dec=0 //в цикле проверяется каждый символ для i=strlen(num_bin) до 0 шаг -1 //сравниваем символ текста с // символом ‘1’ если num_bini = = ‘1’        num_dec=num_dec+2j-i все_если все для i печать num_dec освободить выделенную под указатель num_bin динамическую память   #include "stdio.h" #include "stdlib.h" #include "string.h" #include "math.h" int main ( ) { char *num_bin;  int n, num_dec; unsigned int i; //ввод n printf ("n=" ); scanf ("%i", &n); //выделяется динамическая память num_bin=(char*)malloc(n); //ввод строки puts("num_bin="); gets(num_bin ); //определяется количество разрядов j=strlen(num_bin)-1; //инициализируется значение в //десятичной системе num_dec=0; for ( i= strlen(num_bin); i>=0; i-- ) {       // сравниваем символ текста с       // символом ‘1’   if(*(num_bin+i)= =’1’)   {         num_dec=num_dec+pow(2, j-i);   } } printf("num_dec=%i\n ",num_dec); //освобождение выделенной //динамической памяти free(num_bin); return 1; }

3. Создать проект и реализовать данную задачу в среде                 Visual C++ 6.0.

Пример 6. Дано целое число в десятичной системе счисления. Представить это число в двоичной системе счисления.

 

 Ход выполнения работы

1. Алгоритм перевода числа из десятичной системы счисления в двоичную осуществляется путем деления десятичного числа на 2. Запоминается остаток, и полученное частное снова делится на 2. Эта процедура повторяется до тех пор, пока полученное на некотором шаге частное не станет равным 0 или 1. Записав остатки от деления в обратном порядке, получим число в двоичной системе счисления (в программе результат помещается в строку), например:

105 2

1 52 2

    0 26 2

         0 13 2

              1 6 2

                  0 3 2

                     1 1

Таким образом, 10510 = 11010012 (порядок записи остатков указан стрелкой). Решить данную задачу можно было бы с использованием операции деления, т.е. непосредственно по приведенному алгоритму. Воспользовавшись поразрядными операциями и понятием маски можно упростить решение задачи. Для этого установим начальное значение маски в 1. При помощи операции & проверим, совпадает ли самый правый бит с маской или нет. Если совпадает, то в текущую позицию строки записываем 1, в противном случае – 0. Затем сдвигаем 1 в маске на одну позицию влево. Опять происходит описанная выше проверка и т.д. Количество проверок должно совпадать с количеством бит переменной (десятичным числом), т.е. с размером типа этой переменной, умноженного на 8 (количество байт, занимаемых переменной в ОП, умножаем на количество бит, содержащихся в одном байте).

2. Написать программу, соответствующую алгоритму:

Алгоритм Программа
объявление вещ: *num_bin; цел: i, n, num_dec, mask=1 ввод num_dec n=sizeof(num_dec)*8 выделить динамическую память под указатель num_bin из n+1 символов //в цикле проверяется каждый бит для i=1 до n+1 шаг 1 //проверяем i-ый бит числа num_dec //на наличие 1 если num_dec&mask           num_binn+1-i = = ‘1’ иначе           num_binn+1-i = = ‘0’ все_если сдвиг mask на 1 разряд влево все для i печать num_bin освободить выделенную под указатель num_bin динамическую память   #include "stdio.h" #include "stdlib.h" #include "string.h" #include "math.h" int main ( ) { char *num_bin;  int num_dec, mask=1;  int n, i; //ввод десятичного числа printf("num_dec="); scanf("%d",&num_dec); n=sizeof(num_dec)*8; //выделяется динамическая память num_bin=(char*)malloc(n+1); for ( i= 1; i<=n+1; i++ ) {       // проверяем i-ый бит числа       // num_dec на наличие 1   if(num_dec&mask)         //i–ый бит числа num_dec         //содержит 1         *(num_bin+n+1-i)='1';       else         //i–ый бит числа num_dec         //содержит 0         *(num_bin+n+1-i)='0';      //изменение маски       mask=mask<<1; } printf("num_bin="); // нули до первой 1 не печатаются for(i= 1; i<=n+1; i++)      if(*(num_bin+i)!=0)         break; // печатается число в двоичной системе for( ; i<=n; i++)      printf("%c",*(num_bin+i)); printf("\n"); //освобождение выделенной //динамической памяти free(num_bin); return 1; }

3. Создать проект и реализовать данную задачу в среде                 Visual C++ 6.0.

Л екция 15

Структуры

 

Цели:

ü получить представление о понятиях «структурный тип», «структура»;

ü освоить методику написания алгоритмов с использованием динамических и статических массивов структур, перевода таких алгоритмов на язык программирования С++ и разработки соответствующего проекта в среде Visual C++ 6.0.

 

Понятие структуры

 

При решении практических задач очень часто приходится сталкиваться с объектами, которые невозможно описать переменной одного типа. Для описания такого рода объектов требуется несколько переменных различного типа. Для решения этой проблемы в языке С++ используют понятие «структура» – это совокупность переменных различных типов, объединённых в одну переменную. Элементы структуры называются полями. В качестве полей структуры могут выступать скалярные величины, массивы, а также другие структуры. Таким образом, структурный тип задает внутреннее строение определяемых с его помощью структур-переменных. В отличие от массива, всегда состоящего из однотипных элементов, компоненты структуры-переменной могут быть разных типов и все должны иметь различные имена. Из определения структуры понятно, что заполнение и обработка структур производится только поэлементно – операции над структурами в языке С++ не определены, т.е. ввод-вывод элементов структуры-переменной осуществляется при помощи стандартных функций printf() и scanf(). Становится ясно, что объём оперативной памяти, которую занимает структура-переменная, будет равен суммарному объёму памяти, который занимают все элементы такой структуры.

Описание структуры производится при помощи спецификатора объявления структур: struct. Описание структуры:

struct <имя_структурного_типа>

{

  <имя_типа_данных_1> <поле_1>;

  <имя_типа_данных_2> <поле_2>;

                      …

  <имя_типа_данных_N> <поле_N>;

};

Объявление структуры-переменной:

struct <имя_структурного_типа> <имя_структуры–переменной>;

 

Например, структура «товар» содержит поля:

название товара

закупочная цена

торговая наценка в процентах

объем партии товара

дата поступления партии товара

В соответствии со смыслом поля могут иметь любой из типов данных, допустимых в языке. Так как наименований товаров на складе может быть много, то для определения отдельных структур, содержащих сведения о конкретных товарах, нужно ввести структурный тип. Для данного примера его можно определить так:

struct tovar

{

char name[50]; // Наименование

float price ;       // Цена оптовая

float percent;       // Наценка в %

int vol;            // 06ъем партии

char date[9] ; // Дата поставки партии

};

struct tovar tv;

В данном примере struct – спецификатор структурного типа; tovar – имя структурного типа; tv – структура-переменная.

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

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

gets(tv.name);             // ввод с клавиатуры поля name

tv.price = 1234.56;      // присваивание полю price значения 1234.56

scanf("%f",&tv.percent); // ввод с клавиатуры вещественного значения

                                    // по адресу поля percent

 


Дата добавления: 2019-11-25; просмотров: 499; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!