/** * Soubor: proj3.c * Datum: 28.11.2008 * Autor: Vojtech Kalcik, xkalci01@stud.fit.vutbr.cz * Projekt: Maticove operace, projekt c. 3 pro predmet IZP * Popis: Program provadi operace s maticemi: scitani, soucin, vyraz (A*B) + (A*B), sedlovy bod, pocet spicek, tercova rotace, orba. */ #include #include #include #include const int MIN = 0; //radek, kde ukladam minima const int MAX = 1; //radek, kde ukladam maxima /** * Hlasky programu, ktere se vazi ke stavum programu. */ const char *STAVY[] = { "Vse v poradku.", "Autor: Vojtech Kalcik, xkalci01@stud.fit.vutbr.cz\n" "Projekt: Maticove operace, projekt c. 3 pro predmet IZP\n" "Popis: Program provadi operace s maticemi: scitani, soucin, vyraz (A*B) + (A*B), " "sedlovy bod, pocet spicek, tercova rotace, orba.\n" "\n" "Parametry:\n" " -add soubor1 soubor2 : Secte matice.\n" " -mult soubor1 soubor2 : Vynasobi matice.\n" " -expr soubor1 soubor2 : Spocita vyraz (A*B) + (A*B).\n" " -saddle soubor1 : Najde sedlovy bod.\n" " -peaks soubor1 : Spocita spicky.\n" " -drot soubor1 : Provede tercovou rotaci.\n" " -plough soubor1 : Provede orbu.\n" " -h : Vypise napovedu.\n" "\n" "Soubor1 a soubor2 je cesta k textovemu souboru s matici. V souboru je matice zapsana ve tvaru: prvni cislo-" "pocet radku, druhe cislo-pocet sloupcu a zbytek hodnoty matice. Za matici muze byt libovolny text, ale pred " "nebo vevnitr pouze cisla.", "Chyba v parametrech. Parametrem -h zobrazite napovedu.", "Soubor neexistuje.", "Chyba ve vstupnim souboru.", "Matice nemaji spravne rozmery pro tuto operaci.", "Matice se nepodarila alokovat.", }; /** * Vycet stavu programu. */ enum e_stav { ST_OK = 0, // Vse v poradku ST_NAPOVEDA, // Napoveda ST_SP_PARAMETRY, // Chyba v parametrech ST_SP_SOUBOR, // Soubor neexistuje ST_SP_FORMAT, // Chyba ve vstupnim souboru ST_SP_ROZMERY, // Matice nemaji spravne rozmery pro tuto operaci ST_SP_ALOK, // Nepodarila se alokovat matice }; /** * Vycet operaci. */ enum e_operace { O_SOUCET = 0, // Soucet matic O_SOUCIN, // Soucin matic O_VYRAZ, // Vyraz (A*B) + (A*B) O_SEDLO, // Sedlovy bod O_SPICKY, // Pocet spicek O_TERC, // Tercova rotace O_ORBA, // Orba }; /** * Struktura matice */ typedef struct ma_tice { int **pole; int radky; int sloupce; }Tmatice; /** * Uvolni pamet, tam kde byla alokovana matice */ void uvolni_matici(Tmatice *matice) { for(int i = 0; i < matice->radky; i++) { free(matice->pole[i]); } free(matice->pole); } /** * Alokuje matici */ bool alokuj_matici(Tmatice *matice) { bool zdar = true; matice->pole = malloc(matice->radky*sizeof(int *)); int pocet_alok_rad = 0; if(matice->pole == NULL) { zdar = false; } for(int i = 0;(i < matice->radky)&&(zdar); i++) { matice->pole[i] = malloc(matice->sloupce*sizeof(int)); if(matice->pole[i] == NULL) { zdar = false; pocet_alok_rad = i; } } if(!zdar) { for(int i = 0; i < pocet_alok_rad; i++) { free(matice->pole[i]); } free(matice->pole); } return zdar; } /** * Vypise matici */ void vypis_matici(Tmatice *matice) { printf("%d %d\n", matice->radky, matice->sloupce); for(int i = 0; i < matice->radky; i++) { for(int j = 0; j < matice->sloupce; j++) { printf("%d ", matice->pole[i][j]); } printf("\n"); } } /** * Vynasobi matice */ void soucin_matic(Tmatice *vysledek, Tmatice *matice1, Tmatice *matice2) { for(int i = 0; i < vysledek->radky; i++) { for(int j = 0; j < vysledek->sloupce; j++) { vysledek->pole[i][j] = 0; for(int k = 0; k < matice1->sloupce; k++) { vysledek->pole[i][j] += matice1->pole[i][k] * matice2->pole[k][j]; } } } } /** * Secte matice */ void soucet_matic(Tmatice *vysledek, Tmatice *matice1, Tmatice *matice2) { for(int i = 0; i < vysledek->radky; i++) { for(int j = 0; j < vysledek->sloupce; j++) { vysledek->pole[i][j] = matice1->pole[i][j] + matice2->pole[i][j]; } } } /** * Najde sedlovy bod */ bool najdi_sedlo(Tmatice *pomocna, Tmatice *matice) { int sl_nejvetsi; int sl_nejmensi; bool existuje = false; // najde nejvetsi a nejmensi cislo z radku for(int i = 0; i < matice->sloupce; i++) { for(int j = 0; j < matice->radky; j++) { if(matice->pole[j][i] < matice->pole[pomocna->pole[MIN][i]][i]) { pomocna->pole[MIN][i] = j; } if(matice->pole[j][i] > matice->pole[pomocna->pole[MAX][i]][i]) { pomocna->pole[MAX][i] = j; } } } //porovna nejvetsi a nejmensi bod radku. s nejvetsim a nejmensim bodem sloupce for(int i = 0; (i < matice->radky)&&(!existuje); i++) { sl_nejmensi = 0; sl_nejvetsi = 0; for(int j = 0; j < matice->sloupce; j++) { if(matice->pole[i][j] < matice->pole[i][sl_nejmensi]) { sl_nejmensi = j; } if(matice->pole[i][j] > matice->pole[i][sl_nejvetsi]) { sl_nejvetsi = j; } } //kontroluje jestli nejde o sedlovy bod if((i > 0)&&(i < matice->radky-1)) { if(i == pomocna->pole[MIN][sl_nejvetsi]) { if((sl_nejvetsi > 0)&&(sl_nejvetsi < matice->sloupce-1)) { existuje = true; } } if(i == pomocna->pole[MAX][sl_nejmensi]) { if((sl_nejmensi > 0)&&(sl_nejmensi < matice->sloupce-1)) { existuje = true; } } } } return existuje; } /** * Struktura pro hranu */ typedef struct hra_na { int staticka_souradnice; int roh; }Thrana; /** * Vycet pro pohyby */ enum e_pohyby { VRCH = 0, PRAVO, SPODEK, LEVO, }; /** * Struktura souradnice */ typedef struct sou_radnice { int radek; int sloupec; }Tsouradnice; /** * Najde souradnice z poradevoho cisla v prstenci */ Tsouradnice najdi_souradnici(Thrana *hrany, int cislo, int sirka, int vyska, int pocatek) { Tsouradnice souradnice; if((cislo>=hrany[VRCH].roh)&&(cislo=hrany[PRAVO].roh)&&(cislo=hrany[SPODEK].roh)&&(cislo=hrany[LEVO].roh) { souradnice.radek = pocatek + (vyska - 1) - (cislo - hrany[LEVO].roh); souradnice.sloupec = hrany[LEVO].staticka_souradnice; } return souradnice; } /** * Otoci prstnec */ void otoc_prstenec(Tmatice *matice, Tmatice *vysledek, int pocatek, int sirka, int vyska) { Thrana hrany[4]; hrany[VRCH].staticka_souradnice = pocatek; hrany[VRCH].roh = 0; hrany[PRAVO].staticka_souradnice = pocatek+sirka-1; hrany[PRAVO].roh = sirka-1; hrany[SPODEK].staticka_souradnice = pocatek+vyska-1; hrany[SPODEK].roh = sirka+vyska-2; hrany[LEVO].staticka_souradnice = pocatek; hrany[LEVO].roh = 2*sirka+vyska-3; int pocet_bunek = 2*(sirka-1)+2*(vyska-1); int o_kolik = matice->pole[pocatek][pocatek]; //specialni pripady if(sirka == 1) { pocet_bunek = vyska; hrany[PRAVO].roh = 0; } else if(vyska == 1) { pocet_bunek = sirka; } for(int i=0; ipole[nova.radek][nova.sloupec] = matice->pole[stara.radek][stara.sloupec]; } } /** * Prvede Orbu */ void zorej(Tmatice *vysledek, Tmatice *matice) { int radek = matice->radky-1; int sloupec = matice->sloupce-1; bool nahoru = true; bool naraz = true; for(int i = 0; i < matice->radky; i++) { for(int j = 0; j < matice->sloupce; j++) { vysledek->pole[i][j] = matice->pole[radek][sloupec]; if(naraz) { if((matice->sloupce!=1)&&(matice->radky!=1)) { naraz = false; } if((radek == matice->radky-1)||(radek == 0)) { if(sloupec != 0) { sloupec--; } else { radek--; } } else if((sloupec == matice->sloupce-1)||(sloupec == 0)) { radek--; } } else if(nahoru) { radek--; sloupec++; if((radek==0)||(sloupec==0)||(radek==matice->radky-1)||(sloupec==matice->sloupce-1)) { naraz = true; nahoru = false; } } else { radek++; sloupec--; if((radek==0)||(sloupec==0)||(radek==matice->radky-1)||(sloupec==matice->sloupce-1)) { naraz = true; nahoru = true; } } } } } //----------------------------------------------------------------------------------------- /** * Operace Orba */ int operace_orba(Tmatice *vysledek, Tmatice *matice) { int navrat = ST_OK; vysledek->radky = matice->radky; vysledek->sloupce = matice->sloupce; if(!alokuj_matici(vysledek)) { navrat = ST_SP_ALOK; } if(navrat == ST_OK) { zorej(vysledek, matice); } return navrat; } /** * Operace Tercova rotace */ int operace_terc(Tmatice *matice, Tmatice *vysledek) { int navrat = ST_OK; vysledek->radky = matice->radky; vysledek->sloupce = matice->sloupce; if(!alokuj_matici(vysledek)) { navrat = ST_SP_ALOK; } if(navrat == ST_OK) { int pocet_prstencu, pocatek, sirka, vyska; if(matice->radky < matice->sloupce) { pocet_prstencu = matice->radky / 2; if(matice->radky % 2 == 1) { pocet_prstencu++; } } else { pocet_prstencu = matice->sloupce / 2; if(matice->radky % 2 == 1) { pocet_prstencu++; } } pocatek = 0; sirka = matice->sloupce; vyska = matice->radky; while(pocet_prstencu > 0) { otoc_prstenec(matice, vysledek, pocatek, sirka, vyska); pocatek++; sirka -= 2; vyska -= 2; pocet_prstencu--; } } return navrat; } /** * Operace pocet spicek */ int operace_spicky(Tmatice *matice) { int od_radku, do_radku, od_sloupce, do_sloupce; int pocet = 0; bool je_spicka; for(int i = 0; i < matice->radky; i++) { od_radku = i - 1; if(od_radku < 0) { od_radku = 0; } do_radku = i + 1; if(do_radku > matice->radky-1) { do_radku = matice->radky-1; } for(int j = 0; j < matice->sloupce; j++) { od_sloupce = j - 1; if(od_sloupce < 0) { od_sloupce = 0; } do_sloupce = j + 1; if(do_sloupce > matice->sloupce-1) { do_sloupce = matice->sloupce-1; } je_spicka = true; for(int ii = od_radku; (ii <= do_radku)&&(je_spicka); ii++) { for(int jj = od_sloupce; (jj <= do_sloupce)&&(je_spicka); jj++) { if((ii != i)||(jj != j)) { je_spicka = (matice->pole[i][j] > matice->pole[ii][jj]); } } } if(je_spicka) { pocet++; } } } return pocet; } /** * Operace hledani sedloveho bodu */ int operace_sedlo(Tmatice *matice, bool *je_sedlo) { Tmatice pomocna; int navrat = ST_OK; pomocna.radky = 2; pomocna.sloupce = matice->sloupce; if(!alokuj_matici(&pomocna)) { navrat = ST_SP_ALOK; } if(navrat == ST_OK) { // nastaveni hodnot pomocne matice for(int i = 0; i < pomocna.radky; i++) { for(int j = 0; j < pomocna.sloupce; j++) { pomocna.pole[i][j] = 0; } } *je_sedlo = najdi_sedlo(&pomocna, matice); uvolni_matici(&pomocna); } return navrat; } /** * Operace vyraz (A*B) + (A*B) */ int operace_vyraz(Tmatice *vysledek, Tmatice *matice1, Tmatice *matice2) { int navrat = ST_OK; if(matice1->sloupce == matice2->radky) { vysledek->radky = matice1->radky; vysledek->sloupce = matice2->sloupce; if(!alokuj_matici(vysledek)) { navrat = ST_SP_ALOK; } if(navrat == ST_OK) { soucin_matic(vysledek, matice1, matice2); soucet_matic(vysledek, vysledek, vysledek); } } else { navrat = ST_SP_ROZMERY; } return navrat; } /** * Operace soucin matic */ int operace_soucin(Tmatice *vysledek, Tmatice *matice1, Tmatice *matice2) { int navrat = ST_OK; if(matice1->sloupce == matice2->radky) { vysledek->radky = matice1->radky; vysledek->sloupce = matice2->sloupce; if(!alokuj_matici(vysledek)) { navrat = ST_SP_ALOK; } if(navrat == ST_OK) { soucin_matic(vysledek, matice1, matice2); } } else { navrat = ST_SP_ROZMERY; } return navrat; } /** * Operace soucet matic */ int operace_soucet(Tmatice *vysledek, Tmatice *matice1, Tmatice *matice2) { int navrat = ST_OK; if((matice1->radky == matice2->radky)&&(matice1->sloupce == matice2->sloupce)) { vysledek->radky = matice1->radky; vysledek->sloupce = matice1->sloupce; if(!alokuj_matici(vysledek)) { navrat = ST_SP_ALOK; } if(navrat == ST_OK) { soucet_matic(vysledek, matice1, matice2); } } else { navrat = ST_SP_ROZMERY; } return navrat; } /** * Nacte matici ze souboru */ int nacti_matici(FILE *soubor, Tmatice *matice) { matice->radky = 0; matice->sloupce = 0; int navrat = ST_OK; int je_cislo = 0; int cislo; if((je_cislo = fscanf(soubor, "%d", &cislo)) != EOF) { if(je_cislo != 0) { if(cislo > 0) { matice->radky = cislo; } else { navrat = ST_SP_FORMAT; } if((je_cislo = fscanf(soubor, "%d", &cislo)) != EOF) { if(cislo > 0) { matice->sloupce = cislo; } else { navrat = ST_SP_FORMAT; } } } else { navrat = ST_SP_FORMAT; } } if(je_cislo != 0) { if(!alokuj_matici(matice)) { navrat = ST_SP_ALOK; } // nacitani matice ze souboru for(int i = 0; (i < matice->radky)&&(navrat == ST_OK); i++) { for(int j = 0; (j < matice->sloupce)&&(navrat == ST_OK); j++) { if((je_cislo = fscanf(soubor, "%d", &cislo)) != EOF) { if(je_cislo != 0) { matice->pole[i][j] = cislo; } else { navrat = ST_SP_FORMAT; } } else { navrat = ST_SP_FORMAT; } } } //pokud je pole alokovane, ale nenacetlo se je nutne ho uvolnit if(navrat == ST_SP_FORMAT) { uvolni_matici(matice); } } else { navrat = ST_SP_FORMAT; } return navrat; } /** * Vypsani chybove hlasky nebo napovedy. */ void vypis_hlasku(int stav, int soubor) { FILE *vystup = stdout; if(stav > ST_NAPOVEDA) { vystup = stderr; } if(soubor == 0) { fprintf(vystup, "%s\n", STAVY[stav]); } else { fprintf(vystup, "%s (%d. soubor)\n", STAVY[stav], soubor); } } /** * Struktura, kterou navracĂ­ funkce zpracuj_parametry. */ typedef struct parametry { int co_delat; int stav; FILE *soubor1; FILE *soubor2; }Tparametry; /** * Zpracovani parametru */ Tparametry zpracuj_parametry(int argc, char *argv[]) { Tparametry navrat = { .stav = ST_OK, .soubor1 = NULL, .soubor2 = NULL, }; if(argc == 2) { if(strcmp(argv[1], "-h") == 0) { navrat.stav = ST_NAPOVEDA; } else { navrat.stav = ST_SP_PARAMETRY; } } else if(argc >= 3) { navrat.soubor1 = fopen(argv[2],"r"); if(navrat.soubor1 == NULL) { navrat.stav = ST_SP_SOUBOR; } if(argc >= 4) { navrat.soubor2 = fopen(argv[3],"r"); if(navrat.soubor2 == NULL) { navrat.stav = ST_SP_SOUBOR; } if(strcmp(argv[1], "-add") == 0) { navrat.co_delat = O_SOUCET; } else if(strcmp(argv[1], "-mult") == 0) { navrat.co_delat = O_SOUCIN; } else if(strcmp(argv[1], "-expr") == 0) { navrat.co_delat = O_VYRAZ; } else { navrat.stav = ST_SP_PARAMETRY; } } else if(argc == 3) { if(strcmp(argv[1], "-saddle") == 0) { navrat.co_delat = O_SEDLO; } else if(strcmp(argv[1], "-peaks") == 0) { navrat.co_delat = O_SPICKY; } else if(strcmp(argv[1], "-drot") == 0) { navrat.co_delat = O_TERC; } else if(strcmp(argv[1], "-plough") == 0) { navrat.co_delat = O_ORBA; } else { navrat.stav = ST_SP_PARAMETRY; } } } else { navrat.stav = ST_SP_PARAMETRY; } return navrat; } /** * Zpracovava paramtr co_delat */ bool pracuj(Tparametry parametry) { Tmatice matice1; Tmatice matice2; Tmatice vysledek; int stav1 = ST_OK; int stav2 = ST_OK; int kterej_soubor = 0; int stav_operace = ST_OK; bool zdar = true; //nacteni matic ze souboru stav1 = nacti_matici(parametry.soubor1, &matice1); if(parametry.soubor2 != NULL) { stav2 = nacti_matici(parametry.soubor2, &matice2); } if((stav1 == ST_OK) && (stav2 == ST_OK)) { //zjisteni operace a jeji provedeni. if(parametry.co_delat == O_SOUCET) { stav_operace = operace_soucet(&vysledek, &matice1, &matice2); } else if(parametry.co_delat == O_SOUCIN) { stav_operace = operace_soucin(&vysledek, &matice1, &matice2); } else if(parametry.co_delat == O_VYRAZ) { stav_operace = operace_vyraz(&vysledek, &matice1, &matice2); } else if(parametry.co_delat == O_SEDLO) { bool existuje; stav_operace = operace_sedlo(&matice1, &existuje); if(existuje) { printf("true\n"); } else { printf("false\n"); } } else if(parametry.co_delat == O_SPICKY) { int pocet = operace_spicky(&matice1); printf("%d\n", pocet); } else if(parametry.co_delat == O_TERC) { operace_terc(&matice1, &vysledek); } else if(parametry.co_delat == O_ORBA) { stav_operace = operace_orba(&vysledek, &matice1); } // uvolneni uvolni_matici(&matice1); if(parametry.soubor2 != NULL) { uvolni_matici(&matice2); } if(stav_operace == ST_OK) { if((parametry.co_delat != O_SEDLO)&&(parametry.co_delat != O_SPICKY)) { vypis_matici(&vysledek); uvolni_matici(&vysledek); } } else { parametry.stav = stav_operace; vypis_hlasku(parametry.stav, kterej_soubor); zdar = false; } } else { if(stav1 == ST_SP_FORMAT) { kterej_soubor = 1; } else if(stav2 == ST_SP_FORMAT) { kterej_soubor = 2; } if(stav1 != ST_OK) { parametry.stav = stav1; } else { parametry.stav = stav2; } vypis_hlasku(parametry.stav, kterej_soubor); zdar = false; } return zdar; } /** *Hlavni program */ int main(int argc, char *argv[]) { Tparametry parametry = zpracuj_parametry(argc, argv); if(parametry.stav == ST_OK) { if(pracuj(parametry)) { return EXIT_SUCCESS; } else { return EXIT_FAILURE; } } else { vypis_hlasku(parametry.stav, 0); if(parametry.stav == ST_NAPOVEDA) { return EXIT_SUCCESS; } else { return EXIT_FAILURE; } } }