Kurs podstawy programowania UMCS, zdjęcie laptopa.

PP – Laboratorium 9

Wejściówka

Napisz program w języku C++, który stworzy 10-cio elementową tablicę liczb całkowitych i wypełni ją dowolnymi wartościami. Użyj dynamicznej alokacji pamięci.

Rozwiązanie:
int main() {
    int *arr = new int[10];
    for(int i = 0; i < 10; ++i) arr[i] = i;
    delete[] arr;
    return 0;
}

Zadanie 1

Napisz funkcję w języku C++, która przyjmie jako argumenty dwa napisy – przeszukiwany i poszukiwany. Jeżeli w napisie przeszukiwanym znajduje się napis będący zgodny z napisem poszukiwanym, funkcja powinna zwrócić wskaźnik na indeks pierwszego znaku odnalezionego pod-napisu. W przeciwnym razie funkcja powinna zwrócić nullptr. Napisz program w języku C++, który przetestuje działanie tej funkcji.

Rozwiązanie:
#include <iostream>

char *search(char str[], char str1[]) {
    bool found;
    for(int i = 0; str[i]; ++i) {
        found = true;
        for(int j = 0; str1[j] && str[i + j]; ++j)
            if(str[i + j] != str1[j]) {
                found = false;
                break;
            }
        if(found) return str + i;
    } return nullptr;
}

int main() {
    char str[] = "Ala ma kota.", str1[] = "kota";
    char *found = search(str, str1);

    if(found) 
        std::cout << found << " , index:" << found - str << std::endl;
    else 
        std::cout << "not found\n";

    return 0;
}

Zadanie 2

Napisz program w języku C++, który wczyta od użytkownika wymiary prostokątnego pola bitwy NxM, a następnie dla każdego pola dwie wartości całkowite A oraz D. Na każdym polu znajduje się działo: A definiuje jego moc ataku, zaś D jego obronę. Działa strzelają do siebie nawzajem, jeśli działo atakujące ma większą wartość ataku niż wartość defensywy przeciwnika, to wygrywa walkę i niszczy działo atakowane. W przeciwnym wypadku wygrywa działo broniące się, niszcząc działo atakujące. Program po wczytaniu pola bitwy powinien wczytać wartość nieujemnej zmiennej całkowitej C, a następnie C sekwencji danych: ax, ay, dx, dy, gdzie ax, ay to współrzędne działa atakującego, zaś dx, dy działa broniącego się, po każdej operacji z pola bitwy powinno zniknąć jedno działo. Na koniec program powinien wyświetlić stan pola bitwy w formie:
0 X 0 0 0
0 0 0 X 0
X X 0 0 0

,gdzie X – oznacza działo zniszczone, a O – działo, które pozostało na polu bitwy. Użyj dynamicznej alokacji pamięci, rozwiązanie powinno być rozwiązaniem optymalnym. (Optymalne: pole bitwy powinno być spójnym obszarem pamięci.)
Przykład:
5 3
1 5 2 6 9 2
1 5 7 1 2 2
5 3 2 8 9 5
6 6 8 2 4 1
3 6 4 2 8 3
3
0 0 4 2
4 2 0 2
1 1 2 1

Rozwiązanie:
//Version 1.0
#include <cstdio>
typedef unsigned int uint;

void print_arr(int ***arr, uint n, uint m) {
    for(uint i = 0; i < n; ++i) {
        for(uint j = 0; j < m; ++j)
            printf("%c ", arr[i][j][0] == -1 && arr[i][j][1] == -1 ? 'X' : 'O');
        printf("\n");
    }
}

void f(int ***arr, uint ax, uint ay, uint dx, uint dy) {
    if(arr[ax][ay][0] > arr[dx][dy][1]) arr[dx][dy][0] = arr[dx][dy][1] = -1;
    else arr[ax][ay][0] = arr[ax][ay][1] = -1;
}

int main() {
    uint n, m, c, ax, ay, dx, dy;
    scanf("%u%u", &n, &m);

    int ***battlefield = new int**[n];
    for(uint i = 0; i < n; ++i) {
        battlefield[i] = new int*[m];
        for(uint j = 0; j < m; ++j)
            battlefield[i][j] = new int[2](); //() - inicjalizacja zerami
    }
    print_arr(battlefield, n, m);

    for(uint i = 0; i < n; ++i)
        for(uint j = 0; j < m; ++j)
            scanf("%d%d", &battlefield[i][j][0], &battlefield[i][j][1]);

    scanf("%u", &c);
    for(uint i = 0; i < c; ++i) {
        scanf("%u%u%u%u", &ax, &ay, &dx, &dy);
        f(battlefield, ax, ay, dx, dy);
    }

    print_arr(battlefield, n, m);
    for(uint i = 0; i < n; ++i) {
        for(uint j = 0; j < m; ++j)
            delete[] battlefield[i][j];
        delete[] battlefield[i];
    } delete[] battlefield;

    return 0;
}
//Version 2.0
#include <cstdio>
typedef unsigned int uint;

void print_arr(int *arr, uint n, uint m) {
    for(uint i = 0; i < n; ++i) {
        for(uint j = 0; j < m; ++j)
            printf("%c ", arr[i * m * 2 + j * 2 + 0] == -1 && arr[i * m * 2 + j * 2 + 1] == -1 ? 'X' : 'O');
        printf("\n");
    }
}

void f(int *arr, uint ax, uint ay, uint dx, uint dy, uint n, uint m) {
    if(arr[ax * m * 2 + ay * 2 + 0] > arr[dx * m * 2 + dy * 2 + 1]) 
        arr[dx * m * 2 + dy * 2 + 0] = arr[dx * m * 2 + dy * 2 + 1] = -1;
    else 
        arr[ax * m * 2 + ay * 2 + 0] = arr[ax * m * 2 + ay * 2 + 1] = -1;
}

int main() {
    uint n, m, c, ax, ay, dx, dy;
    scanf("%u%u", &n, &m);

    int *battlefield = new int[n * m * 2];

    for(uint i = 0; i < n; ++i)
        for(uint j = 0; j < m; ++j)
            scanf("%d%d", &battlefield[i * m * 2 + j * 2 + 0], &battlefield[i * m * 2 + j * 2 + 1]);

    scanf("%u", &c);
    for(uint i = 0; i < c; ++i) {
        scanf("%u%u%u%u", &ax, &ay, &dx, &dy);
        f(battlefield, ax, ay, dx, dy, n, m);
    }
    print_arr(battlefield, n, m);

    delete[] battlefield;
    return 0;
}

Zadanie 3

Napisz program w języku C++, który zaalokuje 32 bajtową tablicę, wprowadzi do niej wartości całkowite, a następnie wyświetli elementy tej tablicy jako zmienne typu int.

Rozwiązanie:
#include <iostream>
#include <climits>

int main() {
    char *arr = new char[32];
    int size = 32 / sizeof(int);

    for(int i = 0; i < size; ++i)
        *((int *)arr + i) = INT_MAX - i;

    for(int i = 0; i < size; ++i)
        std::cout << *((int *)arr + i) << " ";
    std::cout << std::endl;

    for(int i = 0; i < 32; ++i)
        std::cout << (int)arr[i] << " ";
    std::cout << std::endl;

    delete[] arr;
    return 0;
}

Zadanie 4

Napisz funkcję w języku C++, która przyjmuje jednowymiarową tablicę liczb zmiennoprzecinkowych. Funkcja powinna zwracać wyznacznik macierzy dla tej tablicy, intepretowanej jako macierzy 3x3. Napisz program w języku C++, który przetestuje działanie tej funkcji.

Rozwiązanie:
#include <iostream>

float det(float *matrix) {
	return matrix[0] * matrix[4] * matrix[8] +  
	       matrix[1] * matrix[5] * matrix[6] +  
	       matrix[2] * matrix[3] * matrix[7] - 
	      (matrix[2] * matrix[4] * matrix[6] +  
	       matrix[0] * matrix[5] * matrix[7] +  
	       matrix[1] * matrix[3] * matrix[8]);
	/*		 
	return matrix[0*3 + 0] * matrix[1*3 + 1] * matrix[2*3 + 2] + 
	       matrix[0*3 + 1] * matrix[1*3 + 2] * matrix[2*3 + 0] +  
	       matrix[0*3 + 2] * matrix[1*3 + 0] * matrix[2*3 + 1] - 
	      (matrix[0*3 + 2] * matrix[1*3 + 1] * matrix[2*3 + 0] +  
	       matrix[0*3 + 0] * matrix[1*3 + 2] * matrix[2*3 + 1] +  
	       matrix[0*3 + 1] * matrix[1*3 + 0] * matrix[2*3 + 2]);
	*/
}

int main() {
	float arr[] = {5, 4, -7, 1, 3, -1, 2, 0, -3};
	std::cout << det(arr) << std::endl;
	return 0;
}

Zadanie 5

Napisz funkcję w języku C++, która przyjmuje jednowymiarową tablicę liczb zmiennoprzecinkowych – matrix, liczbę całkowitą – n, liczbę całkowitą – m i liczbę zmiennoprzecinkową – s. Funkcja powinna zapisać do matrix wynik mnożenia macierzy – matrix, o wymiarach n na m, przez skalar s. Napisz program w języku C++, który przetestuje działanie tej funkcji.

Rozwiązanie:
#include <iostream>

void product_with_scalar(float *matrix, int n, int m, float s) {
    for(int i = 0; i < n * m; ++i) matrix[i] *= s;
}

void print_arr(float *matrix, int n, int m) {
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j)
            std::cout << matrix[i*m + j] << " ";
        std::cout << "\n";
    }
}

int main() {
    float arr[] = {5, 4, -7, 1, 3, -1, 2, 0, -3};
    product_with_scalar(arr, 3, 3, 2.4f);
    print_arr(arr, 3, 3);
    return 0;
}

Zadanie 6

Napisz funkcje w języku C++, które obliczają: a) sumę wektorów, b) różnicę wektorów, c) iloczyn wektora przez skalar, d) iloczyn skalarny wektorów, e) iloczyn wektorowy wektorów w trójwymiarowej przestrzeni euklidesowej. Napisz program w języku C++, który przetestuje działanie tych funkcji.

Rozwiązanie:
#include <iostream>

float *add(float *v1, float *v2) {
    int n = 3;
    for(int i = 0; i < n; ++i) v1[i] += v2[i];
    return v1;
}

float *sub(float *v1, float *v2) {
    int n = 3;
    for(int i = 0; i < n; ++i) v1[i] -= v2[i];
    return v1;
}

float *mul(float *v1, float s) {
    int n = 3;
    for(int i = 0; i < n; ++i) v1[i] *= s;
    return v1;
}

float dot(float *v1, float *v2) {
    int n = 3;
    float temp = 0.f;
    for(int i = 0; i < n; ++i) temp += v1[i] * v2[i];
    return temp;
}

float *cross(float *v1, float *v2) {
    int n = 3;
    float *temp = new float[n];
    temp[0] = v1[1] * v2[2] - v1[2] * v2[1];
    temp[1] = v1[2] * v2[0] - v1[0] * v2[2];
    temp[2] = v1[0] * v2[1] - v1[1] * v2[0];
    for(int i = 0; i < n; ++i) v1[i] = temp[i];
    delete[] temp;
    return v1;
}

void print_vector(float *v) {
    std::cout << v[0] << " " << v[1] << " " << v[2] << std::endl;
}

int main() {
    float s = 3.f, v[3] = {1.1f, 2.2f, 3.3f}, u[3] = {1.f, 2.f, 1.f};
    print_vector(add(v, u));
    print_vector(sub(v, u));
    print_vector(mul(v, s));
    std::cout << dot(v, u) << std::endl;
    print_vector(cross(v, u));
    return 0;
}

Zadanie 7

Napisz funkcję mul w języku C++, która mnoży dwie macierze oraz funkcję print_matrix, która wyświetla macierz. Napisz program w języku C++, który przetestuje działanie tych funkcji.

Rozwiązanie:
#include <iostream>

void mul(float *m1, int r1, int c1, float *m2, int r2, int c2, float *result) {
    for(int i = 0; i < r1; ++i)
        for(int j = 0; j < c2; ++j)
            for(int k = 0; k < c1; ++k)
                result[i * c2 + j] += m1[i * c1 + k] * m2[k * c2 + j];
}

void print_matrix(float *matrix, int n, int m) {
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j)
            std::cout << matrix[i * m + j] << " ";
        std::cout << "\n";
    }
}

int main() {
    float A[] = {1,3,5,7, 2,4,6,8}; //2x4
    float B[] = {1,8,9, 2,7,10, 3,6,11, 4,5,12}; //4x3
    float R[2 * 3]; //2x3
    mul(A, 2, 4, B, 4, 3, R);
    print_matrix(R, 2, 3);
    return 0;
}

Zadanie 8

Napisz program w języku C++, który stworzy tablicę dowolnych liczb całkowitych. Następnie program powinien przekopiować dane z tej tablicy do tablicy tymczasowej temp, przesunąć wszystkie elementy o 2 w lewo (Dwa pierwsze elementy powinny pojawić się na końcu tablicy). (memcpy, memmove)

Rozwiązanie:
#include <cstring>
#include <iostream>

void print_arr(int arr[], int n) {
    for(int i = 0; i < n; ++i) 
        std::cout << arr[i] << " "; 
    std::cout << "\n";
}

int main() {
    const int n = 5;
    int a[n] = {0, 0 ,0 ,0 ,0}, b[n] = {1, 2, 3, 4, 5};

    print_arr(a, n);
    print_arr(b, n);
    memcpy(a, b, n * sizeof(int)); //memcpy(a, b, sizeof b);
    print_arr(a, n);
    print_arr(b, n);
    int tmp1 = a[0], tmp2 = a[1];
    memmove(a, a + 2, (n - 2) * sizeof(int));
    a[n - 2] = tmp1; a[n - 1] = tmp2;
    print_arr(a, n);
    print_arr(b, n);

    return 0;
}
Omówienie:
char a[16];
char b[16];

memcpy(a,b,16);           // poprawne
memmove(a,b,16);          // poprawne ale wolniejsze niż memcpy
memcpy(&a[0], &a[1],10);  // niepoprawne, bo zachodzi na siebie
memmove(&a[0], &a[1],10); // poprawne 

Przygotuj się na kolejne laboratorium!

W celu przygotowania się na kolejne zajęcia, spróbuj wykonać poniższe zadania samodzielnie.

Zadanie 1

Napisz funkcję w języku C++, która dodaje i zwraca wynik sumy dwóch liczb całkowitych przekazanych w argumentach funkcji. Napisz także analogiczną funkcję odejmującą dwie liczby. Napisz program w języku C++, w którym utworzony zostanie odpowiadający tym funkcjom wskaźnik do funkcji. Przypisz temu wskaźnikowi funkcję dodającą i wywołaj ją przez ten wskaźnik. Następnie zrób to samo z funkcją odejmującą.

Zadanie 2

Napisz dwie funkcje w języku C++, zwracającą (1) minimum i (2) maksimum z dwóch liczb całkowitych.

Zadanie 3

Napisz funkcję w języku C++, która liczy i zwraca ekstremum (minimum lub maksimum) liczb z tablicy. Funkcja powinna przyjmować tablicę, jej rozmiar oraz wskaźnik na funkcję liczącą maksimum lub minimum. Wywołaj funkcję dwukrotnie przekazując najpierw wskaźnik na funkcję minimum, a następnie maksimum.

Zadanie 4

Wykorzystaj funkcję qsort do posortowania tablicy liczb całkowitych rosnąco pod względem liczebności cyfry 0 w liczbach.

Zadanie 5

Zmodyfikuj poprzednie rozwiązanie tak, aby wykorzystało funkcję std::sort. Użyj jej zamiast qsort.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *