Programming C

Tasks studies - laboratory


Project maintained by dawidolko Hosted on GitHub Pages — Theme by dawidolko

Lab03 - Functions, pointers, scope of variables

Examples

Functions

#include <stdio.h>

// before the name of the function we provide the type it should return
// Functions can have many arguments of different types
int function_name(int argument1, int argument2){
// Function body - set of instructions
int result = argument1 + argument2;
return result; // return terminates the function and returns the result.
}

// the function may not accept arguments and may not return a value
void hello(){
printf("Hello World!\n");
// return; // It is possible to interrupt the function using return without a value
}

int main(int argc, char const *argv[])
{
hello();
int result = function_name(4,2); // function is called by specifying the function name and its arguments in ()
printf("%i",result);
return 0;
}

Functions with unlimited number of arguments.

#include <stdio.h>
#include <stdarg.h> // A library is required in which the used functions va_start, va_end are declared

int sum(int argc, ...){ // in argc stores the number of arguments
va_list arg; // special type for storing arguments
va_start(arg, argc); // start reading
for (int i = 0; i<argc; i++) { // va_arg(arg, int) reads arguments of a given type
printf("%i\n",va_arg(arg,int));
}
va_end(arg); // end reading
return 1;
}

int main(int argc, char const *argv[])
{
suma(4, 1,2,3,5);
return 0;
}

Pointers

Defining pointer variables

#include <stdio.h>
int main(int argc, char const *argv[])
{
int *ptr; // declaration of a variable that stores an address in memory. (pointer)

char a = 'a';

printf("Value stored by variable a: %c\n", a);

// Using the &variable_name operator, you can read the address of a cell in memory.
// !The address is in hexadecimal format, you must use the appropriate type of printf() function to print it correctly.
printf("Value of variable a is located at address: %p\n", &a);

ptr = &a; // Assigning the address of variable a to a pointer variable

printf("Value of variable a is located at address: %p \n", ptr);
// To read the value located at a given address, we use the dereference operator "*"
printf("Value stored at the address stored by pointer %c\n", *ptr);

// Changing the value using a pointer
*ptr = 'b';
printf("New value of variable a: %c",a);

return 0;
}

:warning: When defining pointers, watch out for the assignment operation:

int a = 55;

int *ptr_a = &a;
int a = 55;

int *ptr_a;
*ptr_a = &a; // this way you will change the value at a given address.

Arrays

Array variables point to the first address in the array.

#include <stdio.h>

int main(int argc, char const *argv[])
{
char tab[20];

char *ptr_tab = tab;
printf("Address of the first element of the array (tab[0]): %p\n", *ptr_tab);
printf("Value: (tab[0]): %c\n", tab[0]);
printf("Value using a pointer: (tab[0]): %c\n", *ptr_tab);
/* code */
return 0;
}

Iterating an array using pointers

#include <stdio.h>

int main(int argc, char const *argv[])
{
const int TAB_SIZE = 20;
char tab[20] = "abcdefghijklmnoprst";

// char *ptr_tab = tab - initialization of the pointer and assigning it the address of the first element of the array
// the limiting condition *ptr_tab does not need a comparison operator because if we hit the end of the array we will get the value 0 (false)
// the loop counter increase condition increases the counter to the next address in memory
for (char *ptr_tab = tab; *ptr_tab; ptr_tab++)
{
printf("Value: %c \n", *ptr_tab);
}
return 0;
}

Tasks

Task 1 - task1.exe and task1.c

(Copy the code from the second lab where you had to print out your data and the data of two people next to you. Using the function, optimize the code so that it takes up as few lines of code as possible.)

Write a function show() that takes a first and last name and then prints them to the console. Call the function, giving your data and the data of two people next to you as arguments.

Write a function sum() that returns the sum of three numbers given as function arguments.

Task 2 - task2.exe and task2.c

Create and test the function max_tab() which takes a 10-element array of integers as an argument and then returns the largest element of the array.

Task 3 - task3.exe and task3.c

Create and test the function mean() which takes a 10-element array of integers as an argument and then returns the average of the array.

Task 4 - stats.exe and stats.c

Using the documentation of the string.h library, create and test the stats() function that takes as an argument a 10-element array of integers and a string of characters that, depending on the stored variable, will cause the function to return a different value:

Task 5 - task5.exe and task5.c

Create a function mystdev() that can take a different number of floating point parameters and returns the average of the arguments. Modify the function to return the standard deviation (read the documentation of the math.h library and find the appropriate functions) of the passed arguments according to the formula:

\[\sigma = \sqrt{\frac{1}{N}\sum_{n=1}^{N}(x_i - \overline{x})^2}\]

where

\[\overline{x}=\frac{1}{N}\sum_{i=1}^{N}x_i\]

Task 6

Create an array of letters from a to z. Using pointers, print the letter f.

Task 7 - task7.exe and task7.c

Create an array of letters from a to z. Create a loop in which you use pointers to print every nth element (defined by the user) of this array starting from ‘c’.

Task 8 - swap.exe and swap.c

Write a function swap() that accepts pointers to two float variables. The function swaps the values ​​of these variables.

Additional examples

Finding a pointer to a number in an array.

The task is to find a pointer to an element in the 2nd row and the 3rd column and then change the value of this element.

#include <stdio.h>
#include <stdlib.h>
#define N 321

void printtab(int tab[3][3])
{
    printf("Tablica:\n");
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            printf("%i ", tab[i][j]);
        }
        printf("\n");
    }
}

int main(int argc, char const *argv[])
{
    int asd[3][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}};

    int *wskfor6;
    for (int *ptr_tab = asd; *ptr_tab; ptr_tab++)
    {
        if (*ptr_tab == 6)
        {
            wskfor6 = ptr_tab;
            printf("%p\n", ptr_tab);
            break;
        }
    }

    printtab(asd);

    *wskfor6 = 999;

    printtab(asd);

    return 0;
}

lub


#include <stdio.h>
#include <stdlib.h>
#define N 321

void printtab(int tab[3][3])
{
    printf("Tablica:\n");
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            printf("%i ", tab[i][j]);
        }
        printf("\n");
    }
}

int main(int argc, char const *argv[])
{
    int asd[3][3] = {
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9}};

    int *wskfor6;

    wskfor6 = &asd[1][2];

    printtab(asd);

    *wskfor6 = 99;

    printtab(asd);

    return 0;
}

Funkcje redukują ilość kodu.

#include <stdio.h>
#include <stdlib.h>

// zmienna globalna
int asd = 10;

void show(int x)
{
    for (int i = 0; i < x; i++)
    {
        printf("%i ", i);
    }
    printf("\n");
}

int main(int argc, char const *argv[])
{
    show(10);
    show(20);
    show(30);


    // bez użycia funkcji kod mógł wyglądać następująco:
    for (int i = 0; i < 10; i++)
    {
        printf("%i ", i);
    }
    printf("\n");

    for (int i = 0; i < 20; i++)
    {
        printf("%i ", i);
    }
    printf("\n");

    for (int i = 0; i < 30; i++)
    {
        printf("%i ", i);
    }
    printf("\n");

    printf("Wartosc zmiennej globalnej %i",asd);
    return 0;
}

###


#include <stdio.h>
#include <stdlib.h>

int max_tab(int tab[])
{
    printf("Tablica tab ma wielkosc - %i elementy\n", sizeof(tab));
    int max_elem = tab[0];
    for (size_t i = 0; i < sizeof(tab); i++)
    {
        if (max_elem < tab[i])
        {
            max_elem = tab[i];
        }
    }
    return max_elem;
}

int main(int argc, char const *argv[])
{
    int x[] = {1, 23, 4, 6};
    int b = max_tab(x);
    printf("Maksymalny element w tablicy x to %i", b);
    return 0;
}

Task 5

#include <stdio.h>
#include <stdarg.h> // Wymagana jest biblioteka w której zadeklarowane są użyte funkcje va_start, va_end
#include <math.h>

double odchstd(int argc, ...){ // w argc przechowuje liczbę argumentów
    va_list arg; // specjalny typ do przechowywania argumentów
    va_start(arg, argc); // rozpoczęcie odczytu

    //  stała która będzie przechowywać rozmiar tablicy równy ilości argumentów.
    const int N = argc;
    // inicjalizazcja tablicy zdolnej przechować N argumentów
    double tab[N];

    // Odczytuje kolejne elementy i dodaje do tablicy.
    for (int i = 0; i<argc; i++) { // va_arg(arg, int) odczytuje argumenty danego typu
        tab[i] = va_arg(arg,double);
    }
    va_end(arg); // zakończenie odczytu

    // obliczenie średniej
    double srednia = 0;
    for(int j = 0; j< argc; j++){
        srednia += tab[j];
    }
    srednia = srednia/argc;

    // obliczenie odchylenia
    double odchstd = 0;
    for (int i = 0; i < argc; i++)
    {
        double roznica = tab[i] - srednia;
        odchstd += roznica*roznica;
    }
    odchstd = odchstd/argc;
    odchstd = sqrt(odchstd);

    return odchstd;
}

int main(int argc, char const *argv[])
{
    double wynik = odchstd(4, 1.0, 2.0, 3.0, 4.0);
    printf("odchylenie standardowe wynosi: %lf", wynik);
    return 0;
}

Task 7

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char const *argv[])
{
    // utworzenie tablicy z literami od a do z (na 27 znaków poeniważ ostatni element będzie wskazywać na symbol pusty \0 - koniec łańcucha znaków)
    char tab[27];
    int x = 97;
    for (size_t i = 0; i < 26; i++)
    {
        tab[i] = x;
        x = x+1 ;
    }
    printf("%s", tab);

    printf("co ktory element wypisac:");
    int n;
    scanf("%i", &n);
    // Jeśli zinkrementujemy wskaźnik o 2 dostaniemy wskaźnik na 3 element tablicy
    // zwiększając wskaźnik ptr_tab o n przegapimy znak \0 zatem w pętli należy przeskakiwać co nty krok
    int counter = n-1;
    for (char *ptr_tab = tab+2; *ptr_tab; ptr_tab++)
    {
        // Zwiększamy licznik iteracji o 1
        counter++;
        // Jeśli mamy już n-ta literę wypisujemy informacje i zerujemy licznik
        if (counter == n)
        {
            printf("Wartosc: %c \n", *ptr_tab);
            counter = 0;
        }
    }

    return 0;
}

swap

#include <stdio.h>

// z użyciem dodatkowej zmiennej
void swap(float *a, float*b){
    // ustawiam zmienna pomocniczą w której przechowam wartość a
    float temp = *a;
    // zapisuje pod adresem przechowywanym przez a wartość zmiennej spod adresu b
    *a = *b;
    // zapisuje pod adresem przechowywanym przez b wartość zmiennej a przechowywanej w temp
    *b = temp;
}

// bez dodatkowej zmiennej
void swap2(float *a, float*b){
    *a = *a + *b;
    *b = *a - *b;
    *a = *a - *b;
}


int main(int argc, char const *argv[])
{
    float a = 4.0;
    float b = 9.0;

    swap(&a, &b);

    printf("dzialanie swap a = %f b=%f\n", a,b);

    swap2(&a,&b);
    printf("dzialanie swap2 a = %f b=%f", a,b);
    return 0;
}