Skip to content

Instantly share code, notes, and snippets.

@TrinityCoder
Last active January 26, 2017 06:53
Show Gist options
  • Save TrinityCoder/a80d51358da5f6347c51a6972549c9ff to your computer and use it in GitHub Desktop.
Save TrinityCoder/a80d51358da5f6347c51a6972549c9ff to your computer and use it in GitHub Desktop.
Ukázkové příklady v C

Všechny následující programy kompilovat např. pomocí:

gcc -std=c99 -Wall -Werror -pedantic -g -o main main.c

(pokud jste kód zkopírovali do souboru jménem main.c).


Úloha 15. (oprava funkce print + vylepšení funkce add_to_data). Přidal jsem navíc funkci main + trochu omáčky na začátek, aby šel kód ihned spustit a byla vidět jeho funkčnost.

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

char* user_get_name() {
    static char* jmeno = "Mirek Mares";
    return jmeno;
}

double user_get_value() {
    return 69.69;
}

typedef struct mydata_t {
    char* name;
    double value;
    int label;
} mydata_t;

void print(struct mydata_t* data) {
    if(data == NULL)
        return;
    printf("Data: '%s', label=%d, value=%lf\n",
                        data->name,
                        data->label,
                        data->value);
}

struct mydata_t* add_to_data(struct mydata_t* data, int n)
{
    struct mydata_t* ret = NULL;
    printf("Data before add... \n");

    // Najdeme nejvetsi label v poli:
    int label = 0;
    for(int i = 0; i < n; ++i)
    {
        if((data + i)->label > label)
        {
            label = (data + i)->label;
        }
        print(data + i);
    }

    // Pokusime se zvetsit pole 'data' o 1, pokud selze, vratime puvodni ukazatel.
    ret = realloc(data, (n + 1)*sizeof(struct mydata_t));
    if(ret == NULL) {
        return data;
    }

    // Nastavime nove pridane prvku pole 'data' hodnoty, jake ma mit podle zadani.
    char* name = user_get_name();
    double value = user_get_value();

    ret[n].name = name;
    ret[n].value = value;
    ret[n].label = label + 1;

    return ret;
}

int main(void) {
    int n = 2;
    struct mydata_t* data = malloc(sizeof(struct mydata_t) * 2);

    data[0].name = "AAA";
    data[0].value = 1.0;
    data[0].label = 10;

    data[1].name = "BBB";
    data[1].value = 2.0;
    data[1].label = 20;

    for(int i = 0; i < 5; ++i)
    {
        data = add_to_data(data, n++);
    }

    free(data);

    return 0;
}

Jednoduchá implementace způsobu, jak lze do stringu načíst obsah libovolně dlouhého textového souboru, aniž bychom se museli obávat, že překročíme paměť, kterou máme alokovanou.

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

int main(int argc, char** argv) {
         if(argc < 2) {
              return 1;
         }

         char* retezec = malloc(1000 * sizeof(char));
         int size = 0;
         int capacity = 1000;

         FILE* f = fopen(argv[1], "r");

         char tmp;
         while(fscanf(f, "%c", &tmp) == 1) {
             if(size + 1 >= capacity) {
                 retezec = realloc(retezec, 2 * capacity);
                 capacity *= 2;
             }
             retezec[size++] = tmp;
         }
         retezec[size] = '\0';

         printf("%s", retezec);

         fclose(f);
         free(retezec);

         return 0;
}

Úloha 13. - opravte signaturu (hlavičku) funkce, která bere matici jako argument a vyplní ji náhodnými celými čísly od 0 do 9 včetně.

Zadaná funkce (s chybou)

Toto je definice funkce ze zadání (tj. obsahující nějakou chybu, kterou máme opravit):

void fill(int r, int c, int m[][])
{
     for(int i = 0; i < r; ++i)
     {
          for(int j = 0; j < c; ++j)
          {
               m[i][j] = rand() % 10;
          }
     }
}

Jak se bude funkce volat?

V zadání je i ukázková funkce main, aby bylo jasné, jak se bude funkce fill v praxi volat.

int main(void)
{
     int r = 4;
     int c = 4;
     int m[r][c];
     fill(r, c, m);
     return 0;
}

Kde je chyba?

Při práci s poli je zásadní tento fakt: Bude-li funkce přebírat jako argument obecně nějaké n-rozměrné pole, tak je potřeba v signatuře funkce specifikovat všechny rozměry (kromě úplně prvního, který je vždy volitelný).

To znamená, že hlavičku funkce je možné opravit dvěma různými způsoby - a oba jsou zcela správné:

// Varianta m[][c]:
void fill(int r, int c, int m[][c])
{
     for(int i = 0; i < r; ++i)
     {
          for(int j = 0; j < c; ++j)
          {
               m[i][j] = rand() % 10;
          }
     }
}
// Varianta m[r][c]
void fill(int r, int c, int m[r][c])
{
     for(int i = 0; i < r; ++i)
     {
          for(int j = 0; j < c; ++j)
          {
               m[i][j] = rand() % 10;
          }
     }
}

A toto je ukázka zkompilovatelného programu (funkce fill zde používá m[][c] a přidal jsem funkci print_matrix, která naopak pro názornost používá m[r][c]; též jsem přidal volání funkce srand(time(NULL)), které je potřeba provést - bez něj lze spouštět program pořád dokola a výstup bude vždy stejný):

#include <stdio.h>
#include <stdlib.h>  // pro rand(), srand()
#include <time.h>   // pro time()

void fill(int r, int c, int m[][c])
{
     for(int i = 0; i < r; ++i)
     {
          for(int j = 0; j < c; ++j)
          {
               m[i][j] = rand() % 10;
          }
     }
}

void print_matrix(int r, int c, int m[r][c]);

int main(void)
{
     srand(time(NULL));
     int r = 4;
     int c = 4;
     int m[r][c];
     fill(r, c, m);
     print_matrix(r, c, m);
     return 0;
}

void print_matrix(int r, int c, int m[r][c])
{
     for(int i = 0; i < r; ++i)
     {
          for(int j = 0; j < c; ++j)
          {
               printf("%d ", m[i][j]);
          }
          printf("\n");
     }
}

Mimochodem, kdybyste v signatuře přeci jen nechali m[][], tak vás na to gcc upozorní touto mimořádně krásnou hláškou:

matrix.c:3:29: error: array type has incomplete element typeint[]’
 void fill(int r, int c, int m[][])
                             ^
matrix.c:3:29: note: declaration ofmas multidimensional array must have bounds for all dimensions except the first
matrix.c: In function ‘fill’:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment