Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

книги / Практикум по программированию на языке Си

..pdf
Скачиваний:
23
Добавлен:
12.11.2023
Размер:
3.53 Mб
Скачать

C:\...>test.exe<result<ENTER>

получен такой результат:

The values from stdin: sizeArray=6

array[0]=1

array[1]=3

array[2]=4

array[3]=7

array[4]=11

array[5]=18

The solution:

array[5]=18 array[4]=11 array[3]=7 array[2]=4 array[1]=3 array[0]=1

В некоторых деталях программа похожа на программу 06_03.с. Значение sizeArray вводится из входного потока во внешнем блоке. Массив array[sizeArray] для вводимой числовой последовательности создается во внутреннем блоке. Значения элементов массива в цикле считываются из входного потока и выводятся (для иллюстрации) в выходной поток. Затем в следующем цикле выполняется их печать в обратном порядке. Распределение выводимой информации по строкам осуществляется за счет вывода (по спецификации %c) в стандартный выходной поток либо символа ‘\t’, либо символа ‘\n’. Выбор "регулируется" значением выражения j%4, где j – вспомогательный параметр цикла.

ЗАДАНИЕ. Выполните рассмотренную программу 06_12B.c без переназначения потока ввода, т.е. введя данные с клавиатуры.

Учтите требования, предъявленные программой к исходным данным: первое число – количество членов в последовательности, затем соответствующие числовые значения членов. Перед исходными данными придется помещать произвольную строку символов (без пробелов), которую программа пропустит при вводе за счет спецификации преобразования %*s в первом обращении к функции scanf().

Проанализируйте результаты исполнения программы и объясните причины их “ненаглядного” представления.

При выполнении программы 06_12B.c по команде

191

C:\...>test.exe<ENTER>

диалог с пользователем и результат выглядят, например, так:

The_input_data:<ENTER> 4<ENTER>

The values from stdin: sizeArray=4

1<ENTER>

array[0]=1

3<ENTER>

array[1]=3

4<ENTER>

array[2]=4

7<ENTER>

array[3]=7

The sulution:

array[2]=4

array[1]=3

array[0]=1

array[3]=7

ЭКСПЕРИМЕНТ. Выполните программу 06_12B.c без переназначения входного потока, набрав в первой строке (обратите внимание на пробелы):

The input data: <ENTER>

Объясните результат выполнения. (При вводе данных функцией scanf() по спецификации %s чтение выполняется до первого пробела. Последовательность "input" и "data" воспринимаются как значения переменной sizeArray и array[0], что ошибочно.)

ЗАДАНИЕ. Замените в тексте программы 06_12B.c вызов функции

scanf(“%*s%d”, &sizeArray);

такой последовательностью: char skip[1000];

gets(skip);

scanf(“%d”,&sizeArray);

Выполните программу без переназначения входного потока, вводя в первой строке те же данные (с пробелами), что и в предыдущем эксперименте.

192

Программа 06_12B_1.c реализует такой вариант. Функция gets() читает из входного потока данные до появления кода "конец строки" (формируемого при нажатии клавиши ENTER). Коды пробелов вводятся как значащие символы. Символьный массив skip[] служит вспомогательным буфером, данные из которого в программе не обрабатываются.

ЗАДАНИЕ. Подготовьте с помощью любого текстового редактора файл с исходными данными, пригодными для чтения программой 06_12B.с, и назовите его 06_12.txt. Выполните программу, настроив входной поток на файл 06_12.txt:

…>test.exe<06_12.txt

Пример данных в файле:

06_12.txt-input_data-file

5

21

7

44

39

11

Обратите внимание, что значения в примере вовсе не образуют последовательность Фибоначчи.

ЗАДАЧА 06-13. Разделите на две программы (генерация и обработка) приведенную в предыдущем параграфе программу 06_09.с сортировки массива с целочисленными элементами, имеющими значения: 12*sin((5*i+2)/3), где i – индекс элемента.

В программе генерации последовательности значений массив как таковой не нужен. Программа должна вычислять заданное (пользователем с клавиатуры) количество числовых значений и выводить их в стандартный выходной поток. Перед последовательностью значений элементов массива нужно выводить их количество. Текст программы генерации:

/* 06_13A.c - генерация последовательности

12*sin((5*i+2)/3) */

193

#include <stdio.h> #include <math.h> int main ()

{

int sizeRow, member,i; printf("sizeRow="); scanf("%d",&sizeRow); printf("%d\n",sizeRow); for (i=0; i<sizeRow; i++)

{member=12*sin((5*i+2)/3.0);

printf("%d\n",member);

}

return 0;

}

Результат выполнения программы при "настройке" стандартных потоков ввода-вывода на клавиатуру и экран дисплея:

sizeRow=8<ENTER>

8

7

8 -9 -6 10 4 -11 -2

Если после компиляции исполнимый модуль программы 06_13A.c помещен в файл test.exe, то директива

>test.exe>sequence<ENTER>

с последующим вводом с клавиатуры количества элементов:

8<ENTER>

формирует текстовый файл sequence с результатами:

sizeRow=

8

7

194

8 -9 -6 10 4 -11 -2

Обратите внимание, что при таком выполнении программы вводимое пользователем значение sizeRow (в примере, равное 8) не перенесено в файл sequence.

Информацию должна прочитывать из текстового файла sequence программа обработки, задача которой (см. условие задачи 06-09) – сформировать массив и рассортировать его, поместив вначале элементы с четными, а затем с нечетными значениями. В программе обработки не требуется вызывать функцию sin(), поэтому не нужно включать заголовочный файл <math.h>. При чтении информации из файла sequence нужно пропустить (игнорировать) "подсказку" sizeRow=, размещенную в первой строке. Для этого используем спецификацию преобразования %*s в форматной строке функции scanf(). Остальная часть программы полностью повторяет текст из программы 06_09.с предыдущего параграфа. Текст программы может быть таким:

/* 06_13B.c - сортировка значений из файла */ #include <stdio.h>

int main ()

{

int sizeArray; scanf("%*s%d",&sizeArray);

{int i, j, jmax, k, kmax;

int series[sizeArray], temp; for (i=0; i<sizeArray; i++) scanf("%d",&series[i]);

printf

("The values from stdin:\nsizeArray=%d",sizeArray); for (i=0; i<sizeArray; i++)

printf ("%cseries[%d]=%d",i%4?'\t':'\n',i,series[i]);

jmax=sizeArray-1; kmax=sizeArray-1;

195

for (j=0; j <= jmax; j++)

{ if (series[j]%2 == 0) continue; for (k=kmax; k > j ; k--)

if (series[k]%2 == 0)

{temp =series[j]; series[j]=series[k]; series[k]= temp;

kmax=jmax=k-1; break;

}

}

printf("\nResult:");

for (i=0; i<sizeArray; i++) printf

("%cseries[%d]=%d",i%4?'\t':'\n',i,series[i]);

}

return 0;

}

Если исполнимый модуль программы test.exe, то, имея сформированный ранее программой 06_13A.c файл sequence, можно ввести такую директиву:

>test.exe< sequence<ENTER>

Результат выполнения программы:

The values from stdin: sizeArray=8

series[0]=7 series[1]=8 series[2]=-9 series[3]=-6 series[4]=10 series[5]=4 series[6]=-11 series[7]=-2 Result:

series[0]=-2 series[1]=8 series[2]=4 series[3]=-6 series[4]=10 series[5]=-9 series[6]=-11 series[7]=7

ЗАДАНИЕ. Приведите программы этого параграфа в соответствие с требованиями традиционного языка Си, т.е. используйте константные выражения в определениях размеров массивов. (При этом не понадобится вложение блоков в программах.)

ЗАДАНИЕ. Перепишите программы из предыдущего параграфа (06_10.с – упорядочение прямым перебором; 06_11.с – сорти-

196

ровка методом пузырька), разделив каждую из них на две части: генерация и запись в файл последовательности числовых значений и обработка (сортировка) с выводом результатов.

6.4. Массивы и матрицы

ЗАДАЧА 06-14. Определите целочисленный двумерный массив (матрицу) с размерами 3 (строки) на 2 (столбца). Инициализируйте элементы массива с помощью одного списка, содержащего значения от 1 до 6. Напечатайте значения массива "по строкам".

/* 06_14.c - инициализация двумерного массива */ #include <stdio.h>

int main ()

{

int i, j;

int ar[3][2]={1,2,3,4,5,6}; for (i=0; i<3; i++)

{printf("\n");

for (j=0; j<2; j++)

printf("ar[%d][%d]=%d\t",i,j,ar[i][j]);

}

return 0;

}

Результаты выполнения программы:

ar[0][0]=1 ar[0][1]=2 ar[1][0]=3 ar[1][1]=4 ar[2][0]=5 ar[2][1]=6

Результаты выполнения программы иллюстрируют "порядок" размещения в памяти элементов многомерного массива. Друг за другом (подряд) располагаются элементы в соответствии с возрастанием самого правого индекса. Еще раз обратите внимание, что индексы элементов массива начинаются с 0. Это не соответствует принятой в математике нумерации строк и столбцов матриц.

ЗАДАНИЕ. Измените в программе список инициализации, ограничив в нем фигурными скобками значения, относящиеся к

197

строкам. Убедитесь, что результаты выполнения программы не изменяются при таком списке: {{1,2},{3,4},{5,6}}.

ЗАДАЧА 06-15. Определите двумерный целочисленный массив с размерами 4 на 4. С помощью инициализации "превратите" массив в единичную матрицу. Напечатайте полученную матрицу. (Учтите при печати, что нумерация элементов массива начинается с 0, а в матрице строки и столбцы нумеруются, начиная с 1.)

/* 06_15.c – инициализация массива с единичной матрицей */

#include <stdio.h> #define N 4

int main ()

{

int i, j;

int ar[N][N]={1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1}; for (i=0; i<N; i++)

{printf("\n");

for (j=0; j<N; j++) printf("ar[%d,%d]=%d\t",i+1,j+1,ar[i][j]);

}

return 0;

}

Чтобы подчеркнуть отличие нумерации элементов матриц от элементов массивов, при выводе использована конструкция [i,j].

Результаты выполнения программы:

ar[1,1]=1

ar[1,2]=0

ar[1,3]=0

ar[1,4]=0

ar[2,1]=0

ar[2,2]=1

ar[2,3]=0

ar[2,4]=0

ar[3,1]=0

ar[3,2]=0

ar[3,3]=1

ar[3,4]=0

ar[4,1]=0

ar[4,2]=0

ar[4,3]=0

ar[4,4]=1

В программе инициализация выполнена с помощью одного списка начальных значений. Наглядность повысится, если использовать (как в предыдущем задании) вложенные инициализаторы для отдельных строк:

int ar[N][N]= {{…},{…},{…},{…}};

198

Этот вариант реализован в программе 06_15_1.с.

ЗАДАНИЕ. С помощью инициализации сформируйте в двумерном массиве верхнюю треугольную матрицу, присвоив ее ненулевым элементам номера тех строк, в которых они расположены. (Напомним, что матрица aikназывается верхней тре-

угольной, если aik==0 для всех i>k.)

Эта задача решена в программе 06_15_2.с.

ЗАДАНИЕ. С помощью инициализации сформируйте в двумерном массиве матрицу, у которой все элементы нулевые, за исключением:

1) первого столбца, элементы которого равны 1;

2)последней строки, элементы которой кроме первого равны номеру строки.

Не все понятно при необходимости в программе создавать и обрабатывать матрицы с переменными размерами. Например, рассмотрим такую простейшую проблему.

ЗАДАЧА 06-16. Сформируйте матрицу с заранее не фиксированными размерами n на m, присвойте ее элементам значения i+k, где i – номер строки, k – номер столбца элемента. Распечатайте полученную матрицу "по строкам".

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

имя_массива[индекс_1][индекс_2]

Так как по условию задачи размеры матрицы заранее не фиксированы, то для ее представления, во-первых, можно применять средства динамического распределения памяти (будут рассмотрены позже). Во-вторых, возможно определить в программе массив с фиксированными размерами, которые должны быть заведомо больше, чем размеры тех матриц, для представления которых массив создается. Третье решение предлагает Стандарт 99 языка Си, допускающий определение массивов с переменными размерами.

199

Благожелательный к нуждам программистов компилятор (например, DJGPP), нарушая устаревшие ограничения языка Си, позволяет во внутреннем блоке программы определять двумерный массив, размеры которого вычисляются во внешнем блоке. Используя указанные возможности, определим во внешнем блоке программы переменные n и m и присвоим им (или инициализацией, или с помощью ввода, или операцией присваивания) желаемые значения. Во вложенном блоке определим двумерный массив matr[n][m] для представления матрицы. Решение с инициализацией переменных n и m представляет следующая программа:

/* 06_16.c - двумерный массив с переменными размерами */

#include <stdio.h> int main ()

{

int n=4, m=3;

{int i, j;

int matr[n][m];

for (i=0; i<n; i++) for (j=0; j<m; j++)

matr[i][j]=(i+1)+(j+1); for (i=0; i<n; i++)

{printf("\n");

for (j=0; j<m; j++)

printf ("matr[%d,%d]=%d\t",i+1,j+1,matr[i][j]);

}

}

return 0;

}

Результаты выполнения программы:

matr[1,1]=2 matr[1,2]=3 matr[1,3]=4 matr[2,1]=3 matr[2,2]=4 matr[2,3]=5 matr[3,1]=4 matr[3,2]=5 matr[3,3]=6 matr[4,1]=5 matr[4,2]=6 matr[4,3]=7

ЗАДАНИЕ. Измените программу, добавив ввод с клавиатуры размеров формируемой матрицы.

Задача решена в программе 06_16_1.с.

200