Скачать презентацию Тема Указатели и массивы продолжение Лекция 04 10 Скачать презентацию Тема Указатели и массивы продолжение Лекция 04 10

Лекция-10-Иванченко.ppt

  • Количество слайдов: 15

Тема Указатели и массивы (продолжение) Лекция 04. 10. 11 г. 1 Тема Указатели и массивы (продолжение) Лекция 04. 10. 11 г. 1

Символьные указатели Язык С не имеет отдельного типа данных для работы со строками символов Символьные указатели Язык С не имеет отдельного типа данных для работы со строками символов и они представляются массивами символов char[]. Например, строковая константа “I am a string” будет представлена в памяти символьным массивом из 14 элементов (13 символов+’’). Рассмотрим два способа определения объектов программы, с помощью которых можно работать со строками: char amessage[] = “I am a string” ; /* массив */ char *pmessage = “I am a string” ; /* указатель */ В первом случае amessage – это массив, занимающий 14 байтов памяти, заполненных символами из строковой константы и каждый символ в этом массиве можно изменять. При этом переменная amessage всегда будет указывать на один и тот же участок памяти и её значение изменить нельзя. Во втором случае pmessage – указатель размером 4 байта. С его помощью можно также получить доступ к любому символу строковой константы, но изменять символы нельзя. Кроме того, переменная pmessage в дальнейшем может получить другое значение, например, в результате присваивания: pmessage = “I am another string” ; Лекция 04. 10. 11 г. 2

Обработка строк При выполнении различных преобразований над строками необходимо очень внимательно подходить к учёту Обработка строк При выполнении различных преобразований над строками необходимо очень внимательно подходить к учёту разницы между представлением строк массивами и указателями. Рассмотрим известную задачу «обмен значениями» для двух строк. #include #include #define MAXLEN 200 void strcpy_(char* s, char* t) { while(*s++ = *t++); } void swaps(char* a, char *b) { char c[MAXLEN]; strcpy_(c, a); strcpy_(a, b); strcpy_(b, c); } main() { char s 1[MAXLEN] = "first"; char s 2[MAXLEN] = "second"; printf("%s, %sn", s 1, s 2); swaps(s 1, s 2); printf("%s, %sn", s 1, s 2); system("PAUSE"); return 0; } Лекция 04. 10. 11 г. Ok! 3

Обработка строк Модифицируем программу – в основной программе будем использовать указатели: #include <stdio. h> Обработка строк Модифицируем программу – в основной программе будем использовать указатели: #include #include #define MAXLEN 200 void strcpy_(char* s, char* t) { while(*s++ = *t++); } void swaps(char* a, char *b) { char c[MAXLEN]; strcpy_(c, a); strcpy_(a, b); strcpy_(b, c); } main() { char *s 1 = "first"; char *s 2 = "second"; printf("%s, %sn", s 1, s 2); swaps(s 1, s 2); printf("%s, %sn", s 1, s 2); system("PAUSE"); return 0; } Лекция 04. 10. 11 г. Err! 4

Обработка строк Основная причина неудачи предыдущей программы – попытка изменить символы в строковой константе Обработка строк Основная причина неудачи предыдущей программы – попытка изменить символы в строковой константе (это невозможно!). Однако в этом случае есть более лёгкое решение – строки оставить на месте, а поменять значения указателей: #include #include #define MAXLEN 200 void swaps(char* a, char *b) { char *c = a; a = b; b = c; } main() { char *s 1 = "first"; char *s 2 = "second"; printf("%s, %sn", s 1, s 2); swaps(s 1, s 2); printf("%s, %sn", s 1, s 2); system("PAUSE"); return 0; } Лекция 04. 10. 11 г. Err! 5

Обработка строк В этот раз неудача объясняется тем, что значения указателей s 1 и Обработка строк В этот раз неудача объясняется тем, что значения указателей s 1 и s 2 в функции изменять нельзя по той же причине, которая была рассмотрена ранее в теме «два способа передачи аргументов в функцию» . Выход – использование адресов указателей s 1 и s 2 (т. е. указателей на указатели): #include #include void swaps(char** a, char** b) { char *c = *a; *a = *b; *b = c; } main() { char *s 1 = "first"; char *s 2 = "second"; printf("%s, %sn", s 1, s 2); swaps(&s 1, &s 2); printf("%s, %sn", s 1, s 2); system("PAUSE"); return 0; } Лекция 04. 10. 11 г. Ok! 6

Иллюстрация к программе main #include <stdio. h> #include <stdlib. h> void swaps(char** a, char** Иллюстрация к программе main #include #include void swaps(char** a, char** b) { char *c = *a; *a = *b; *b = c; } main() { char *s 1 = "first"; char *s 2 = "second"; printf("%s, %sn", s 1, s 2); swaps(&s 1, &s 2); printf("%s, %sn", s 1, s 2); system("PAUSE"); return 0; } s 1: addr 1 first s 2: addr 2 second swaps a: &s 1 b: &s 2 после вызова swaps s 1: first s 2: Лекция 04. 10. 11 г. addr 2 addr 1 second 7

Массивы указателей Так как указатели являются обычными переменными, их можно хранить в массиве. Создадим Массивы указателей Так как указатели являются обычными переменными, их можно хранить в массиве. Создадим объект «массив строк» , проинициализируем его и выполним перестановку некоторых элементов этого массива: #include #include void swaps(char** a, char** b) { char *c = *a; *a = *b; *b = c; } main() { char* arrs[] = {"first", "second", "third", "fourth", "fifth"}; int i, n = sizeof(arrs)/sizeof(*arrs); for(i = 0; i < n; i++) printf("%d: %sn", i+1, arrs[i]); swaps(&arrs[0], &arrs[2]); swaps(&arrs[1], &arrs[4]); printf("----n"); for(i = 0; i < n; i++) printf("%d: %sn", i+1, arrs[i]); system("PAUSE"); return 0; } Лекция 04. 10. 11 г. 8

Иллюстрация к программе arrs → arrs[0] first arrs[1] arrs → arrs[0] first second arrs[1] Иллюстрация к программе arrs → arrs[0] first arrs[1] arrs → arrs[0] first second arrs[1] second arrs[2] third arrs[3] fourth arrs[4] fifth Лекция 04. 10. 11 г. 9

Многомерные массивы Синтаксис языка С допускает, чтобы при определении массива его элементами были массивы Многомерные массивы Синтаксис языка С допускает, чтобы при определении массива его элементами были массивы (одинакового размера!). В этом случае приходим к понятию многомерного прямоугольного массива. Например, популярный математический объект «матрица» может быть представлен двумерным массивом: #include #include main() { int matr[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; int i, n = 3, j, m = 3; for(i = 0; i < n; i++) { for(j = 0; j < m; j++) printf("%4 d", matr[i][j]); printf("n"); } system("PAUSE"); return 0; } matr – массив из 3 -х элементов, каждый из которых является массивом из 3 -х элементов Лекция 04. 10. 11 г. 10

Многомерные массивы Можно задать двумерный массив неопределенного (по первому измерению!) размера : #include <stdio. Многомерные массивы Можно задать двумерный массив неопределенного (по первому измерению!) размера : #include #include main() { int matr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}}; int i, n = sizeof(matr)/sizeof(*matr); int j, m = 3; for(i = 0; i < n; i++) { for(j = 0; j < m; j++) printf("%4 d", matr[i][j]); printf("n"); } system("PAUSE"); return 0; } Лекция 04. 10. 11 г. 11

Многомерные массивы и указатели По аналогии с одномерными массивами можно предположить, что справедливо соотношение: Многомерные массивы и указатели По аналогии с одномерными массивами можно предположить, что справедливо соотношение: x[i][j] эквивалентно *(*(x+i)+j). Проверим это: #include #include main() { int matr[][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12}}; int i, n = sizeof(matr)/sizeof(*matr); int j, m = 3; for(i = 0; i < n; i++) { for(j = 0; j < m; j++) printf("%4 d", matr[i][j]); printf("n"); } printf("[1, 1]->%4 dn", *(*(matr+1)+1)); printf("[3, 2]->%4 dn", *(*(matr+3)+2)); system("PAUSE"); return 0; } Лекция 04. 10. 11 г. 12

Многомерные массивы нерегулярной структуры С помощью указателей можно сконструировать необычные, «зубчатые» массивы, в которых Многомерные массивы нерегулярной структуры С помощью указателей можно сконструировать необычные, «зубчатые» массивы, в которых каждая строка может иметь свой размер, например так: 1 2 5 3 4 3 8 5 7 9 #include #include main() { int m 1[] = {1, 2}; int m 2[] = {5, 3, 4, 7, 9, 2}; int m 3[] = {3, 8, 5}; int *matr[] = {m 1, m 2, m 3}; printf("[1, 1]->%4 dn", *(*(matr+1)+1)); printf("[1, 5]->%4 dn", *(*(matr+1)+5)); printf("[2, 2]->%4 dn", *(*(matr+2)+2)); printf("[1, 1]->%4 dn", matr[1][1]); printf("[1, 5]->%4 dn", matr[1][5]); printf("[2, 2]->%4 dn", matr[2][2]); system("PAUSE"); return 0; } Лекция 04. 10. 11 г. 13 2

Динамические многомерные массивы Используя указатели и динамическое выделение памяти сконструируем зубчатый массив специального вида Динамические многомерные массивы Используя указатели и динамическое выделение памяти сконструируем зубчатый массив специального вида - нижнюю треугольную матрицу размера n (n вводится с клавиатуры), заполненную числовыми значениями по следующему правилу: 1 2 1 3 2 1 4 3 2 1 5 4 3 2 1 6 5 4 3 2 1 7 6 5 4 3 2 1 8 7 6 5 4 3 2 1 9 8 7 6 5 4 3 2 Лекция 04. 10. 11 г. 1 14

Динамические многомерные массивы #include <stdio. h> #include <stdlib. h> main() { int i, j, Динамические многомерные массивы #include #include main() { int i, j, n; int **t; printf("n: "); scanf("%d", &n); t = (int **)calloc(n, sizeof(**t)); for(i = 0; i < n; i++) { t[i] = (int *)calloc(i+1, sizeof(*t)); for(j = 0; j <= i; j++) t[i][j] = i-j+1; } for(i = 0; i < n; i++) { for(j = 0; j <= i; j++) printf("%4 d", t[i][j]); printf("n"); } system("PAUSE"); return 0; } Лекция 04. 10. 11 г. 15