Главная страница
Навигация по странице:

  • Внимание

  • Внимание! Первый индекс ACol определяет номер столбца, а второй A

  • Options

  • Л5_для Teams. Лабораторная работа 5. Обработка одномерных массивов Цель работы


    Скачать 64.92 Kb.
    НазваниеЛабораторная работа 5. Обработка одномерных массивов Цель работы
    Дата13.12.2021
    Размер64.92 Kb.
    Формат файлаdocx
    Имя файлаЛ5_для Teams.docx
    ТипЛабораторная работа
    #301478

    Лабораторная работа №5. Обработка одномерных массивов




    Цель работы: изучить составной тип данных – массив, основные свойства компоненты StringGrid. Написать и отладить программу с использованием одномерных массивов.

    5.1. Общие теоретические сведения


    Массив – конечная последовательность данных одного типа. Массив – объект сложного типа, каждый элемент которого определяется именем (ID) и целочисленным значением индекса (номера), по которому к элементу массива производится доступ. Рассмотрим одномерные массивы.

    Внимание! Индексы массивов в языке С/С++ начинаются с 0.

    В программе одномерный массив декларируется следующим образом:

    тип ID массива [размер];

    где размер – указывает количество элементов в массиве. Размер массива может задаваться константой или константным выражением. Для использования массивов переменного размера существует отдельный механизм – динамическое выделение памяти.

    Примеры декларации массивов:

    int a[5];

    double b[4] = {1.5, 2.5, 3.75};

    в целочисленном массиве а первый элемент а[0], второй – а[1], …, пятый – а[4]. Для массива b, состоящего из действительных чисел, выполнена инициализация, причем элементы массива получат следующие значения: b[0]=1.5, b[1]=2.5, b[2]=3.75, b[3]=0.

    В языке С/С++ не проверяется выход индекса за пределы массива. Корректность использования индексов элементов массива должен контролировать программист.

    Примеры описания массивов:

    const Nmax=10; – задание максимального значения;

    typedef double mas1[Nmax*2]; – описание типа одномерного массива;

    mas1 a; – декларация массива а типа mas1;

    int ss[10]; – массив из десяти целых чисел.

    Элементы массивов могут использоваться в выражениях так же, как и обычные переменные, например:

    f = 2*a[3] + a[Ss[i] + 1]*3;

    a[n] = 1 + sqrt(fabs(a[n–1]));

    5.2. Создание оконного приложения

    Компонента StringGrid


    При работе с массивами ввод и вывод значений обычно организуется с использованием компоненты StringGrid, предназначенной для отображения информации в виде двухмерной таблицы, каждая ячейка которой представляет собой окно однострочного редактора (аналогично окну Edit). Доступ к информации осуществляется с помощью элемента Cells[ACol][ARow] типа AnsiString, где целочисленные значения ACol, ARow указывают позицию элемента.

    Внимание! Первый индекс ACol определяет номер столбца, а второй ARow – номер строки в отличие от индексов массива.

    В инспекторе объектов значения ColCount и RowCount устанавливают начальные значения количества столбцов и строк в таблице, а FixedCols и FixedRows задают количество столбцов и строк фиксированной зоны. Фиксированная зона выделена другим цветом и обычно используется для надписей.

    5.3. Пример выполнения задания


    Удалить из массива А размером N, состоящего из целых чисел (положительных и отрицательных), все отрицательные числа. Новый массив не создавать. Для заполнения массива использовать фунцию random(kod) – генератор случайных равномерно распределенных целых чисел от 0 до (int)kod.

    5.3.1. Пример создания оконного приложения


    Значение N вводить из Edit, значения массива А – из компоненты StringGrid. Результат вывести в компоненту StringGrid.

    Панель диалога и результаты выполнения программы приведена на рис. 5.1.



    Рис. 5.1



    Настройка компоненты StringGrid


    На закладке Additional выберите пиктограмму , установите компоненты StringGrid1 и StringGrid2 и отрегулируйте их размеры. В инспекторе объектов для обоих компонент установите значения ColCount равными 2, RowCount равными 1, т.е. по два столбца и одной строке, а значения FixedCols и FixedRows равными 0. Значение ширины клетки столбца DefaultColWidth равным 40.

    По умолчанию в компоненту StringGrid ввод данных разрешен только программно. Для разрешения ввода данных с клавиатуры необходимо в свойстве Options строку goEditing для компоненты StringGrid1 установить в положение true.

    Текст функций-обработчиков может иметь следующий вид:

    . . .

    int n = 4;

    //---------------------------------------------------------------------------

    void __fastcall TForm1::FormCreate(TObject *Sender)

    {

    randomize(); // Изменение начального адреса для random()

    Edit1->Text=IntToStr(n);

    StringGrid1->ColCount=n;

    for(int i=0; i
    StringGrid1->Cells[i][0] = IntToStr(random(21)-10);

    Label3->Hide(); // Скрыть компоненту

    StringGrid2->Hide();

    }

    //---------------------------------------------------------------------------

    void __fastcall TForm1::Button1Click(TObject *Sender)

    {

    n=StrToInt(Edit1->Text);

    if(n>10){

    ShowMessage("Максимальное количество 10!");

    n=10;

    Edit1->Text = "10";

    }

    StringGrid1->ColCount=n;

    for(int i=0; i
    StringGrid1->Cells[i][0]=IntToStr(random(21)-10);

    Label3->Hide();

    StringGrid2->Hide();

    }

    //---------------------------------------------------------------------------

    void __fastcall TForm1::Button2Click(TObject *Sender)

    {

    int i, kol = 0, a[10]; // Декларация одномерного массива

    //Заполнение массива А элементами из таблицы StringGrid1

    for(i=0; i
    a[i]=StrToInt(StringGrid1->Cells[i][0]);

    //Удаление отрицательных элементов из массива А

    for(i=0; i
    if(a[i]>=0) a[kol++] = a[i];

    StringGrid2->ColCount = kol;

    StringGrid2->Show(); // Показать компоненту

    Label3->Show();

    //Вывод результата в таблицу StringGrid2

    for(i=0; iCells[i][0]=IntToStr(a[i]);

    }



    5.3.2. Пример создания консольного приложения


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

    . . .

    #include

    #include

    void main()

    {

    int a[10],n, i, kol=0;

    randomize(); // Изменение начального адреса для random()

    printf("Input N (<=10) ");

    scanf("%d", &n);

    puts("\n Massiv A");

    for(i=0; i
    a[i] = random(21)-10; // Заполнение массива А случайными числами

    printf("%4d", a[i]);

    }

    //Удаление отрицательных элементов из массива А

    for(i=0; i
    if(a[i]>=0) a[kol++] = a[i];

    puts("\n Rezult massiv A");

    for(i=0; i
    puts("\n Press any key ... ");

    getch();

    }
    С заполненным случайными числами массивом А результат программы может быть следующим:



    5.4. Индивидуальные задания


    Написать программу по обработке одномерных массивов. Размеры массивов вводить с клавиатуры. Предусмотреть возможность ввода данных как с клавиатуры, так и с использованием функции random().

    При создании оконного приложения скалярный (простой) результат выводить в виде компоненты Label, а массивы вводить и выводить с помощью компонент StringGrid.

    В одномерном массиве, состоящем из n вводимых с клавиатуры целых элементов, вычислить:

    1. Произведение элементов массива, расположенных между максимальным и минимальным элементами.

    2. Сумму элементов массива, расположенных между первым и последним нулевыми элементами.

    3. Сумму элементов массива, расположенных до последнего положительного элемента.

    4. Сумму элементов массива, расположенных между первым и последним положительными элементами.

    5. Произведение элементов массива, расположенных между первым и вторым нулевыми элементами.

    6. Сумму элементов массива, расположенных между первым и вторым отрицательными элементами.

    7. Сумму элементов массива, расположенных до минимального элемента.

    8. Сумму целых частей элементов массива, расположенных после последнего отрицательного элемента.

    9. Сумму элементов массива, расположенных после последнего элемента, равного нулю.

    10. Сумму модулей элементов массива, расположенных после минимального по модулю элемента.

    11. Сумму элементов массива, расположенных после минимального элемента.

    12. Сумму элементов массива, расположенных после первого положительного элемента.

    13. Сумму модулей элементов массива, расположенных после первого отрицательного элемента.

    14. Сумму модулей элементов массива, расположенных после первого элемента, рав­ного нулю.

    15. Сумму положительных элементов массива, расположенных до максимального элемента.

    16. Произведение элементов массива, расположенных между первым и последним отрицательными элементами.



    Лабораторная работа №6. Обработка двухмерных динамических массивов



    Цель работы: изучить понятие «указатель», правила создания и приемы обработки динамических массивов на примере двухмерного массива.

    6.1. Краткие теоретические сведения

    Особенности применения указателей


    Обращение к объектам любого типа в языке C может проводиться по имени, как мы до сих пор делали, и по указателю (косвенная адресация).

    Указатель – это переменная, которая может содержать адрес некоторого объекта в памяти компьютера, например адрес другой переменной. Через указатель, установленный на переменную, можно обращаться к участку оперативной памяти (ОП), отведенной компилято­ром под ее значение.

    Указатель объявляется следующим образом:

    тип * ID указателя;

    Перед использованием указатель должен быть инициирован либо конкретным адресом, либо значением NULL (0) – отсутствие указателя.

    С указателями связаны две унарные операции: & и *. Операция & означает «взять адрес», а операция разадресации * – «значение, расположенное по адресу», например:

    int x, *y; // х – переменная типа int , у – указатель типа int

    y = &x; // y – адрес переменной x

    *y = 1; // по адресу y записать 1, в результате x = 1

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

    Операции сложения, вычитания и сравнения (больше/меньше) имеют смысл только для последовательно расположенных данных – массивов. Операции сравнения «==» и «!=» имеют смысл для любых указателей, т.е. если два указателя равны между собой, то они указывают на одну и ту же переменную.

    Связь указателей с массивами


    Указатели и массивы тесно связаны между собой. Идентификатор массива является указателем на его первый элемент, т.е. для массива int a[10] выражения a и a[0] имеют одинаковые значения, т.к. адрес первого (с индексом 0) элемента массива – это адрес начала размещения его элементов в ОП.

    Пусть объявлены массив из 10 элементов и указатель типа double:

    double a[10], *p;

    если p = a; (установить указатель p на начало массива a), то следующие обращения: a[i] , *(a+i) и *(p+i) эквивалентны, т.е. для любых указателей можно использовать две эквивалентные формы доступа к элементам массива: a[i] и *(a+i). Очевидна эквивалентность следующих выражений:

    &a[0]  &(*p)  p

    Декларация многомерного массива:


    тип ID[размер 1][размер 2]…[размер N];

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

    int a[2][3] = {{0,1,2},{3,4,5}};

    в ОП будет размещен следующим образом:

    a[0][0]=0, a[0][1]=1, a[0][2]=2,a[1][0]=3, a[1][1]=4, a[1][2]=5.

    Если в списке инициализаторов данных не хватает, то соответствующему элементу присваивается значение 0.

    Указатели на указатели


    Связь указателей и массивов с одним измерением справедлива и для массивов с бóльшим числом измерений.

    Если рассматривать предыдущий массив (int a[2][3];) как массив двух массивов размерностью по три элемента каждый, то обращению к элементу а[i][j] соответствует эквива­лентное выражение *(*(а+i)+j), а объявление этого массива с использованием указателей будет иметь вид

    int **а;

    Таким образом, имя двухмерного массива – ID указателя на указатель.

    Динамическое размещение данных


    Для создания массивов с переменной размерностью используется динамическое размещение данных, декларируемых указателями.

    Для работы с динамической памятью используются стандартные функции библиотеки alloc.h:

    void*malloc(size) и void *calloc(n, size) – выделяют блок памяти размером size и nsize байт соответственно; возвращают указатель на выделенную область, при ошибке – значение NULL;

    void free(bf); – освобождает ранее выделенную память с адресом bf.

    Другим, более предпочтительным подходом к динамическому распределению памяти является использование операций языка С++ new и delete.

    Операция new возвращает адрес ОП, отведенный под динамически размещенный объект, при ошибке – NULL, а операция deleteосвобождает память.

    Минимальный набор действий, необходимых для динамического размещения одномерного массива действительных чисел размером n:


    double *а;

    . . .

    а = new double[n]; // Захват памяти для n элементов

    . . .

    delete []а; // Освобождение памяти

    Минимальный набор действий, необходимых для динамического размещения двухмерного массива действительных чисел размером nm:


    int i, n, m; // n, m – размеры массива

    double **a;

    a = new double *[n]; // Захват памяти под указатели

    for(i=0; i
    a[i] = new double [m]; // и под элементы

    . . .

    for(i=0; i
    delete []a;

    6.2. Пример выполнения задания


    Рассчитать значения вектора , где А – квадратная матрица размером NN, а Y и B – одномерные массивы размером N. Элементы вектора Y определяются по формуле .

    6.2.1. Пример создания оконного приложения


    Значение N вводить из Edit, А и B – из компонент StringGrid. Результат вывести в компоненту StringGrid.

    Панель диалога и результаты выполнения программы приведена на рис. 6.1.



    Рис. 6.1

    Настройка компонент StringGrid


    Для компоненты StringGrid1 значения ColCount и RowCount установите равными, например, 3 – три столбца и три строки, а FixedCols и FixedRows – 1.

    Так как компоненты StringGrid2 и StringGrid3 имеют только один столбец, то у них ColCount = 1, RowCount = 3, а FixedCols = 0 и FixedRows = 1.

    В свойстве Options строку goEditing для компонент StringGrid1 и StringGrid2 установите в положение true.

    Для изменения размера n используется функция-обработчик EditChange, полученная двойным щелчком по компоненте Edit.

    Текст программы может иметь следующий вид:

    . . .

    //---------------------- Глобальные переменные -------------------

    int n = 3;

    double **a, *b; // Декларации указателей

    //---------------------------------------------------------------------------

    void __fastcall TForm1::FormCreate(TObject *Sender)

    {

    Edit1->Text=IntToStr(n);

    StringGrid1->ColCount = n+1; StringGrid1->RowCount = n+1;

    StringGrid2->RowCount = n+1; StringGrid3->RowCount = n+1;

    // Ввод в левую верхнюю ячейку таблицы названия массивов

    StringGrid1->Cells[0][0] = "Матрица A";

    StringGrid2->Cells[0][0] = "Массив B";

    StringGrid3->Cells[0][0] = "Массив Y";

    for(int i=1; i<=n;i++){

    StringGrid1->Cells[0][i]="i="+IntToStr(i);

    StringGrid1->Cells[i][0]="j="+IntToStr(i);

    }

    }

    //---------------------------------------------------------------------------

    void __fastcall TForm1::Edit1Change(TObject *Sender)

    {

    int i;

    n=StrToInt(Edit1->Text);

    StringGrid1->ColCount = n+1; StringGrid1->RowCount = n+1;

    StringGrid2->RowCount = n+1; StringGrid3->RowCount = n+1;

    for(i=1; i<=n;i++){

    StringGrid1->Cells[0][i]="i="+IntToStr(i);

    StringGrid1->Cells[i][0]="j="+IntToStr(i);

    }

    }

    //---------------------------------------------------------------------------

    void __fastcall TForm1::Button1Click(TObject *Sender)

    {

    double s;

    int i,j;

    a = new double*[n]; // Захват памяти под указатели

    for(i=0; iЗахват памяти под элементы

    b = new double[n];

    // Заполнение массивов А и В элементами из таблиц StringGrid1 и StringGrid2

    for(i=0; i
    for(j=0; jCells[j+1][i+1]);

    b[i]=StrToFloat(StringGrid2->Cells[0][i+1]);

    }

    // Умножение строки матрицы А на вектор В и вывод результата s в StringGrid3

    for(i=0; i
    for(s=0, j=0; j
    StringGrid3->Cells[0][i+1] = FloatToStrF(s, ffFixed,8,2);

    }

    }

    //---------------------------------------------------------------------------

    void __fastcall TForm1::Button2Click(TObject *Sender)

    {

    for(int i=0; i
    delete []a; delete []b;

    ShowMessage("Память освобождена!");

    Close();

    }

    4.3.2. Пример создания консольного приложения


    Текст программы может иметь следующий вид:

    . . .

    void main()

    {

    double **a, *b, s;

    int i, j, n;

    puts("Input size N < 10"); scanf("%d",&n);

    a = new double*[n]; // Захват памяти под указатели

    for(i=0; ia[i] можно заменить на *(a+i)

    b = new double[n]; // Захват памяти под элементы

    puts("\nInput Massiv A:");

    for(i=0; i
    for(j=0; j
    puts("\nInput Massiv B:");

    for( i=0; i
    puts("\nMassiv Y:");

    for(i=0; i
    for(s=0, j=0; j
    s+=a[i][j]*b[j];

    printf(" %8.2lf ", y[i]);

    }

    puts("\nPress any key ... ");

    getch();

    }
    При вводе значений элементов массивов в одной строке через пробелы должен получиться следующий результат:

    6.3. Индивидуальные задания


    Написать программу по обработке динамических массивов. Размеры массивов вводить с клавиатуры. При создании оконного приложения скалярный (простой) результат выводить в виде компоненты Label, а массивы вводить и выводить с помощью компонент StringGrid, в которых 0-й столбец и 0-ю строку использовать для отображения индексов массивов.

    1. Из матрицы размером NM получить вектор B, присвоив его k-му элементу значение 0, если все элементы k-го столбца матрицы нулевые, иначе 1.

    2. Из матрицы размером NM получить вектор B, присвоив его k-му элементу значение 1, если элементы k-й строки матрицы упорядочены по убыванию, иначе 0.

    3. Из матрицы размером NM получить вектор B, присвоив его k-му элементу значение 1, если k-я строка матрицы симметрична, иначе значение 0.

    4. Задана матрица размером NM. Определить количество «особых» элементов матрицы, считая элемент «особым», если он больше суммы остальных элементов своего столбца.

    5. Задана матрица размером NM. Определить количество элементов матрицы, у которых слева находится элемент больше его, а справа – меньше.

    6. Задана матрицаразмером NM. Определить количество различных значений матрицы, т.е. повторяющиеся элементы считать один раз.

    7. В матрице размером NM упорядочить строки по возрастанию их первых элементов.

    8. В матрице размером NM упорядочить строки по возрастанию суммы их элементов.

    9. В матрице размером NM упорядочить строки по возрастанию их наибольших элементов.

    10. Определить, является ли квадратная матрица симметричной относительно побочной диагонали.

    11. Задана матрица размером NM. Определить количество элементов матрицы, у которых слева находится элемент меньше его, а справа – больше.

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

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

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

    15. Из матрицы размером nполучить матрицу размером n–1 путем удаления строки и столбца, на пересечении которых расположен элемент с наибольшим по модулю значением.

    16. В матрице размером n найти сумму элементов, лежащих ниже главной диагонали, и произведение элементов, лежащих выше главной диагонали.


    написать администратору сайта