Лекция 3 Массивы и строки
Скачать 272.56 Kb.
|
Лекция 3 Массивы и строкиМассивМассив – это группа однотипных элементов, имеющих общее имя и расположенных в памяти рядом.Особенности:
На рисунке показана структура целочисленного одномерного массива a. Размер этого массива — 16 ячеек:Int a[16];а[0] а[1] а[2] а[3] а[4] а[5] а[6] а[7] а[8] а[9] а[10] а[11] а[12] а[13] а[14] а[15]Заметьте, что максимальный индекс одномерного массива a равен 15, но размер массива 16 ячеек. Нумерация элементов массива в Си начинается с НУЛЯ !Примеры:string ListStudent [30]; //список студентов в группеint flat [180]; //квартиры в домеfloat x[10], y[10]; //координаты точек на плоскостиchar Name [10] = {‘v’, ‘a’, ‘l’, ‘e’, ‘n’, ‘t’, ‘i’, ‘n’}; //имя
Инициализация массивов
string days[7]={“Sunday”, “Monday”, “Tuesday”,“Wednesday”, “Thursday”, “Friday”, “Saturday”};Если начальные значения не заданы, в ячейках находится «мусор»!Следующая инициализация выделит память под 5 целых чисел,а начальных значений задано только 3. В этом случае четвёртыйи пятый элемент будут инициализированы (по умолчанию) значением 0.int testScore[5]= {74, 87, 91};Инициализация следующего вида не будет компилироваться:float milles[4]= {74.4, 87.2, , 91.7};const int N=15;string ListStudent [N];Что неправильно? int N = 10; float A[N]; const int int X[4.5]; int A[10]; A[10] = 0; float X[5]; int n = 1; X[n-2] = 4.5; X[n+8] = 12.; выход за границы массива (стираются данные в памяти) int X[4]; X[2] = 4.5; дробная часть отбрасывается (ошибки нет) float B[2] = { 1., 3.8, 5.5 }; int A[2] = { 1, 3.8 }; float Массивы Объявление: Ввод значений элементов массива с клавиатуры: Поэлементные операции: Вывод значений элементов массива на экран: const int N = 5; int A[N], i; printf("Введите 5 элементов массива:\n"); for( i=0; i < N; i++ ) { printf ("A[%d] = ", i ); scanf ("%d", & A[i] ); } A[0] = A[1] = A[2] = A[3] = A[4] = 5 12 34 56 13 for( i=0; i < N; i++ ) A[i] = A[i]*2; printf("Результат:\n"); for( i=0; i < N; i++ ) printf("%4d", A[i]); Результат: 10 24 68 112 26 Случайные числа Случайное целое число X в интервале от 1 до 20 #include #include #include int main() { srand((unsigned)time(NULL)); int x=rand()%20+1; // генерируем числа в диапазоне от 1 до 20 printf("%i",x); return 0; } void srand(unsigned int) - функция установки начального значения генератора псевдослучайных чисел. unsigned - приведение аргумента к типу беззнакового целого time - функция выдачи текущего времени NULL - нулевой указатель, передаваемый функции time для выдачи текущего времени только как результата. Заполнение массива случайными числами #include #include #include main() { srand((unsigned)time(NULL)); const int N = 10; int A[N], i; printf("Исходный массив:\n"); for (i = 0; i < N; i++ ) { A[i] = random(100) + 50; printf("%4d", A[i]); } ... } int random(int N)-функция выдает случайное число от 0 до N-1 { return rand() % N; } Какой интервал? ? ПРИМЕР : Реверс массива Задача: переставить элементы массива в обратном порядке (выполнить инверсию). Алгоритм: поменять местами A[0] и A[N-1], A[1] и A[N-2], … Псевдокод:
for ( i = 0; i < N/2; i++ ) // поменять местами A[i] и A[N-1-i] сумма индексов N-1 ПРИМЕР : Циклический сдвиг элементов массива Задача: сдвинуть элементы массива влево на 1 ячейку, первый элемент становится на место последнего. Алгоритм: A[0]=A[1]; A[1]=A[2];… A[N-2]=A[N-1]; Цикл: for ( i = 0; i < N-1; i ++) A[i] = A[i+1]; Что неверно? ? почему не N? main() { const int N = 10; int A[N], i, c; // заполнить массив // вывести исходный массив c = A[0]; for ( i = 0; i < N-1; i ++) A[i] = A[i+1]; A[N-1] = c; // вывести полученный массив } Двумерный массивВ двумерном массиве, кроме количества элементов массива, есть такие характеристики как, количество строк и количество столбцов двумерного массива.В объявлении двумерного массива нужно указать:
// пример объявление двумерного массива:int a[5][3];// инициализация двумерного массива:int a[5][3] = { {4, 7, 8}, {9, 66, -1}, {5, -5, 0}, {3, -3, 30}, {1, 1, 1} };Матрицы Задача: запомнить положение фигур на шахматной доске. 1 2 3 4 5 6
c6 A[5][2] Двумерный массив (Матрица) Объявление: const int N = 3, M = 4; int A[N][M]; float a[2][2] = {{3.2, 4.3}, {1.1, 2.2}}; char sym[2][2] = { 'a', 'b', 'c', 'd' }; Ввод с клавиатуры: for ( i = 0; i < N; i ++ ) for ( j = 0; j < M; j ++ ) { printf ( "A[%d][%d]=", i, j); scanf ( "%d", &A[i][j] ); } Если переставить циклы? ? A[0][0]= 25 A[0][1]= 14 A[0][2]= 14 ... A[2][3]= 54 i j for ( j = 0; j < M; j ++ ) for ( i = 0; i < N; i ++ ) { Двумерный массив (Матрица) Заполнение случайными числами for ( i = 0; i < N; i ++ ) for ( j = 0; j < M; j ++ ) A[i][j] = random(25)- 10; Какой интервал? ? цикл по строкам цикл по столбцам Вывод на экран for ( i = 0; i < N; i ++ ) { for ( j = 0; j < M; j ++ ) printf("%5d", A[i,j]); printf("\n"); } перейти на новую строку for ( j = 0; j < M; j ++ ) printf("%5d", A[i][j]); вывод строки
Если переставить циклы? ? в той же строке Пример: Нахождение суммы элементов матрицы main() { const int N = 3, M = 4; int A[N][M], i, j, S = 0; ... // заполнение матрицы и вывод на экран for ( i = 0; i < N; i ++ ) for ( j = 0; j < M; j ++ ) S += A[i][j]; printf("Сумма элементов матрицы S=%d", S); } Пример: Вычисление коэффициентов Бинома Ньютона называются биномиальными коэффициентами. Задание Используя два описанных ниже метода, найти значения коэффициентов разложения многочлена (a + b)n . Входные данные С клавиатуры вводится число n — значениемаксимальной степени, для которой нужно посчитать коэффициенты бинома Ньютона. Выходные данные На экран выводятся n + 1 строк. Каждая i – я строка (0 i n ) содержит целые числа, записанные через пробел, — посчитанные биномиальные коэффициенты Cik (0 k i). называется биномом Ньютона, а коэффициенты (0 m n) Определение Многочлен вида Выпишем коэффициенты разложения в строчку, начиная с n = 0, 1 и так далее следующим образом: n | Коэффициенты 0 | 1 1 | 1 1 2 | 1 2 1 3 | 1 3 3 1 4 | 1 4 6 4 1 5 | 1 5 10 10 5 1 6 | 1 6 15 20 15 6 1 7 |1 7 21 35 35 21 7 ... |........................................... Для каждого коэффициента можно записать следующие рекуррентные соотношения: Треугольник Паскаля где выражение n! (n-факториал) обозначает произведение всех натуральных чисел от 1 до n. Исходя из соотношений: 0! = 1, n!= n*(n − 1)! (n > 0) можно написать рекурсивную функцию вычисления факториала, а затем использовать ее для вычисления биномиальных коэффициентов по приведенной выше формуле. Биномиальные коэффициенты также можно вычислить по следующей формуле (число сочетаний из n по k): int faсt(int n) { if (!n) return 1; return (n * faсt(n-1)); } Определение числа сочетаний с помощью рекурсии Чем плох массив символов? char A[4] = { 'A', '3', '[', 'Ж'}; char B[10]; Это массивы символов: Для массива:
Что нужно:
Символьные строки
рабочая часть s[0] s[1] s[2] s[3] char s[80]; признак окончания строки: символ с кодом 0 Символ '\0' имеет код 0 символ '0' имеет код 48 ! Символьная строка – это последовательность символов, заключенная в двойные кавычки, которая заканчивается символом '\0'. Строка символов хранится в памяти ЭВМ как массив символов. Значение символьной строки - это адрес ее первого символа. При трансляции программы компилятор разместит все символьные строки в памяти, а в программу вместо них подставит соответствующие адреса (т.е. значения символьных строк!). Объявление символьных строк Объявить строку = выделить ей место в памяти и присвоить имя. char s[80]; char s1[80] = "abc"; char qqq[] = "Вася"; выделяется 80 байт, в строке – «мусор» (если она глобальная, то нули '\0‘) выделяется 80 байт, занято 4 байта (с учетом '\0') выделяется 5 байт (с учетом '\0')
! Ввод и вывод символьных строк Задача: ввести слово с клавиатуры и заменить все буквы «а» на буквы «б». main() { char q[80]; int i; printf("Введите строку\n"); scanf( "%s", q); i = 0; while ( q[i] != '\0' ) { if ( q[i] == 'а' ) q[i] = 'б'; i ++; } printf ( "Результат: %s ", q ); } %s не надо ставить &: q &q[0] %s – формат для ввода и вывода символьных строк (выводится только часть до '\0' "%s" пока не дошли до конца строки переход к следующему символу начали с q[0] Ввод одного слова: Ввод строки с пробелами: char q[80]; printf ("Введите текст:\n"); scanf ( "%s", q ); printf ("Введено:\n%s", q ); Ввод символьных строк Введите текст: Вася пошел гулять Введено: Вася char q[80]; printf("Введите текст:\n"); gets ( q ); printf("Введено:\n%s", q ); Введите текст: Вася пошел гулять Введено: Вася пошел гулять Универсальный способ: Только для одной строки: printf ( "Результат: %s", q ); Вывод символьных строк puts ( q );
printf ( "%s\n", q ); Функции для работы со строками Длина строки: strlen (string length) Подключение библиотеки: #include char q[80] = "qwerty"; int n; n = strlen ( q ); n = 6 При определении длины символ '\0' не учитывается! ! Сравнение строк char q1[80], q2[80]; int n; gets ( q1 ); gets ( q2 ); n = strcmp ( q1, q2 ); strcmp (string comparison): Функция вычисляет разность между кодами первых двух отличающихся символов! ! Пример решения задачи Задача: ввести строку и определить, сколько в ней слов. Программа должна работать только при вводе правильного пароля. Идея решения:
Проверка пароля #include main() { char secret[] = "123", pass[20]; printf ( "Введите пароль\n" ); gets ( pass ); if ( strcmp ( pass, secret ) != 0 ) { printf ( "Пароль неверный" ); getch (); return 1; } ... } если пароль неверный... сообщить об ошибке и выйти из программы аварийное завершение, код ошибки 1 Основная часть программы #include #include main() { char q[80]; int i, len, count = 0; ... // проверка пароля printf ("Введите предложение\n"); gets ( q ); len = strlen( q ); if ( q[0] != ' ') count++; for ( i = 0; i < len - 1; i ++ ) if ( q[i] == ' ' && q[i+1] != ' ' ) count ++; printf ( "Найдено %d слов", count ); } особый случай если нашли пробел, а за ним не пробел… предыдущий слайд Копирование строк strcpy (string copy) char q1[10] = "qwerty", q2[10] = "01234"; strcpy ( q1, q2 ); куда откуда Старое значение q1 стирается! ! копирование «хвоста» строки char q1[10] = "qwerty", q2[10] = "01234"; strcpy ( q1, q2+2 );
q2 q1 q2 = &q2[0] q2+2 = &q2[2]
Копирование строк копирование в середину строки char q1[10] = "qwerty", q2[10] = "01234"; strcpy ( q1+2, q2 );
q2 q1 q1+2 = &q1[2]
char q1[10] = "qwerty", q2[10] = "01234"; strcpy ( q1+2, q2+3 );
q2 q1
q2+3 = &q2[3] q1+2 = &q1[2] Копирование строк strncpy – копирование нескольких символов char q1[10] = "qwerty", q2[10] = "01234"; strncpy ( q1+2, q2, 2 );
q2 q1 q1+2 = &q1[2]
Функция strncpy не добавляет символ '\0' в конце строки! ! Копирование строк копирование строки-константы char q1[10] = "qwerty"; strcpy ( q1+1, "ABCD");
q1
char q1[10] = "qwerty"; strcpy ( "ABCD", q1+2 ); Первым параметром может быть константа! ! НЕ Копирование строк копирование внутри одной строки char q[10] = "012345"; strcpy ( q, q+2 );
q
char q[10] = "012345"; strcpy ( q+2, q );
q
Зацикливание! Объединение строк strcat (string concatenation) = копирование второй строки в конец первой char q1[10] = "qwe", q2[10] = "0123"; strcat ( q1, q2 );
q2 q1
char q1[10] = "qwe", q2[10] = "0123"; strcat ( q1, q2+2 );
q2 q1
что-то другое Проблемы при копировании строк Транслятор не сообщает об этих ошибках! ! char q1[] = "qwer", q2[10] = "01234"; strcpy ( q1+2, q2 );
q2 q1
char q[10] = "01234"; strcpy ( q+2, q ); |