В языке программирования С заложены средства для задания последовательностей упорядоченных данных [6.1]. Такие последовательности называются массивами. В массивах должны быть упорядочены данные одного и того же типа. В данной лабораторной работе будут рассматриваться массивы символов, которые определятся типом char. Одномерный массив наиболее часто применяется в виде строки символов. Строка – это одномерный '\0'. При объявлении массива символов,
предназначенного для хранения строки, необходимо отвести одно место для нуля, т.е. для символа окончания строки '\0'. Например, если дана строка , в которой 6 символов, каждый из которых занимает в памяти 1 байт, то при инициализации такой строки необходимо отвести 1 байт для нулевого
символа. Поэтому следует сделать объявление строки для семи символов:
char str[7] = "qwerty";
Альтернативным объявлением может служить безразмерная инициализация:
char str[ ] = "qwerty";
При этом в случае определения длины строки результатом будет число 6. Размер строки не изменится, если в ней указать символ окончания строки:
char str[ ] = "qwerty\0";
Аналогично числовым массивам в языке С могут использоваться массивы строк, т.е. набор одномерных массивов символов. Например, сервер базы данных сверяет команды пользователей с массивом допустимых команд [6.2]. В качестве массива строк для этого случая будет служить двухмерный
char str[30][80];
Число 30 – это количество строк массива, а число 80 – максимальная длина каждой строки с учетом нулевого символа завершения строки.
Чтобы обратиться к отдельной строке двухмерного символьного массива, достаточно указать только левый индекс объявленного массива.
Многомерные символьные массивы образуются, как и числовые массивы:
char str[n][m]...[N];
В объявлении массива n – первая размерность, m – вторая размерность, ..., N – N -я (последняя) размерность. Значения размерностей – целые неотрицательные числа.
Одномерный массив – это список связанных однотипных переменных.
Общая форма записи одномерного массива [6.2]:
тип имя_массива[размер];
В приведенной записи элемент тип объявляет базовый тип массива. Количество элементов, которые будут храниться в массиве с именем имя_массива, определяется элементом размер.
В языке С
Доступ к отдельному элементу массива осуществляется с помощью индекса. Индекс описывает позицию элемента внутри массива.
Все массивы занимают смежные ячейки памяти, т.е. элементы массива в памяти расположены последовательно друг за другом. Ячейка памяти с наименьшим адресом относится к первому элементу массива, а с наибольшим – к последнему.
Для массива символов при инициализации массива необходимо резервировать место для символа окончания строки, т.е. для символа '\0'.
Строковая константа – это набор символов, заключенных в двойные апострофы, например, "hello".
В конец символьной строки не требуется обязательно добавлять нуль, компилятор языка С делает это автоматически. При инициализации символьной строки как одномерного массива необходимо предусмотреть место для нулевого символа, например:
char str[7] = "hello";
Каждая строка содержит на один символ больше, чем задано явно: все строки оканчиваются нулевым символом, имеющим значение 0.
Для одномерных массивов общий размер массива в байтах вычисляется по формуле:
всего байт = размер типа в байтах * количество элементов
Двухмерный массив представляет собой список одномерных массивов.
Общая форма записи двухмерного массива:
тип имя_массива[размер1] [размер2];
В приведенной записи размер1 означает число строк двухмерного массива, а размер2 – количество столбцов. При этом размерность размер2 определяет максимальную длину для заданного массива. Обычно размер2 задают с некоторым запасом.
В двухмерном массиве позиция любого элемента определяется двумя индексами. Индексы каждого из размеров массива начинаются с нуля.
Место хранения для всех элементов массива определяется во время компиляции. Память, выделенная для хранения массива, используется в течение всего времени существования массива.
Для двухмерных массивов заданного типа общий размер массива в байтах вычисляется по формуле:
всего байт = количество строк * количество столбцов * размер в байтах
Инициализация двухмерного символьного массива может быть определена либо посимвольно, либо построчно, например
char str[3][80] = {
{'1','2','3','4','5'},
{'x','y','z'},
{'A','B','C','D'}
};
char str2[3][80] = {
"0123456789",
"x_y_z",
"A B C D" };
Число 80 взято с запасом для возможной длины строки. Число 3 – это количество строк двухмерного массива. В обоих случаях могут быть добавлены символы окончания строки ( '\0' ). Символ '\0' не выводится на экран дисплея и не передается в файл, например, в текстовый файл. В то же время необходимо помнить, что каждая строка заканчивается нулевым символом.
Общая форма записи многомерного массива:
тип имя_массива[размер1] [размер2]... [размерN];
Индексация каждого размера начинается с нуля. Элементы многомерного массива располагаются в памяти в порядке возрастания самого правого индекса. Поэтому правый индекс будет изменяться быстрее, чем левый (левые). При этом в конце каждой строки подразумевается нулевой символ.
При обращении к многомерным массивам компьютер много времени затрачивает на вычисление адреса, так как при этом приходится учитывать значение каждого индекса [6.2]. Поэтому доступ к элементам многомерного массива происходит значительно медленнее, чем к элементам одномерного. В связи с этим использование многомерных массивов встречается значительно реже, чем одномерных или двухмерных массивов.
Для многомерных массивов общий размер многомерного массива в байтах вычисляется по формуле:
всего байт = размер1 * размер2* ... *размерN * размер типа в байтах
Очевидно, многомерные массивы способны занять большой объем памяти, а программа, которая их использует, может очень быстро столкнуться с проблемой нехватки памяти.
Для определения размера типа в байтах применяется функция sizeof(), которая возвращает целое число. Например, sizeof(char).
При инициализации многомерных массивов необходимо указать все данные (размерности) за исключением крайней слева размерности. Это нужно для того, чтобы компилятор смог определить длину подмассивов, составляющих массив, и смог выделить необходимую память.
Пример 1. Напишите программу определения длины заданных строк и их распечатки, а также определения размера строк в байтах.
Для решения поставленной задачи применим библиотечную функцию strlen() и оператор sizeof.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <string.h>
int main (void) {
char str[] = {'A','B','C','D','\0'};
char str2[] = "hello, world\0";
printf("\n\t The lines are:\n\n\t ");
puts(str);
printf("\t "); // Для отступа от края дисплея
puts(str2);
printf("\n\t The length of the 1st line (%s) is: %i\n", str, strlen(str));
printf("\t The size of the memory of the 1st line (%s) is: %i\n", str, sizeof str);
printf("\n\t The length of 2-nd line (%s) is: %i\n", str2, strlen(str2));
printf("\t Memory size 2-nd line (%s) is: %i\n", str2, sizeof str2);
printf("\n Press any key: ");
_getch();
return 0;
}
В программе функция strlen() возвращает длину строки, причем строка должна заканчиваться символом строки [6.2]. strlen() необходимо подключить заголовок <string.h>. Оператор sizeof во время компиляции программы получает размер типа или значения. Для определения размера типа оператор используется со скобками, например, sizeof(char), а для определения размера конкретного значения оператор может использоваться без скобок.
В программе использована функция puts(), которая записывает строку, адресуемую, например, параметром str, в стандартное выходное устройство – дисплей.
Результат выполнения программы показан на рис 6.1.
(рис 6.1) Определение длины и размерности строкЗадание 1
str2[] уберите символ завершения строки. Проанализируйте и объясните результат.puts() примените функции printf().Пример 2. Напишите программу копирования одной заданной строки в другую.
Для решения используем библиотечную функцию , для которой подключим заголовок <string.h>.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <string.h>
int main (void) {
char str1[] = "123456789";
char str2[] = "qwerty";
printf("\n\t The length of the line \"%s\" is: %d\n", str1, strlen(str1));
strcpy(str1, str2);
printf("\t After copying: ");
puts(str1);
printf("\n\t The length of the line \"%s\" is: %d\n", str1, strlen(str1));
printf("\n Press any key: ");
_getch();
return 0;
}
Результат выполнения программы показан на рис 6.2.
(рис 6.2) Копирование строк Задание 2
strcpy ().Пример 3. Напишите программу преобразования десятичной системы счисления в двоичную. Исходное десятичное число считайте целым без знака.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
int main (void) {
const char D[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
int newNumber[80];
long int inputNumber;
int i = 0, base = 2;
printf("\n\t Enter a positive integer: ");
scanf_s("%ld", inputNumber);
// Прямой процесс преобразования десятичного числа в двоичное
do {
newNumber[i] = inputNumber % base;
++i;
inputNumber /= base;
} while ( inputNumber != 0 );
//Запись преобразованного числа в обратном порядке
printf("\n\t Result after conversion: ");
for (--i; i >= 0; --i)
printf("%d", newNumber[i]);
printf("\n\n Press any key: ");
_getch();
return 0;
}
В программе использован квалификатор (спецификатор) типа const, который указывает компилятору, что
Результат выполнения программы показан на рис 6.3.
(рис 6.3) Перевод десятичного числа в двоичное числоЗадание 3
do–while примените цикл while.Пример 4. С помощью функции присоедините одну строку к другой с пробелом и без.
Пусть имеются строки str1 и str2. Функция присоединяет к строке str1 копию строки str2 и завершает строку str1 нулевым символом. Процесс присоединения называется конкатенацией.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <string.h>
#define N 79
int main (void) {
char str1[N+1], str2[N+1];
printf("\n\t Print 1 string of characters: ");
gets_s(str1, N); // для MS Visual Studio
printf("\t Print 2 string of characters: "); gets_s(str2, N); // для MS Visual Studio
strcat_s(str1, N, str2); // для MS Visual Studio
printf("\n\t Result after concatenation: %s\n", str1);
printf("\n Press any key: ");
_getch();
return 0; }
Возможный результат выполнения программы показан на рис 6.4.
(рис 6.4) Результат конкатенации двух строкЗадание 4
strcat (). Предусмотрите пробел между именем и фамилией.Пример 5. Для заданного двухмерного символьного массива сравните длину каждой строки друг с другом и вывести результат сравнения: 1-я строка меньше или больше 2-й строки, строки равны между собой.
Для сравнения двух строк используем библиотечную функцию , которая сравнивает в лексикографическом порядке две строки и возвращает целое значение, зависящее от результата сравнения [6.2]. Если первая строка меньше второй, то возвращается значение меньше нуля, если строки равны (по длине), то возвращается нуль, если первая строка больше второй, то возвращается число больше нуля.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <string.h> // Для функции strcmp()
#define n 2
#define m 80
int main (void)
{
int i, x;
char str[n][m] = {
"hello,",
"Hello," };
printf("\n\t Array of strings:\n");
for (i = 0; i < n; ++i)
printf("\t %d) %s\n\t (Length: %d)\n", i+1, str[i], strlen(str[i]));
printf("\n\t Comparision of lines: ");
for (i = 0; i < (n - 1); ++i)
{x = strcmp(str[i], str[i+1]);
printf("\n\t Return the function of \"strcmp()\": %d", x);
if (x == 0)
printf("\n Line %d is equal to %d?nd line.", i+1, i+2);
else if (x > 0)
printf("\n Line %d is not equal to %d?nd line.", i+1, i+2);
else if (x < 0)
printf("\n Line %d is not equal to %d-nd line.", i+1, i+2);
}
printf("\n\n Press any key: ");
_getch();
return 0;
}
Результат выполнения программы показан на рис 6.5.
(рис 6.5) Лексикографическое сравнение двух строк Задание 5
Пример 6. Напишите программу создания символьного трехмерного массива, когда, например, на одной странице имеются три строки и на второй странице имеются также три строки. Предусмотрите изменение регистра в выводе на экран строк, когда строчные буквы становятся прописными и наоборот.
Для перевода регистра используем библиотечные функции tolower() и toupper() с подключением библиотеки <ctype.h>.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>
#define n 3
#define m 2
#define N 79
int main (void)
{
int i, k;
// Определение и инициализация символьного массива
char str[n][m][N] = {
{"department: fet", "Specialization: acouY"},
{"Course: 1st", "SURNAME: ivAnov"},
{"Group: 141", "nAmE: Peter"}
};
// Построчный вывод 1-й страницы
printf("\n\t 1?st page:\n");
for (i = 0; i < n; ++i){
printf("\t");
printf("%s\n", str[i]);
}
// Посимвольный вывод 2-й страницы
printf("\n\t 2?nd page:\n");
for (i = 0; i < n; ++i) {
printf("\t");
for (k = 0; k < N; ++k)
printf("%c", toupper(str[i][m-1][k])); // или tolower()
}
printf("\n\n Press any key: ");
_getch();
return 0;
}
В программе используется трехмерный массив размера 3 $$\times$$ 2 $$\times$$ 80. Это означает, что прямоугольная таблица (массив) данных размера 3 $$\times$$ 80 как бы скрепляется 2 раза, например, по заданному числу страниц. Следует обратить внимание на вывод страниц. В первом случае используется построчный вывод со спецификатором %s, а во втором – посимвольный вывод со спецификатором %c. Кроме того, в первом случае к заданному массиву обращение происходит только по одной размерности, а во втором – используются все три размерности массива. Третий размер – число 80 – взят для того, чтобы строки умещались на всей ширине дисплея.
Результат выполнения программы показан на рис 6.6.
(рис 6.6) Вывод страничных данных трехмерного массиваЗадание 6
tolower() для перевода в строчные буквы.Пример 7. В символьной строке находятся слова и два числа, разделенные пробелами или запятыми. Выделите из строки слова и числа, разместите их в отдельных массивах. При этом считанные числа и слова разместите в дополнительных символьных массивах. Выведите значения сформированных символьных массивов. Произведите преобразование строковых (символьных) чисел к числам с плавающей точкой (тип double ). Если после десятичной точки находится нуль (или нули), то число определите как целое, в противном случае – как число с плавающей точкой, т.е. типа double.
Для решения примера используем библиотечные функции isalpfa() для определения буквы во входном потоке (с подключением библиотеки ctype.h ), isspace() – для определения пробелов во входном потоке (с подключением библиотеки ctype.h ), isdigit() – для определения цифры во входном потоке (с подключением библиотеки ctype.h ), atof() – для преобразования строки чисел в число с плавающей точкой (с подключением библиотеки stdlib.h ), atoi() – для преобразования строки чисел в целое число (с подключением библиотеки stdlib.h ), modf() – для выделения целой и дробной части числа (с подключением библиотеки math.h ), strlen() – для определения длины строки (с подключением библиотеки string.h ).
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#define N 79
int main (void) {
double r = 0.0, b3, b4;
int i, j, k, m, n, A[N], n2, n3, n4;
char str[N], str2[N], str3[N], str4[N];
// Множественная инициализация
i = j = k = m = 0;
// Обнуление символьных массивов
for (n2 = 0; n2 < N; ++n2)
str2[n2] = 0;
for (n3 = 0; n3 < N; ++n3)
str3[n3] = 0;
for (n4 = 0; n4 < N; ++n4)
str4[n4] = 0;
printf("\n\t Print line with 2-nd numbers:\n\t ");
gets_s(str, sizeof(str)/sizeof(str[0]));
printf("\n\t The line is:\n");
printf("\t %s\n", str);
while (str[i] != '\0') {
if ( isalpha(str[i]) || isspace(str[i]) )
str2[j++] = str[i];
else if (isdigit(str[i]) || str[i] == '.')
A[k++] = i; // массив индексов цифр потока
else
str2[j++] = str[i];
++i; }
printf("\n\t A string of words and symbols:\n\t"); puts(str2);
if (k > 0)
{
n = 0;
for (i = 0; i < k; ++i){
if (A[i + 1] - A[i] == 1 )
str3[n++] = str[A[i]];
else if (A[i+1] - A[i] > 1)
{m = A[i+1]; str3[n++] = str[A[i]]; break;}
}
}
printf("\n");
if (n > 0) {
r = modf(atof(str3), b3);
if (!r) // если не нуль
printf("\t The number is an integer: %d", atoi(str3));
else
printf("\t The number is real (double): %lf\n", atof(str3));
}
if (m > 0 ) {
j = 0;
for (i = m; i <= A[k - 1]; ++i)
str4[j++] = str[i];
r = modf(atof(str4), b4);
if (!r) // если не нуль
printf("\t The number is an integer: %d", atoi(str4));
else
printf("\t The number is real (double): %lf\n", atof(str4));
}
printf("\n\n Press any key: ");
_getch();
return 0;
}
В программе функция modf() возвращает величину дробной части числа (переменная r ) и целой части (от переменных b3, b4 взяты их адреса, т.е. b3, b4 ). Анализ массива с индексами цифр исходного символьного массива дает возможность выделить индексацию двух чисел входного потока. Функция gets_s() автоматически добавляет '\0', поэтому при объявлении размерности символьного массива следует предусмотреть одно место для '\0'. Для переносимости программ размерность массива в функции gets_s() определена с помощью функции sizeof().
Возможный результат выполнения программы показан на рис 6.7.
(рис 6.7) Выделение чисел из строки Задание 7
while сделайте короче.double примените тип float. Проверьте работоспособность программы.break примените goto. Проверьте работоспособность программы.Пример 8. Напишите программу, в которой генерируется строка символов заданного размера (более трех) и для которой определяется подстрока из трех символов, вводимой пользователем. В случае, когда подстрока не обнаружена, предусмотреть генерирование случайной строки поиска 1000 раз, и программа должна искать подстроку до первого совпадения.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
int main (void) {
int i, j, k, n,
N = 1000,
numA, numZ,
in,
ch_box[3];
char str[16],
str2[4];
srand((unsigned)time(NULL));
numA = (int)'a'; // числовой код латинской буквы а
numZ = (int)'z'; // числовой код латинской буквы z
printf("\n Enter a string of 3 letters: ");
in = scanf_s("%s", str2, sizeof(str2));
if ( in == 0 )
{
printf("\n Error input. Print any key: ");
_getch();
exit(1);
}
printf("\n\t substring is \"%s\"\n", str2);
for (n = 0; n < N; n++) {
for (i = 0; i < 15; i++)
str[i] = numA + rand() % (numZ - numA) + 1;
str[i] = '\0';
k = 0;
for (i = 0; i < 13; i++)
if (str2[0] == str[i] str2[1] == str[i+1] \
str2[2] == str[i+2])
{
ch_box[0] = i; ch_box[1] = i+1; ch_box[2] = i+2;
k++;
break; }
if (k > 0)
break;
}
if (k == 0)
printf("\n\t \"%s\" not found", str2);
else
printf("\n Substring \"%s\" found at positions %d, %d, %d", \
str2, ch_box[0]+1, ch_box[1]+1, ch_box[2]+1);
puts("\n");
for (k = 0; k < 15; k++)
printf(" %3d)", k+1);
puts("");
for (j = 0; j < 15; j++)
printf(" %3c ", str[j]);
printf("\n\n ... Press any key: ");
_getch();
return 0;
}
букв. Интервал чисел определяется между кодом буквы 'a' и кодом буквы 'z'.
Возможный положительный результат выполнения программы показан на рис 6.8.
(рис 6.8) Пример определения подстроки в строкеЗадание 8
goto.ctype.h и string.h?strcmp ()?В языке программирования С заложены средства для задания последовательностей упорядоченных данных [6.1]. Такие последовательности называются массивами. В массивах должны быть упорядочены данные одного и того же типа. В данной лабораторной работе будут рассматриваться массивы символов, которые определятся типом char. Одномерный массив наиболее часто применяется в виде строки символов. Строка – это одномерный '\0'. При объявлении массива символов,
предназначенного для хранения строки, необходимо отвести одно место для нуля, т.е. для символа окончания строки '\0'. Например, если дана строка , в которой 6 символов, каждый из которых занимает в памяти 1 байт, то при инициализации такой строки необходимо отвести 1 байт для нулевого
символа. Поэтому следует сделать объявление строки для семи символов:
char str[7] = "qwerty";
Альтернативным объявлением может служить безразмерная инициализация:
char str[ ] = "qwerty";
При этом в случае определения длины строки результатом будет число 6. Размер строки не изменится, если в ней указать символ окончания строки:
char str[ ] = "qwerty\0";
Аналогично числовым массивам в языке С могут использоваться массивы строк, т.е. набор одномерных массивов символов. Например, сервер базы данных сверяет команды пользователей с массивом допустимых команд [6.2]. В качестве массива строк для этого случая будет служить двухмерный
char str[30][80];
Число 30 – это количество строк массива, а число 80 – максимальная длина каждой строки с учетом нулевого символа завершения строки.
Чтобы обратиться к отдельной строке двухмерного символьного массива, достаточно указать только левый индекс объявленного массива.
Многомерные символьные массивы образуются, как и числовые массивы:
char str[n][m]...[N];
В объявлении массива n – первая размерность, m – вторая размерность, ..., N – N -я (последняя) размерность. Значения размерностей – целые неотрицательные числа.
Одномерный массив – это список связанных однотипных переменных.
Общая форма записи одномерного массива [6.2]:
тип имя_массива[размер];
В приведенной записи элемент тип объявляет базовый тип массива. Количество элементов, которые будут храниться в массиве с именем имя_массива, определяется элементом размер.
В языке С
Доступ к отдельному элементу массива осуществляется с помощью индекса. Индекс описывает позицию элемента внутри массива.
Все массивы занимают смежные ячейки памяти, т.е. элементы массива в памяти расположены последовательно друг за другом. Ячейка памяти с наименьшим адресом относится к первому элементу массива, а с наибольшим – к последнему.
Для массива символов при инициализации массива необходимо резервировать место для символа окончания строки, т.е. для символа '\0'.
Строковая константа – это набор символов, заключенных в двойные апострофы, например, "hello".
В конец символьной строки не требуется обязательно добавлять нуль, компилятор языка С делает это автоматически. При инициализации символьной строки как одномерного массива необходимо предусмотреть место для нулевого символа, например:
char str[7] = "hello";
Каждая строка содержит на один символ больше, чем задано явно: все строки оканчиваются нулевым символом, имеющим значение 0.
Для одномерных массивов общий размер массива в байтах вычисляется по формуле:
всего байт = размер типа в байтах * количество элементов
Двухмерный массив представляет собой список одномерных массивов.
Общая форма записи двухмерного массива:
тип имя_массива[размер1] [размер2];
В приведенной записи размер1 означает число строк двухмерного массива, а размер2 – количество столбцов. При этом размерность размер2 определяет максимальную длину для заданного массива. Обычно размер2 задают с некоторым запасом.
В двухмерном массиве позиция любого элемента определяется двумя индексами. Индексы каждого из размеров массива начинаются с нуля.
Место хранения для всех элементов массива определяется во время компиляции. Память, выделенная для хранения массива, используется в течение всего времени существования массива.
Для двухмерных массивов заданного типа общий размер массива в байтах вычисляется по формуле:
всего байт = количество строк * количество столбцов * размер в байтах
Инициализация двухмерного символьного массива может быть определена либо посимвольно, либо построчно, например
char str[3][80] = {
{'1','2','3','4','5'},
{'x','y','z'},
{'A','B','C','D'}
};
char str2[3][80] = {
"0123456789",
"x_y_z",
"A B C D" };
Число 80 взято с запасом для возможной длины строки. Число 3 – это количество строк двухмерного массива. В обоих случаях могут быть добавлены символы окончания строки ( '\0' ). Символ '\0' не выводится на экран дисплея и не передается в файл, например, в текстовый файл. В то же время необходимо помнить, что каждая строка заканчивается нулевым символом.
Общая форма записи многомерного массива:
тип имя_массива[размер1] [размер2]... [размерN];
Индексация каждого размера начинается с нуля. Элементы многомерного массива располагаются в памяти в порядке возрастания самого правого индекса. Поэтому правый индекс будет изменяться быстрее, чем левый (левые). При этом в конце каждой строки подразумевается нулевой символ.
При обращении к многомерным массивам компьютер много времени затрачивает на вычисление адреса, так как при этом приходится учитывать значение каждого индекса [6.2]. Поэтому доступ к элементам многомерного массива происходит значительно медленнее, чем к элементам одномерного. В связи с этим использование многомерных массивов встречается значительно реже, чем одномерных или двухмерных массивов.
Для многомерных массивов общий размер многомерного массива в байтах вычисляется по формуле:
всего байт = размер1 * размер2* ... *размерN * размер типа в байтах
Очевидно, многомерные массивы способны занять большой объем памяти, а программа, которая их использует, может очень быстро столкнуться с проблемой нехватки памяти.
Для определения размера типа в байтах применяется функция sizeof(), которая возвращает целое число. Например, sizeof(char).
При инициализации многомерных массивов необходимо указать все данные (размерности) за исключением крайней слева размерности. Это нужно для того, чтобы компилятор смог определить длину подмассивов, составляющих массив, и смог выделить необходимую память.
Пример 1. Напишите программу определения длины заданных строк и их распечатки, а также определения размера строк в байтах.
Для решения поставленной задачи применим библиотечную функцию strlen() и оператор sizeof.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <string.h>
int main (void) {
char str[] = {'A','B','C','D','\0'};
char str2[] = "hello, world\0";
printf("\n\t The lines are:\n\n\t ");
puts(str);
printf("\t "); // Для отступа от края дисплея
puts(str2);
printf("\n\t The length of the 1st line (%s) is: %i\n", str, strlen(str));
printf("\t The size of the memory of the 1st line (%s) is: %i\n", str, sizeof str);
printf("\n\t The length of 2-nd line (%s) is: %i\n", str2, strlen(str2));
printf("\t Memory size 2-nd line (%s) is: %i\n", str2, sizeof str2);
printf("\n Press any key: ");
_getch();
return 0;
}
В программе функция strlen() возвращает длину строки, причем строка должна заканчиваться символом строки [6.2]. strlen() необходимо подключить заголовок <string.h>. Оператор sizeof во время компиляции программы получает размер типа или значения. Для определения размера типа оператор используется со скобками, например, sizeof(char), а для определения размера конкретного значения оператор может использоваться без скобок.
В программе использована функция puts(), которая записывает строку, адресуемую, например, параметром str, в стандартное выходное устройство – дисплей.
Результат выполнения программы показан на рис 6.1.
(рис 6.1) Определение длины и размерности строкЗадание 1
str2[] уберите символ завершения строки. Проанализируйте и объясните результат.puts() примените функции printf().Пример 2. Напишите программу копирования одной заданной строки в другую.
Для решения используем библиотечную функцию , для которой подключим заголовок <string.h>.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <string.h>
int main (void) {
char str1[] = "123456789";
char str2[] = "qwerty";
printf("\n\t The length of the line \"%s\" is: %d\n", str1, strlen(str1));
strcpy(str1, str2);
printf("\t After copying: ");
puts(str1);
printf("\n\t The length of the line \"%s\" is: %d\n", str1, strlen(str1));
printf("\n Press any key: ");
_getch();
return 0;
}
Результат выполнения программы показан на рис 6.2.
(рис 6.2) Копирование строкЗадание 2
strcpy ().Пример 3. Напишите программу преобразования десятичной системы счисления в двоичную. Исходное десятичное число считайте целым без знака.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
int main (void) {
const char D[] = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
int newNumber[80];
long int inputNumber;
int i = 0, base = 2;
printf("\n\t Enter a positive integer: ");
scanf_s("%ld", inputNumber);
// Прямой процесс преобразования десятичного числа в двоичное
do {
newNumber[i] = inputNumber % base;
++i;
inputNumber /= base;
} while ( inputNumber != 0 );
//Запись преобразованного числа в обратном порядке
printf("\n\t Result after conversion: ");
for (--i; i >= 0; --i)
printf("%d", newNumber[i]);
printf("\n\n Press any key: ");
_getch();
return 0;
}
В программе использован квалификатор (спецификатор) типа const, который указывает компилятору, что
Результат выполнения программы показан на рис 6.3.
(рис 6.3) Перевод десятичного числа в двоичное числоЗадание 3
do–while примените цикл while.Пример 4. С помощью функции присоедините одну строку к другой с пробелом и без.
Пусть имеются строки str1 и str2. Функция присоединяет к строке str1 копию строки str2 и завершает строку str1 нулевым символом. Процесс присоединения называется конкатенацией.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <string.h>
#define N 79
int main (void) {
char str1[N+1], str2[N+1];
printf("\n\t Print 1 string of characters: ");
gets_s(str1, N); // для MS Visual Studio
printf("\t Print 2 string of characters: "); gets_s(str2, N); // для MS Visual Studio
strcat_s(str1, N, str2); // для MS Visual Studio
printf("\n\t Result after concatenation: %s\n", str1);
printf("\n Press any key: ");
_getch();
return 0; }
Возможный результат выполнения программы показан на рис 6.4.
(рис 6.4) Результат конкатенации двух строкЗадание 4
strcat (). Предусмотрите пробел между именем и фамилией.Пример 5. Для заданного двухмерного символьного массива сравните длину каждой строки друг с другом и вывести результат сравнения: 1-я строка меньше или больше 2-й строки, строки равны между собой.
Для сравнения двух строк используем библиотечную функцию , которая сравнивает в лексикографическом порядке две строки и возвращает целое значение, зависящее от результата сравнения [6.2]. Если первая строка меньше второй, то возвращается значение меньше нуля, если строки равны (по длине), то возвращается нуль, если первая строка больше второй, то возвращается число больше нуля.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <string.h> // Для функции strcmp()
#define n 2
#define m 80
int main (void)
{
int i, x;
char str[n][m] = {
"hello,",
"Hello," };
printf("\n\t Array of strings:\n");
for (i = 0; i < n; ++i)
printf("\t %d) %s\n\t (Length: %d)\n", i+1, str[i], strlen(str[i]));
printf("\n\t Comparision of lines: ");
for (i = 0; i < (n - 1); ++i)
{x = strcmp(str[i], str[i+1]);
printf("\n\t Return the function of \"strcmp()\": %d", x);
if (x == 0)
printf("\n Line %d is equal to %d?nd line.", i+1, i+2);
else if (x > 0)
printf("\n Line %d is not equal to %d?nd line.", i+1, i+2);
else if (x < 0)
printf("\n Line %d is not equal to %d-nd line.", i+1, i+2);
}
printf("\n\n Press any key: ");
_getch();
return 0;
}
Результат выполнения программы показан на рис 6.5.
(рис 6.5) Лексикографическое сравнение двух строкЗадание 5
Пример 6. Напишите программу создания символьного трехмерного массива, когда, например, на одной странице имеются три строки и на второй странице имеются также три строки. Предусмотрите изменение регистра в выводе на экран строк, когда строчные буквы становятся прописными и наоборот.
Для перевода регистра используем библиотечные функции tolower() и toupper() с подключением библиотеки <ctype.h>.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>
#define n 3
#define m 2
#define N 79
int main (void)
{
int i, k;
// Определение и инициализация символьного массива
char str[n][m][N] = {
{"department: fet", "Specialization: acouY"},
{"Course: 1st", "SURNAME: ivAnov"},
{"Group: 141", "nAmE: Peter"}
};
// Построчный вывод 1-й страницы
printf("\n\t 1?st page:\n");
for (i = 0; i < n; ++i){
printf("\t");
printf("%s\n", str[i]);
}
// Посимвольный вывод 2-й страницы
printf("\n\t 2?nd page:\n");
for (i = 0; i < n; ++i) {
printf("\t");
for (k = 0; k < N; ++k)
printf("%c", toupper(str[i][m-1][k])); // или tolower()
}
printf("\n\n Press any key: ");
_getch();
return 0;
}
В программе используется трехмерный массив размера 3 $$\times$$ 2 $$\times$$ 80. Это означает, что прямоугольная таблица (массив) данных размера 3 $$\times$$ 80 как бы скрепляется 2 раза, например, по заданному числу страниц. Следует обратить внимание на вывод страниц. В первом случае используется построчный вывод со спецификатором %s, а во втором – посимвольный вывод со спецификатором %c. Кроме того, в первом случае к заданному массиву обращение происходит только по одной размерности, а во втором – используются все три размерности массива. Третий размер – число 80 – взят для того, чтобы строки умещались на всей ширине дисплея.
Результат выполнения программы показан на рис 6.6.
(рис 6.6) Вывод страничных данных трехмерного массиваЗадание 6
tolower() для перевода в строчные буквы.Пример 7. В символьной строке находятся слова и два числа, разделенные пробелами или запятыми. Выделите из строки слова и числа, разместите их в отдельных массивах. При этом считанные числа и слова разместите в дополнительных символьных массивах. Выведите значения сформированных символьных массивов. Произведите преобразование строковых (символьных) чисел к числам с плавающей точкой (тип double ). Если после десятичной точки находится нуль (или нули), то число определите как целое, в противном случае – как число с плавающей точкой, т.е. типа double.
Для решения примера используем библиотечные функции isalpfa() для определения буквы во входном потоке (с подключением библиотеки ctype.h ), isspace() – для определения пробелов во входном потоке (с подключением библиотеки ctype.h ), isdigit() – для определения цифры во входном потоке (с подключением библиотеки ctype.h ), atof() – для преобразования строки чисел в число с плавающей точкой (с подключением библиотеки stdlib.h ), atoi() – для преобразования строки чисел в целое число (с подключением библиотеки stdlib.h ), modf() – для выделения целой и дробной части числа (с подключением библиотеки math.h ), strlen() – для определения длины строки (с подключением библиотеки string.h ).
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <math.h>
#define N 79
int main (void) {
double r = 0.0, b3, b4;
int i, j, k, m, n, A[N], n2, n3, n4;
char str[N], str2[N], str3[N], str4[N];
// Множественная инициализация
i = j = k = m = 0;
// Обнуление символьных массивов
for (n2 = 0; n2 < N; ++n2)
str2[n2] = 0;
for (n3 = 0; n3 < N; ++n3)
str3[n3] = 0;
for (n4 = 0; n4 < N; ++n4)
str4[n4] = 0;
printf("\n\t Print line with 2-nd numbers:\n\t ");
gets_s(str, sizeof(str)/sizeof(str[0]));
printf("\n\t The line is:\n");
printf("\t %s\n", str);
while (str[i] != '\0') {
if ( isalpha(str[i]) || isspace(str[i]) )
str2[j++] = str[i];
else if (isdigit(str[i]) || str[i] == '.')
A[k++] = i; // массив индексов цифр потока
else
str2[j++] = str[i];
++i; }
printf("\n\t A string of words and symbols:\n\t"); puts(str2);
if (k > 0)
{
n = 0;
for (i = 0; i < k; ++i){
if (A[i + 1] - A[i] == 1 )
str3[n++] = str[A[i]];
else if (A[i+1] - A[i] > 1)
{m = A[i+1]; str3[n++] = str[A[i]]; break;}
}
}
printf("\n");
if (n > 0) {
r = modf(atof(str3), b3);
if (!r) // если не нуль
printf("\t The number is an integer: %d", atoi(str3));
else
printf("\t The number is real (double): %lf\n", atof(str3));
}
if (m > 0 ) {
j = 0;
for (i = m; i <= A[k - 1]; ++i)
str4[j++] = str[i];
r = modf(atof(str4), b4);
if (!r) // если не нуль
printf("\t The number is an integer: %d", atoi(str4));
else
printf("\t The number is real (double): %lf\n", atof(str4));
}
printf("\n\n Press any key: ");
_getch();
return 0;
}
В программе функция modf() возвращает величину дробной части числа (переменная r ) и целой части (от переменных b3, b4 взяты их адреса, т.е. b3, b4 ). Анализ массива с индексами цифр исходного символьного массива дает возможность выделить индексацию двух чисел входного потока. Функция gets_s() автоматически добавляет '\0', поэтому при объявлении размерности символьного массива следует предусмотреть одно место для '\0'. Для переносимости программ размерность массива в функции gets_s() определена с помощью функции sizeof().
Возможный результат выполнения программы показан на рис 6.7.
(рис 6.7) Выделение чисел из строкиЗадание 7
while сделайте короче.double примените тип float. Проверьте работоспособность программы.break примените goto. Проверьте работоспособность программы.Пример 8. Напишите программу, в которой генерируется строка символов заданного размера (более трех) и для которой определяется подстрока из трех символов, вводимой пользователем. В случае, когда подстрока не обнаружена, предусмотреть генерирование случайной строки поиска 1000 раз, и программа должна искать подстроку до первого совпадения.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
int main (void) {
int i, j, k, n,
N = 1000,
numA, numZ,
in,
ch_box[3];
char str[16],
str2[4];
srand((unsigned)time(NULL));
numA = (int)'a'; // числовой код латинской буквы а
numZ = (int)'z'; // числовой код латинской буквы z
printf("\n Enter a string of 3 letters: ");
in = scanf_s("%s", str2, sizeof(str2));
if ( in == 0 )
{
printf("\n Error input. Print any key: ");
_getch();
exit(1);
}
printf("\n\t substring is \"%s\"\n", str2);
for (n = 0; n < N; n++) {
for (i = 0; i < 15; i++)
str[i] = numA + rand() % (numZ - numA) + 1;
str[i] = '\0';
k = 0;
for (i = 0; i < 13; i++)
if (str2[0] == str[i] str2[1] == str[i+1] \
str2[2] == str[i+2])
{
ch_box[0] = i; ch_box[1] = i+1; ch_box[2] = i+2;
k++;
break; }
if (k > 0)
break;
}
if (k == 0)
printf("\n\t \"%s\" not found", str2);
else
printf("\n Substring \"%s\" found at positions %d, %d, %d", \
str2, ch_box[0]+1, ch_box[1]+1, ch_box[2]+1);
puts("\n");
for (k = 0; k < 15; k++)
printf(" %3d)", k+1);
puts("");
for (j = 0; j < 15; j++)
printf(" %3c ", str[j]);
printf("\n\n ... Press any key: ");
_getch();
return 0;
}
букв. Интервал чисел определяется между кодом буквы 'a' и кодом буквы 'z'.
Возможный положительный результат выполнения программы показан на рис 6.8.
(рис 6.8) Пример определения подстроки в строкеЗадание 8
goto.ctype.h и string.h?strcmp ()?Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.