Přednáška http://efis.tul.cz/~dana.nejedlova/ Základy programování, Programování I a II Přednáška z jazyka C Přednesen zbytek témat. Zápočtový test. Požadavky na program ke zkoušce. Cvičení Tabulka řetězců s prvky vypisovanými indexem. Vstupní data jsou v textovém souboru. Program zjistí počet řádků a sloupků. Program alokuje dynamicky matici a vektory nadpisů řádků a sloupků pointerů na řetězce. Program načte data do matice a vektorů. Program vypíše nabídků sloupců a uživatel zadá číslo sloupce. Program vypíše nabídků řádků a uživatel zadá číslo řádku. Funkce pro čtení čísla jsou ze souboru 12.txt. Program vypíše řetězec na zadadém řádku a sloupku. #include #include #include #include #define SOUBOR "Tabulka.txt" #define DELKA_BUFFERU 1024 #define SEPARATORY ";\t\n" int zjisti_pocet_radku(char *nazev_souboru) { FILE *fr; char buffer_radku[DELKA_BUFFERU]; int i = 0; if ((fr = fopen(nazev_souboru, "r")) == NULL) { printf("Soubor %s se nepodarilo otevrit.\n", nazev_souboru); exit(1); } while (fgets(buffer_radku, DELKA_BUFFERU, fr) != NULL) { i++; } if (fclose(fr) == EOF) { printf("Soubor %s se nepodarilo uzavrit.\n", nazev_souboru); exit(1); } i--; /* Radek pro nadpis se nezapocita. */ printf("Soubor %s ma %d radku.\n", nazev_souboru, i); return i; } int zjisti_pocet_sloupku(char *nazev_souboru) { FILE *fr; char buffer_radku[DELKA_BUFFERU]; char *cislo_string; int i = 0; if ((fr = fopen(nazev_souboru, "r")) == NULL) { printf("Soubor %s se nepodarilo otevrit.\n", nazev_souboru); exit(1); } if (fgets(buffer_radku, DELKA_BUFFERU, fr) != NULL) { cislo_string = strtok(buffer_radku, SEPARATORY); if (cislo_string != NULL) { i++; } while ((cislo_string = strtok(NULL, SEPARATORY)) != NULL) { i++; } } if (fclose(fr) == EOF) { printf("Soubor %s se nepodarilo uzavrit.\n", nazev_souboru); exit(1); } printf("Soubor %s ma %d sloupku.\n", nazev_souboru, i); return i; } void vytvor_vektor_retezcu(char ***x, int r) { if ((*x = (char **) malloc(r * sizeof(char *))) == NULL) { printf("Malo pameti!\n"); exit(1); } } void vytvor_matici_retezcu(char ****x, char ***p_x, int r, int s) { int i; if ((*p_x = (char **) malloc(r * s * sizeof(char *))) == NULL) { printf("Malo pameti!\n"); exit(1); } if ((*x = (char ***) malloc(r * sizeof(char **))) == NULL) { printf("Malo pameti!\n"); exit(1); } for (i = 0; i < r; i++) { (*x)[i] = *p_x + i * s; } } void zrus_vektor(void **x) { free((void *) *x); *x = NULL; } void zrus_matici(void **x, void **p_x) { free(*p_x); *p_x = NULL; free(*x); *x = NULL; } int nacti_data(char *nazev_souboru, int s, char **nadpis_radku, char **nadpis_sloupku, char ***matice) { FILE *fr; char buffer_radku[DELKA_BUFFERU]; char *cislo_string; int i, j; if ((fr = fopen(nazev_souboru, "r")) == NULL) { printf("Soubor %s se nepodarilo otevrit.\n", nazev_souboru); exit(1); } j = 0; if (fgets(buffer_radku, DELKA_BUFFERU, fr) != NULL) { cislo_string = strtok(buffer_radku, SEPARATORY); if (cislo_string != NULL) { nadpis_sloupku[j] = (char *) calloc(strlen(cislo_string) + 1, sizeof(char)); strcpy(nadpis_sloupku[j++], cislo_string); } while ((cislo_string = strtok(NULL, SEPARATORY)) != NULL) { nadpis_sloupku[j] = (char *) calloc(strlen(cislo_string) + 1, sizeof(char)); strcpy(nadpis_sloupku[j++], cislo_string); } } i = 0; while (fgets(buffer_radku, DELKA_BUFFERU, fr) != NULL) { cislo_string = strtok(buffer_radku, SEPARATORY); if (cislo_string != NULL) { nadpis_radku[i] = (char *) calloc(strlen(cislo_string) + 1, sizeof(char)); strcpy(nadpis_radku[i++], cislo_string); } j = 0; while ((cislo_string = strtok(NULL, SEPARATORY)) != NULL) { if (j == s) { printf("Nadbytecna polozka v radku %d.", i + 1); return 1; } matice[i - 1][j] = (char *) calloc(strlen(cislo_string) + 1, sizeof(char)); strcpy(matice[i - 1][j++], cislo_string); } if (j < s) { printf("Chybi polozka v radku %d.", i + 1); return 1; } } if (fclose(fr) == EOF) { printf("Soubor %s se nepodarilo uzavrit.\n", nazev_souboru); exit(1); } return 0; } void vypis_pole_retezcu(int r, char **x) { int i; for (i = 0; i < r; i++) { printf("%d %s\n", i + 1, x[i]); } } int zadej_cele_cislo(char *prompt) { int cislo; printf(prompt); while (scanf("%d", &cislo) != 1) { printf("Zadali jste cislo spatne.\n"); printf("Zadejte cislo znovu: "); while (getchar() != '\n') ; } while (getchar() != '\n') ; return cislo; } int zadej_cislo_v_intervalu(char *prompt, int min, int max) { int cislo; printf(prompt, min, max); while ((cislo = zadej_cele_cislo("")) < min || cislo > max) { printf("Zadali jste cislo mimo interval.\n"); printf(prompt, min, max); } return cislo; } int main() { int radky, sloupky, radek, sloupek; char ***matice, **p_matice, **nadpis_radku, **nadpis_sloupku; bool pokracovat; if ((radky = zjisti_pocet_radku(SOUBOR)) < 1) { return 1; } if ((sloupky = zjisti_pocet_sloupku(SOUBOR)) < 1) { return 1; } vytvor_vektor_retezcu(&nadpis_radku, radky); vytvor_vektor_retezcu(&nadpis_sloupku, sloupky); vytvor_matici_retezcu(&matice, &p_matice, radky, sloupky); if (nacti_data(SOUBOR, sloupky, nadpis_radku, nadpis_sloupku, matice) == 1) { return 1; } do { vypis_pole_retezcu(sloupky, nadpis_sloupku); sloupek = zadej_cislo_v_intervalu("Zadejte sloupec jako cele cislo od %d do %d: ", 1, sloupky); vypis_pole_retezcu(radky, nadpis_radku); radek = zadej_cislo_v_intervalu("Zadejte radek jako cele cislo od %d do %d: ", 1, radky); printf("%s\n", matice[radek - 1][sloupek - 1]); pokracovat = zadej_cele_cislo("Pro ukonceni programu zadejte 0: "); } while (pokracovat); zrus_vektor((void **) &nadpis_radku); zrus_vektor((void **) &nadpis_sloupku); zrus_matici((void **) &matice, (void **) &p_matice); printf("%p %p %p %p\n", nadpis_radku, nadpis_sloupku, matice, p_matice); /* Overeni, ze byly spravne vynulovany pointery */ printf("Hello world!\n"); return 0; } Třídění pole řetězců podle délky. Řetězec je ve struktuře spolu s jeho délkou dynamicky. Vstupní data jsou v souboru. Soubor se přečte poprvé pro zjištění počtu řetězců. Data se čtou po druhém otevření souboru do dynamicky alokovaných řetězců. #include #include #include #define SOUBOR_VSTUP "RezezceVstup.txt" #define SOUBOR_VYSTUP "RezezceVystup.txt" #define DELKA_BUFFERU 1024 typedef struct { int delka; char *retezec; } RETEZEC; int sort_up_retezec(const void *p_a, const void *p_b) { return ((RETEZEC *) p_a)->delka - ((RETEZEC *) p_b)->delka; } void nacti_retezce(char *nazev_souboru, RETEZEC *pole_retezcu) { FILE *fr; char buffer_radku[DELKA_BUFFERU]; int i = 0; if ((fr = fopen(nazev_souboru, "r")) == NULL) { printf("Soubor %s se nepodarilo otevrit.\n", nazev_souboru); exit(1); } while (fgets(buffer_radku, DELKA_BUFFERU, fr) != NULL) { pole_retezcu[i].retezec = (char *) calloc(strlen(buffer_radku) + 1, sizeof(char)); strcpy(pole_retezcu[i].retezec, buffer_radku); pole_retezcu[i++].delka = strlen(buffer_radku); } if (fclose(fr) == EOF) { printf("Soubor %s se nepodarilo uzavrit.\n", nazev_souboru); exit(1); } } void zapis_retezce(char *nazev_souboru, RETEZEC *pole_retezcu, int pocet) { FILE *fw; int i; if ((fw = fopen(nazev_souboru, "w")) == NULL) { printf("Soubor %s se nepodarilo otevrit.\n", nazev_souboru); exit(1); } for (i = 0; i < pocet; i++) { fprintf(fw, pole_retezcu[i].retezec); } if (fclose(fw) == EOF) { printf("Soubor %s se nepodarilo uzavrit.\n", nazev_souboru); exit(1); } printf("Byl vytvoren soubor %s a bylo do nej zapsano %d retezcu.\n", nazev_souboru, i); } int zjisti_pocet_radku(char *nazev_souboru) { FILE *fr; char buffer_radku[DELKA_BUFFERU]; int i = 0; if ((fr = fopen(nazev_souboru, "r")) == NULL) { printf("Soubor %s se nepodarilo otevrit.\n", nazev_souboru); exit(1); } while (fgets(buffer_radku, DELKA_BUFFERU, fr) != NULL) { i++; } if (fclose(fr) == EOF) { printf("Soubor %s se nepodarilo uzavrit.\n", nazev_souboru); exit(1); } printf("Soubor %s ma %d radku.\n", nazev_souboru, i); return i; } void vytvor_vektor(RETEZEC **x, int pocet) { if ((*x = (RETEZEC *) malloc(pocet * sizeof(RETEZEC))) == NULL) { printf("Malo pameti!\n"); exit(1); } } void zrus_vektor(void **x) { free((void *) *x); *x = NULL; } int main() { RETEZEC *pole_retezcu; int pocet_retezcu; pocet_retezcu = zjisti_pocet_radku(SOUBOR_VSTUP); vytvor_vektor(&pole_retezcu, pocet_retezcu); nacti_retezce(SOUBOR_VSTUP, pole_retezcu); qsort((void *) pole_retezcu, pocet_retezcu, sizeof(RETEZEC), sort_up_retezec); zapis_retezce(SOUBOR_VYSTUP, pole_retezcu, pocet_retezcu); zrus_vektor((void **) &pole_retezcu); printf("Hello world!\n"); return 0; } Řetězec je ve struktuře spolu s jeho délkou staticky. Počet řetězců je dán konstantou POCET_RETEZCU. Řetězce jsou omezeny konstantou MAX_DELKA_RETEZCE. Generuje se náhodná délka řetězce a náhodné znaky z intervalu A-Z, viz soubor 6.txt. Třídění je uplatněno na pole pointerů na prvky pole a potom na pole přímo a je vypsána doba trvání třídění. #include #include #include #include #define SOUBOR_VYSTUP1 "RezezceVystup1.txt" #define SOUBOR_VYSTUP2 "RezezceVystup2.txt" #define MAX_POCET_RETEZCU_PRO_ZAPIS 10 #define POCET_RETEZCU 1000000 #define MAX_DELKA_RETEZCE 1000 #define ROZSAH_KODU_ZNAKU (1 + 'Z' - 'A') typedef struct { int delka; char retezec[MAX_DELKA_RETEZCE + 1]; } RETEZEC; int sort_up_pointery(const void *p_a, const void *p_b) { return (*(RETEZEC **) p_a)->delka - (*(RETEZEC **) p_b)->delka; } int sort_up_retezec(const void *p_a, const void *p_b) { return ((RETEZEC *) p_a)->delka - ((RETEZEC *) p_b)->delka; } void generuj_retezce(RETEZEC *pole_retezcu, int pocet) { int i, j; printf("Generuji retezce.\n"); for (i = 0; i < pocet; i++) { pole_retezcu[i].delka = rand() % MAX_DELKA_RETEZCE + 1; for (j = 0; j < pole_retezcu[i].delka; j++) { pole_retezcu[i].retezec[j] = 'A' + rand() % ROZSAH_KODU_ZNAKU; } pole_retezcu[i].retezec[j] = '\0'; } } void zapis_retezce(char *nazev_souboru, RETEZEC *pole, int pocet) { FILE *fw; int i; if ((fw = fopen(nazev_souboru, "w")) == NULL) { printf("Soubor %s se nepodarilo otevrit.\n", nazev_souboru); exit(1); } for (i = 0; i < pocet; i++) { fprintf(fw, "%s\n", pole[i].retezec); } if (fclose(fw) == EOF) { printf("Soubor %s se nepodarilo uzavrit.\n", nazev_souboru); exit(1); } printf("Byl vytvoren soubor %s a bylo do nej zapsano %d retezcu.\n", nazev_souboru, i); } void zapis_retezce_pomoci_pointeru(char *nazev_souboru, RETEZEC **pole, int pocet) { FILE *fw; int i; if ((fw = fopen(nazev_souboru, "w")) == NULL) { printf("Soubor %s se nepodarilo otevrit.\n", nazev_souboru); exit(1); } for (i = 0; i < pocet; i++) { fprintf(fw, "%s\n", pole[i]->retezec); } if (fclose(fw) == EOF) { printf("Soubor %s se nepodarilo uzavrit.\n", nazev_souboru); exit(1); } printf("Byl vytvoren soubor %s a bylo do nej zapsano %d retezcu.\n", nazev_souboru, i); } void vytvor_vektor(RETEZEC **x, int pocet) { if ((*x = (RETEZEC *) malloc(pocet * sizeof(RETEZEC))) == NULL) { printf("Malo pameti!\n"); exit(1); } } void vytvor_vektor_pointeru_na_prvky_pole(RETEZEC ***x, RETEZEC *pole, int pocet) { int i; if ((*x = (RETEZEC **) malloc(pocet * sizeof(RETEZEC *))) == NULL) { printf("Malo pameti!\n"); exit(1); } for (i = 0; i < pocet; i++) { (*x)[i] = &pole[i]; } } void zrus_vektor(void **x) { free((void *) *x); *x = NULL; } int main() { RETEZEC *pole_retezcu; /* Staticky retezec "RETEZEC pole_retezcu[POCET_RETEZCU];" se do zasobniku nevejde, kdyz jsou velke konstanty POCET_RETEZCU a MAX_DELKA_RETEZCE. */ RETEZEC **vektor_pointeru_na_prvky_pole; time_t sec_z, sec_k; srand((unsigned int) time(NULL)); vytvor_vektor(&pole_retezcu, POCET_RETEZCU); vytvor_vektor_pointeru_na_prvky_pole(&vektor_pointeru_na_prvky_pole, pole_retezcu, POCET_RETEZCU); generuj_retezce(pole_retezcu, POCET_RETEZCU); time(&sec_z); qsort((void *) vektor_pointeru_na_prvky_pole, POCET_RETEZCU, sizeof(RETEZEC *), sort_up_pointery); time(&sec_k); printf("Pocet sekund trideni pole pointeru: %g.\n", difftime(sec_k, sec_z)); if (POCET_RETEZCU <= MAX_POCET_RETEZCU_PRO_ZAPIS) { zapis_retezce_pomoci_pointeru(SOUBOR_VYSTUP1, vektor_pointeru_na_prvky_pole, POCET_RETEZCU); } time(&sec_z); qsort((void *) pole_retezcu, POCET_RETEZCU, sizeof(RETEZEC), sort_up_retezec); time(&sec_k); printf("Pocet sekund trideni pole primo: %g.\n", difftime(sec_k, sec_z)); if (POCET_RETEZCU <= MAX_POCET_RETEZCU_PRO_ZAPIS) { zapis_retezce(SOUBOR_VYSTUP2, pole_retezcu, POCET_RETEZCU); } zrus_vektor((void **) &vektor_pointeru_na_prvky_pole); printf("Hello world!\n"); return 0; }