- •Министерство образования Республики Беларусь
- •1. Что такое программа на языке программирования
- •2. Общее знакомство с языком с
- •3. Структура простой программы на языке с
- •4. Что такое программа на языке с
- •5. Представление информации и типы данных в языке с
- •6. Константы
- •7. Переменные
- •8. Элементарный вВод и вывод информации
- •9. Выражения и операции
- •9.1. Арифметические операции
- •9.2. Операция изменения знака
- •9.3. Операции инкремента и декремента
- •9.4. Операция присваивания
- •9.6. Поразрядные логические операции
- •9.8. Логические операции и операции отношения
- •9.9. Условная операция «? :»
- •9.10. Операция последовательного вычисления
- •9.11. Операция определения требуемой памяти в байтах sizeof
- •9.12. Операция приведения типа (type)
- •10. Операторы управления вычислительным процессом
- •10.1. Операторы ветвления if и else
- •10.2. Оператор switch
- •10.3. Оператор цикла while
- •10.4. Оператор цикла do…while
- •10.5. Оператор цикла for
- •10.6. Бесконечные циклы
- •10.7. Другие управляющие средства языка с
- •10.8. Стандартные математические функции
- •11. Вычисление выражений и побочные эффекты
- •11.1. Преобразования типов при вычислении выражений
- •11.2. Побочные эффекты при вычислении выражений
- •12. Массивы
- •12.1. Описание массива
- •12.2. Инициализация массива
- •12.3. Ввод-вывод массива
- •12.4. Двумерные массивы (массивы массивов)
- •13. Указатели
- •14. Адресная арифметика
- •15. Массивы и указатели
- •15.1. Указатели и одномерные массивы
- •15.2. Указатели и двумерные массивы
- •16. Строки
- •17. Массивы строк
- •18. Функции
- •18.1. Определение функции в языке с
- •18.2. Возвращение значений из функции
- •18.3. Формальные и фактические параметры функции
- •18.4. Вызов функции
- •18.5. Объявление и определение функции: прототип функции
- •19. Передача параметров в функции
- •19.1. Способы передачи параметров в функции
- •19.2. Передача параметров в функции в языке с
- •19.3. Передача указателей в функции
- •20. Классы хранения и видимость переменных
- •20.1. Общие положения
- •20.2. Спецификаторы класса памяти
- •20.3. Область видимости функций
- •20.4. Глобальные переменные
- •20.5. Глобальные статические переменные
- •20.6. Локальные переменные
- •20.7. Статические локальные переменные
- •20.8. Регистровые переменные
- •20.9. Выводы
- •21. Организация памяти программы
- •22. Многофайловая компиляция (проекты)
- •23. Передача в функции массивОв
- •23.1. Передача одномерных массивов в функции
- •23.2. Передача двумерных массивов в функции
- •23.3. Передача в функции символьных строк
- •23.4. Возвращение указателей из функций
- •24. Функции с переменным количеством аргументов
- •24.1. Соглашения о вызовах: модификаторы функций
- •24.2. Объявление списка параметров переменной длины
- •25. Передача параметров в функцию main()
- •26. Указатели на функцию
- •27. Стандартные функцИи языка с
- •27.1. Функции для работы со строками
- •27.2. Функции для проверки символов и преобразования данных
- •27.3. Функция быстрой сортировки – gsort()
- •27.4. Функция двоичного поиска – bsearch()
- •28. Работа с файлами
- •28.1. Основные понятия
- •28.2. Основные функции для работы с файлами
- •28.3. Открытие и закрытие файлов
- •28.4. Ввод/вывод символов
- •28.5. Ввод/вывод строк
- •28.6. Форматированный ввод/вывод
- •28.7. Ввод/вывод блоков данных
- •28.8. Другие средства для работы с файлами
- •28.9. Ввод/вывод низкого уровня (префиксный доступ к файлам)
- •29. Типы, определяемые пользователем: Перечисления, структуры и объединения
- •29.1. Переименование типов – оператор typedef
- •29.2. Перечисления (enum)
- •29.3. Основные сведения о структурах
- •29.4. Структурные переменные в памяти компьютера
- •29.5. Доступ к полям структуры
- •29.6. Массивы структур
- •29.7. Структуры и функции
- •29.8. Объединения (union)
- •30. Динамическая память
- •30.1. Понятие динамического объекта
- •30.2 Создание и уничтожение динамических объектов
- •30.3 Динамическое размещение одномерных массивов и строк
- •30.4 Динамическое размещение двумерных массивов
- •30.5. Функции для работы с блоками памяти
- •31. Динамические структуры данных
- •31.1. Понятие структуры данных
- •31.2. Структуры, ссылающиеся на себя
- •31.3. Связанные списки
- •31.5. Очереди
- •Ниже приводятся примеры функций для очереди (структура элемента очереди совпадает со структурой элемента стека в примере выше):
- •32. Препроцессор языка с
- •32.1 Директива включения файлов
- •32.2. Директива определения макрокоманд (макросов)
- •32.3 Директива условной компиляции
- •32.4 Дополнительные директивы препроцессора
23.2. Передача двумерных массивов в функции
Вместо одномерного массива функции передается указатель на его первый элемент. Точно так же не передается функции и двумерный массив. Массив массивов (т.е. двумерный массив в языке С) при передаче в функцию превращается в указатель на массив, а не в указатель на указатель. В функцию передается указатель на массив, число элементов которого равно длине строки двумерного массива.
Следующее описание является неверным:
func(int **mas) { // ошибка!!!
...
}
Если в функцию передается двумерный массив:
int mas[N][M];
func(mas);
описание функции должно соответствовать
func(int mas[][M]) {
...
}
или
func(int (*pmas)[M]) { // pmas - указатель на массив из M элементов
...
}
Скобки (*pmas) в объявлении обязательны, т.к. int *pmas[M] – это массив указателей на int, а не указатель на массив.
Обратить внимание! Так как функция не выделяет место для массива, нет необходимости знать его точный размер. Поэтому количество строк N может быть опущено. В то же время количество элементов в строке (количество столбцов M) опускать нельзя, т.к. «форма» массива (количество столбцов) используется для вычисления смещения элемента относительно начала массива. Поэтому количество столбцов (вторую размерность M) надо указывать обязательно.
Задача. Разработать функции для печати массива из 10 столбцов и замены знака у всех элементов массива с 5-ю столбцами.
void print10(int mas[][10], int n) {
int i, j;
for (i=0; i<n; i++) {
for (j=0; j<10; j++)
printf("%5d ", mas[i][j]);
printf("\n");
}
}
void negative5(int (*mas)[5], int n, int m) {
int i, j;
for (i=0; i<n; i++)
for (j=0; j<m; j++)
mas[i][j] = - mas[i][j];
}
void main(void) {
int a[10][10],
b[10][5] = {{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 9, 9, 9}};
int i, j, n=5;
for (i=0; i<n; i++)
for (j=0; j<10; j++)
scanf("%d", &a[i][j]);
print10(a,n);
negative5(b,3,4);
for (i=0; i<3; i++) {
for (j=0; j<4; j++)
printf("%5d ", b[i][j]);
printf("\n");
}
}
Обратить внимание! У двумерных (многомерных) массивов есть один неприятный недостаток при передаче их в функцию – для обработки массива с пятью столбцами нужно писать одну функцию, а для массива с десятью столбцами – другую!
При передаче функции двумерного массива как фактического параметра необходимо обязательно указывать количество столбцов. Однако, если работа с двумерным массивом не требует доступа к элементам посредством конкретного указания строк и столбцов, то функция может воспринимать многомерный массив как одномерный, хотя в качестве фактического параметра ей передается многомерный массив.
long sum(int m[], int n) {
long s = 0;
int i;
for (i = 0; i < n; i++)
s += m[i]; // s += *(m+i);
return s;
}
void main(void) {
int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
int b[2][10] = {{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
{11, 12, 13, 14, 15, 16, 17, 18, 19, 20}};
int c[5][10] = {{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
{11, 12, 13, 14, 15, 16, 17, 18, 19, 20},
{21, 22, 23, 24, 25, 26, 27, 28, 29, 30}};
printf("Сумма массива a = %d\n", sum(a, 10));
printf("Сумма массива b = %d\n", sum((int *)b, 20));
printf("Сумма массива c = %d\n", sum((int *)c, 30));
}
Функция sum() работает с двумерными массивами так же, как и с одномерными массивами. Так работать с двумерным массивом позволяет способ хранения в памяти многомерных массивов в языке С. Правда, есть одно ограничение – реальное количество элементов в строке такого массива должно строго совпадать со второй размерностью массива, а вот количество строк в таком массиве может быть любым.