Kurs podstawy programowania UMCS, zdjęcie laptopa.

PP – Laboratorium 11

Wejściówka

Napisz program w języku C++, który za pomocą wskaźnika do funkcji wywoła funkcję f. Funkcja f powinna przyjmować dwa argumenty typu całkowitego oraz zwracać wynik operacji sqrt(a * b / 3).

Rozwiązanie:
#include <cmath>

float f(int a, int b) {
	return sqrt(a * b / 3.f);
}

int main() {
    float (*fun)(int, int);
    fun = f;
	fun(10, 10);
    return 0;
}

Zadanie 1

Napisz program w języku C++, który zmienia kolejność elementów w posortowanej tablicy liczb całkowitych, w następujący sposób:
– pierwszym elementem powinna być maksymalna wartość,
– drugim elementem powinna być minimalna wartość,
– trzecim elementem powinna być druga maksymalna wartość,
– czwartym elementem powinna być druga minimalna wartość,
i tak dalej.

Rozwiązanie:
#include <iostream>

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

void rearrange_max_min(int arr[], int n) {
    int *temp = new int[n];
    int min_idx = 0, max_idx = n - 1;
    for(int i = 0; i < n; ++i) {
        if(!(i % 2)) temp[i] = arr[max_idx--];
        else temp[i] = arr[min_idx++];
    }
    for(int i = 0; i < n; ++i) arr[i] = temp[i];
    delete[] temp;
}

int main() {
    int nums[] = {0, 1, 3, 4, 5, 6, 7, 8, 10};
    int n = sizeof(nums) / sizeof(nums[0]);
    rearrange_max_min(nums, n);
    print_arr(nums, n);
    return 0;
}

Zadanie 2

Napisz funkcję w języku C++, która przyjmuje następujące argumenty: wskaźnik na tablicę liczb całkowitych – arr, liczbę całkowitą będącą rozmiarem tej tablicy – n, liczbę całkowitą – k oraz wskaźnik na tablicę liczb całkowitych – result. Funkcja powinna wprowadzić do tablicy result k największych elementów z nieposortowanej tablicy arr przekazanej w argumencie. Funkcja nie powinna modyfikować oryginalnej tablicy. Napisz program w języku C++, który przetestuje działanie tej funkcji.

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

bool compare(const int &a, const int &b) {
    return a > b;
}

void top_k_elements(int *arr, int n, int k, int *result) {
    int *cpy = new int[n];

    memcpy(cpy, arr, n * sizeof(arr[0]));
    std::sort(cpy, cpy + n, compare);
    memcpy(result, cpy, k * sizeof(cpy[0]));

    delete[] cpy;
}

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

int main() {
    int nums[] = {4, 5, 9, 12, 9, 22, 45, 7};
    int n = sizeof(nums) / sizeof(nums[0]), k = 3;
    int *result = new int[k];

    top_k_elements(nums, n, k, result);
    print_arr(result, k);

    delete[] result;
    result = nullptr;
    return 0;
}

Zadanie 3

Napisz program w języku C++, który wczyta od użytkownika liczbę, jako napis. Liczba powinna mieć co najwyżej 10 znaków. Następnie program powinien zwiększyć tą liczbę o 0.123 i ją wyświetlić.

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

int main() {
    char dig[11] = {0};
    std::cin >> dig;
    char *p;
    float f = strtod(dig, &p);
    if(p > dig) 
        std::cout << f + 0.123f << "\n";
    else 
        std::cout << " Konwersja się nie udała.\n";
    return 0;
}

Zadanie 4

Napisz funkcję w języku C++, która znajduje element pojawiający się w tablicy tylko raz, gdy inne elementy pojawiają się dwukrotnie. Funkcja w argumencie powinna przyjąć wskaźnik na tablicę liczb całkowitych oraz rozmiar tej tablicy. Napisz program w języku C++, który przetestuje działanie tej funkcji.

Rozwiązanie:
#include <iostream>

int search_single_element(int *arr, int n) {
    int result = arr[0];
    for (int i = 1; i < n; ++i) 
        result ^= arr[i];
    return result;
}


int main() {
    int array[] = {3, 1, 5, 1, 5, 7, 9, 7, 9};
    int n = sizeof(array) / sizeof(array[0]);
    std::cout << search_single_element(array, n) << std::endl;
    return 0;
}

Zadanie 5

Wykorzystując wskaźniki na funkcje napisz program w języku C++, który w zależności od wywołania funkcji f wykona dodawanie lub odejmowanie dwóch macierzy kwadratowych. Spróbuj użyć wskaźników na funkcję tak, aby powtórzyć jak najmniej kodu w zaproponowanej implementacji (zasada DRY). Dodatkowo funkcja f powinna wyświetlić wynik wybranej operacji. Wynik operacji na macierzach powinien być zapisany do pierwszej tablicy. Operacje na tablicach powinny być przeprowadzone za pomocą arytmetyki wskaźników.

Rozwiązanie:
#include <iostream>

typedef int (*p_fun)(int, int);

int add(int a, int b) {
    return a + b;
}

int sub(int a, int b) {
    return a - b;
}

void print_matrix(int *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";
    }
}

void f(int *a, int *b, int n, p_fun fun) {
    for(int i = 0; i < n; ++i)
        for(int j = 0; j < n; ++j)
            *(a + i * n + j) = fun(*(a + i * n + j), *(b + i * n + j));
    print_matrix(a, n, n);
}

int main() {
    int arr1[]={1, 2, 3, 5, 15, 0, 12, 13, 5};
    int arr2[]={1, 2, 3, 5, 15, 0, 12, 13, 5};
    f(arr1, arr2, 3, add);
    f(arr1, arr2, 3, sub);
    f(arr1, arr2, 3, sub);
    return 0;
}

Zadanie 6

Zdefiniuj funkcję f w języku C++, która w argumencie przyjmuje nieujemną liczbę całkowitą n, tablicę liczb całkowitych arr oraz wskaźnik na liczbę zmiennoprzecinkową result. Funkcja powinna zwrócić, za pomocą argumentu result, wynik następującej sumy:
f(n) = Σ(0<=a<=n) (x*(x-a))
gdzie dla arr[a] podzielnego przez 5 x = a3 lub x = sqrt(a) w przeciwnym razie. Napisz program, który sprawdzi działanie tej funkcji. Program powinien wczytać ze standardowego wejścia nieujemną liczbę całkowitą n, zaalokować pamięć, wypełnić ją losowymi wartościami z przedziału <0;15> i wyświetlić na standardowym wyjściu wynik funkcji f.

Rozwiązanie:
#include <iostream>
#include <cmath>
#include <cstdlib>
#include <ctime>

const int MIN = 0;
const int MAX = 15;

void fill_arr(int *arr, unsigned int n) {
    for(unsigned int i = 0; i < n; ++i) 
        arr[i] = MIN + rand() / (RAND_MAX / (MAX - MIN + 1));
}

void f(unsigned int n, int *arr, float *result) {
    *result = 0.f;
    float x = 0.f;
    for(unsigned int a = 0; a <= n; ++a) {
        x = !(arr[a] % 5) ? pow(a, 3) : sqrt(a);
        *result += x * (x - a);
    }
}

int main() {
    srand(time(0));
    unsigned int n;
    std::cin >> n;
    float r = 0.f;
    int *arr = new int[n + 1];
    fill_arr(arr, n + 1);
    f(n, arr, &r);
    std::cout << r << std::endl;
    delete[] arr;
    return 0;
}

Zadanie 7

Zaprojektuj i zdefiniuj funkcję transpose w języku C++, która w parametrze przyjmie macierz liczb zmiennoprzecinkowych o wielkości n x n. Zadaniem tej funkcji będzie wykonanie transpozycji tej macierzy. Forma reprezentacji macierzy oraz sposób jej przekazania do funkcji i zwrócenia wartości do samodzielnego określenia. W funkcji głównej pokaż użycie tej funkcji. Macierz transponowana macierzy A to macierz AT, która powstaje poprzez zamianę jej wierszy na kolumny i kolumn na wiersze. Napisz program w języku C++, który przetestuje działanie tej funkcji, dynamicznie zaalokuje pamięć dla dwuwymiarowej macierzy i wypełni ją dowolnymi wartościami.

Rozwiązanie:
#include <iostream>

void fill_matrix(float **arr, int n, int m) {
    for(int i = 0; i < n; ++i)
        for(int j = 0; j < m; ++j) 
            arr[i][j] = i * m + j;
}

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

void transpose(float **mat, int n, int m) {
    for(int i = 0; i < n; ++i)
        for(int j = i + 1; j < m; ++j)
            std::swap(mat[i][j], mat[j][i]);
}

int main() {
    int n = 4;
    float **arr = new float*[n];
    for(int i = 0; i < n; ++i) 
        arr[i] = new float[n];
    
    fill_matrix(arr, n, n);
    print_matrix(arr, n, n);
    transpose(arr, n, n);
    print_matrix(arr, n, n);
    
	for(int i = 0; i < n; ++i) 
	    delete[] arr[i]; 
	delete[] arr;
    return 0;
}

Zadanie 8

Napisz funkcję w języku C++, która przyjmuje wskaźnik na void oraz liczbę całkowitą ptrsize. ptrsize jest liczbą bajtów, która reprezentuje zmienną. Funkcja powinna odpowiednio zrzutować zmienną na typ char lub int, a następnie zwiększyć jej wartość o jeden. Napisz program w języku C++, który sprawdzi działanie tej funkcji dla obu tych typów.

Rozwiązanie:
#include <iostream>

void increase(void *data, int ptrsize) {
    if(ptrsize == sizeof(char)) {
        char *ptrchar;
        ptrchar = (char*)data;
        (*ptrchar)++;
    } else if(ptrsize == sizeof(int)) {
        int *ptrint;
        ptrint = (int*)data;
        (*ptrint)++;
    }
}

int main()  {
    char c = 'x';
    int i = 10;
    increase(&c, sizeof(c));
    std::cout << c <<"\n";
    increase(&i, sizeof(i));
    std::cout << i <<"\n";
    return 0;
}

Zadanie 9

Napisz funkcję w języku C++, który znajdzie najmniejszy i drugi najmniejszy element w dowolnej tablicy liczb całkowitych. Wartość najmniejszego i drugiego najmniejszego elementu powinny zostać zwrócone za pomocą argumentów funkcji. Do operowania na tablicy użyj arytmetyki wskaźników. Napisz program w języku C++, który przetestuje działanie tej funkcji.

Rozwiązanie:
#include <iostream>

void find(int *array, int n, int &s, int &ss) {
    if(*array < *(array + 1)) {
        s = *array;
        ss = *(array + 1);
    } else {
        s = *(array + 1);
        ss = *array;
    }

    for(int i = 0; i < n; ++i) {
        if (s > *(array + i)) {
            ss = s;
            s = *(array + i);
        } else if (*(array + i) < ss) {
            ss = *(array + i);
        }
    }
}

int main() {
    int s, ss, array[7] = {5, 6, 7, 2, 3, 4, 12};
    find(array, 7, s, ss);
    std::cout << s << " " << ss << "\n";
    return 0;
}

Zadanie 10

Napisz program w języku C++, który zaalokuje pamięć dla dwóch 10-elementowych tablic liczb całkowitych: a i b. Następnie program powinien wczytać od użytkownika wartość całkowitą x i wypełnić nią tablicę a, zaś tablica b powinna być uzupełniona wartością x, powiększoną o 2. Na koniec program powinien wyświetlić obie tablice, zaimplementowane rozwiązanie nie powinno używać pętli.

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

int op_increase(int i) {
    return i + 2;
}

void print_elem(int i) {
    std::cout << i << " ";
}

int main() {
    int x, *a = new int[10], *b = new int[10];
    std::cin >> x;
    std::fill(a, a + 10, x);
    std::transform(a, a + 10, b, op_increase);
    std::for_each(a, a + 10, print_elem);
    std::cout << std::endl;
    std::for_each(b, b + 10, print_elem);
    std::cout << std::endl;     
    delete[] a;
    delete[] b;
    a = b = nullptr;
    return 0;
}

Zadanie 11

Zaprojektuj funkcję w języku C++, która dla wprowadzonej tablicy liczb rzeczywistych znajdzie podaną w argumencie wartość. Funkcja powinna zwrócić do niej wskaźnik, lub wskaźnik na NULL, jeśli nie znajdzie jej w tablicy. Zaimplementowane rozwiązanie nie powinno wykorzystywać pętli.

Rozwiązanie:
#include <algorithm>

float *f(float *arr, int n, float x) {
	float *p = std::find(arr, arr + n, x);
	if(p != arr + n) return p;
	else return nullptr;
}

Zadanie 12

Napisz dwie funkcje w języku C++ condition i action. Funkcja condition powinna przyjąć liczbę całkowitą i zwrócić wartość logiczną. Funkcja action powinna przyjmować referencję na liczbę całkowitą i nic nie zwracać. Funkcja condition ma sprawdzać, czy w liczbie powtarza się którakolwiek cyfra. Funkcja action powinna odwrócić kolejność cyfr w tej liczbie. Napisz funkcję modify_array, która przyjmie tablicę liczb całkowitych, jej rozmiar oraz dwa wskaźniki na funkcje o nagłówkach takich jak condition i action. Dla każdego elementu tablicy spełniającego warunek condition należy wywołać funkcję action.

Rozwiązanie:
#include <iostream>

void action(int &value) {
    int result = 0;
    do {
        result *= 10;
        result += value % 10;
    } while(value /= 10);
    value = result;
}

bool condition(int value) {
    int tmp[10] = {};
    do {
        ++tmp[value % 10];
        if(tmp[value % 10] > 1) return true;
    } while(value /= 10);
    return false;
}

void modify_array(int arr[], int n, bool (*cond)(int), void (*act)(int&)) {
    for(int i = 0; i < n; ++i) if(cond(arr[i])) act(arr[i]);
}

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

int main() {
    const int n = 5;
    int arr[n] = {1142, 123, 3243, 1543, 15443};
    print_arr(arr, n);
    modify_array(arr, n, condition, action);
    print_arr(arr, n);
    return 0;
}

Zadanie 13

Napisz funkcję w języku C++, do użycia jako komparator w funkcji qsort, która pozwoli posortować napisy rosnąco względem ich ostatnich znaków. Jeżeli ostatnie znaki są jednakowe, należy porównać przedostatnie itd.

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

unsigned int str_len(const char *str) {
    unsigned int len = 0;
    while(*(str + ++len));
    return len;
}

int str_cmp(const void *a, const void *b) {
    char c0, c1;
    const char* str_0 = (const char*)a;
    const char* str_1 = (const char*)b;
    unsigned int i = 0, n = str_len(str_0), m = str_len(str_1);
    unsigned int min_len = n < m ? n : m;
    
    for(int i = 1; i <= min_len; ++i) {
        c0 = str_0[n - i];
        c1 = str_1[m - i];
        if(c0 != c1) return c0 - c1;
    }
    return n - m;
}

void print_arr(const char arr[][100], int n) {
    for(int i = 0; i < n; ++i)
        std::cout << arr[i] << std::endl;
    std::cout << std::endl;
}

int main() {
    char arr[5][100] = {
        "limE",
        "alA",
        "keicaM",
        "nadgoB",
        "test"
    };
    print_arr(arr, 5);
    str_cmp(arr[0], arr[1]);
    qsort(arr, 5, 100, str_cmp);
    print_arr(arr, 5);
    return 0;
}

Zadanie 14

Napisz program w języku C++, który podzieli podany string na tokeny (fragmenty napisu) rozdzielone podanym znakiem. Zbierz wszystkie tokeny do tablicy string-ów i następnie wyświetl je na ekranie. Do wykonania zadania można użyć funkcji strtok() z pliku <cstring>.

PRZYKŁAD:
char str[] = "ala;ma kota;i;dwa psy"
char delimeter = ';'
tokeny: "ala", "ma kota", "i", "dwa psy"

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

int main() {
    char str[100] = "ala;ma kota;i;dwa psy", delimeter = ';';
    char* tokens[100];
    int num_tokens = 0;

    char* token = strtok(str, &delimeter);
    while (token != nullptr) {
        tokens[num_tokens] = token;
        num_tokens++;
        token = strtok(nullptr, &delimeter);
    }

    for (int i = 0; i < num_tokens; ++i) std::cout << tokens[i] << "\n";
    return 0;
}

Zadanie 15

W języku C++ napisz funkcję search_string(), która przyjmie tablicę napisów, jej rozmiar oraz wskaźnik na funkcję pf odpowiedniej postaci. Funkcja search_string() powinna zwrócić wskaźnik na napis, dla którego funkcja f wykorzystująca funkcje pf zwróci największą wartość. Zdefiniuj funkcję search_string() tak, aby jako funkcja pf mogła być wywołana funkcja biblioteczna strpbrk z <cstring>, której jako drugi argument zostanie przekazany napis złożony z samogłosek. Funkcja f powinna zwracać ilość samogłosek w przetwarzanym napisie.

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


unsigned int f(const char *str, char *(*pf)(const char *, const char *)) {
    unsigned int result = 0;
    const char *tmp = str;
    while(tmp) {
        tmp = pf(tmp, "aeiouy");
        if(tmp) ++result;
        else return result;
        tmp += 1;
    }
    return result;
}

const char *search_string(const char *arr[], int n, char *(*pf)(const char *, const char *)) {
    unsigned int tmp = 0, max = f(arr[0], pf);
    const char *result = arr[0];
    for(int i = 1; i < n; ++i) {
        tmp = f(arr[i], pf);
        if(tmp > max) {
            max = tmp;
            result = arr[i];
        }
    }
    return result;
}

int main() {
    const char *arr[5] = {
        "emil",
        "ala",
        "maciek",
        "bogdan",
        "test"
    };
    std::cout << search_string(arr, 5, strpbrk) << std::endl;
    return 0;
}

Dodaj komentarz

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