====== Převod čísel ====== #include #include #include #include const char rimsky[]={'I','V','X','L','C','D','M','S','Q'}; char *in=NULL; unsigned int readLine(char **pLine, unsigned int *N, FILE *stream); //arabsky na rimsky char ar(void) { unsigned int len; unsigned int delka = readLine(&in, &len, stdin); if (delka==1) { fprintf(stderr,"CHYBA: Nic nezadano!\n"); free(in); return EXIT_FAILURE; } short nuly=0; //nejdriv zjistime jestli je zadane cislo, a je ve spravnem rozsahu... for (short pozice_v_cisle=delka; pozice_v_cisle>1; pozice_v_cisle--) { char cislice=in[delka-pozice_v_cisle]; //potrebujem to brat odzadu (jinak dostanem EOF a je to v ...) //kontrola jestli bylo zadano cislo if (cislice<'0' || cislice>'9') { fprintf(stderr,"CHYBA: Spatne zadani (%c neni cislice)!\n", cislice); //trosku paradoxni pojmenovani promenne :) free(in); return EXIT_FAILURE; } //kontrola jestli nebyla zadana nula if (cislice=='0') { nuly++; if (nuly==delka-1) { fprintf(stderr,"CHYBA: Spatne zadani (0)!\n"); free(in); return EXIT_FAILURE; } } } //...a teprve potom zacnem neco resit for (short pozice_v_cisle=delka; pozice_v_cisle>1; pozice_v_cisle--) { char cislice=in[delka-pozice_v_cisle]; short pozice_v_poli=(pozice_v_cisle-2)*2; //cerna magie, ale funguje :) if (cislice>'3' && pozice_v_poli+1>8) { fprintf(stderr,"CHYBA: Spatne zadani (overflow)!\n"); free(in); return EXIT_FAILURE; } //pokud je vstup mensi jak 4 (a vetsi jak 0) if (cislice<'4' && cislice>'0') { for (short i=cislice; i>'0'; i--){ printf("%c",rimsky[pozice_v_poli]); //napis tolikrat I } } //kdyz je 4 (tak trosku vyjimka) if (cislice=='4') printf("%c%c",rimsky[pozice_v_poli],rimsky[pozice_v_poli+1]); //kdyz je vstup v rozsahu 5--8 if (cislice>'4' && cislice<'9') { printf("%c",rimsky[pozice_v_poli+1]); for (short i=cislice-5; i>'0'; i--) { printf("%c",rimsky[pozice_v_poli]); } } //kdyz je vstup 9 (dalsi "vyjimka") if (cislice=='9') printf("%c%c",rimsky[pozice_v_poli],rimsky[pozice_v_poli+2]); } printf("\n"); // http://www.lamer.cz/quotes/show/12 free(in); return EXIT_SUCCESS; } //rimsky na arabsky char ra(void) { unsigned int len; unsigned int delka = readLine(&in, &len, stdin); if (delka==1) { fprintf(stderr,"CHYBA: Nic nezadano!\n"); free(in); return EXIT_FAILURE; } short last=SHRT_MAX; //zaloz promennou pro predchozi short arab=0; //soucet vsech cisel je zatim 0 short hodnota=0; //na pocatku nebylo nic for (short i=0; i=3 && in[i]==in[i-3] && in[i-1]==in[i-2] && in[i]==in[i-1]) { //pokud jde vice jak 3 stejne znaky za sebou (treba IIII) fprintf(stderr,"CHYBA: Spatne zadani! (IIII)\n"); free(in); return EXIT_FAILURE; } if (hodnota>last) { //pokud se odecita if (hodnota/last!=10 && hodnota/last!=5) { //dosel jsem ke zjisteni, ze pokazde kdyz ma byt odcitani platne, tak podil tech zadanych cisel je 5 nebo 10... tim se osetri chyby jako IC nebo IMM... velky dik za toto zjisteni patri me pritelkyni, ktery me k teto myslence inspirovala. :) fprintf(stderr,"CHYBA: Spatne zadani! (IMM)\n"); free(in); return EXIT_FAILURE; } if (i>=2 && in[i-1]==in[i-2]) { //osetreni proti IIV a podobnym fprintf(stderr,"CHYBA: Spatne zadani! (IIV)\n"); free(in); return EXIT_FAILURE; } if (i>=1 && in[i-1]==in[i+1]) { //osetreni proti IVI a podobnym fprintf(stderr,"CHYBA: Spatne zadani! (IVI)\n"); free(in); return EXIT_FAILURE; } arab+=hodnota-2*last; } else arab+=hodnota; last=hodnota; } if (arab<0) { fprintf(stderr,"CHYBA: Spatne zadani (overflow)!\n"); free(in); return EXIT_FAILURE; } printf ("%d\n",arab); free(in); return EXIT_SUCCESS; } int main(int argc, char *argv[]) { if (argc == 1 || (argc == 2 && strcmp("-h", argv[1]) == 0)) printf("Sepsal a v hlavni rohli sehral xkalab00\n\n-ar Prevod z arabskych na rimska cisla\n-ra Prevod z rimskych na arabska cisla\n-aa Prevod z arabskych na arabska cisla (kontrola zapisu)\n-rr Prevod z rimskych na rimska cisla (kontrola zapisu)\n"); if (argc == 2 && strcmp("-ar", argv[1])==0) ar(); if (argc == 2 && strcmp("-ra", argv[1])==0) ra(); if (argc == 2 && strcmp("-aa", argv[1])==0) { fprintf(stderr,"CHYBA: Neimplementovana operace!\n"); return EXIT_FAILURE; } if (argc == 2 && strcmp("-rr", argv[1])==0) { fprintf(stderr,"CHYBA: Neimplementovana operace!\n"); return EXIT_FAILURE; } return EXIT_SUCCESS; } // Martinkovy bloky kodu inline void testAlloc(void *ptr) { if (ptr == NULL) { // vypise na standardni chybovy vystup chybovou hlasku. fprintf(stderr, "CHYBA: Nedostatek pameti!\n"); exit(EXIT_FAILURE); } } // testAlloc() unsigned int readLine(char **pLine, unsigned int *N, FILE *stream) { const int B_INCREMENT = 16; int blockSize = *N; if (*pLine == NULL) { // uzivatel nic nealokoval blockSize = B_INCREMENT; *pLine = malloc(blockSize*sizeof(char)); testAlloc(*pLine); } int c; int i = 0; while ((c = getc(stream)) != EOF && c != '\n') { (*pLine)[i] = c; i += 1; if ((i % blockSize) == 0) { // pokud je na konci bloku, je potreba jej natahnout blockSize += B_INCREMENT; *pLine = realloc(*pLine, blockSize); testAlloc(*pLine); } } // Pozor! Pole predavane odkazem se musi indexovat takto. Bez zavorky // bychom indexovali pole ukazatelu, protoze operator * ma nizsi prioritu // nez []. (*pLine)[i] = '\0'; // na zaver je potreba retezec spravne ukoncit *N = blockSize; return i+1; // vraci delku retezce }