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ě.
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;
}
}
}
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;
}
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 type ‘int[]’
void fill(int r, int c, int m[][])
^
matrix.c:3:29: note: declaration of ‘m’ as multidimensional array must have bounds for all dimensions except the first
matrix.c: In function ‘fill’: