Problem z sprawdzeniem poprawności zapisu

0

Mój program ma w założeniu zamienić liczbę rzymska na arabską. Program działa, lecz np. w momencie wpisania IIII wyskakuje że to jest 4 choć nie m takiej liczby. To samo jak się wpisze IC, choć nie ma takiej liczby on ją przelicza. Jak napisać funkcję/pętlę/cokolwiek co sprawdzi poprawność wprowadzonej liczby i ewentualnie poinformuje o błędzie? Program zaczerpnięty z internetu. Potrzebuje go w pełni działającego na zaliczenie, z programowania jestem noga, i nigdy nie będę programistą, ale swoje muszę przejść.

 
char rzymska[24];

void RzymToArab(char* zawartosc)

{
  int wynik = 0;
  for(int i = 0; i <= 24; i++)
  {
    if(zawartosc[i] == 'I' && zawartosc[i+1] == 'V')
    {
        wynik+=4;
        i++;
    }
    else if(zawartosc[i] == 'I' && zawartosc[i+1] == 'X')
    {
        wynik+=9;
        i++;
    }
    else if(zawartosc[i] == 'X' && zawartosc[i+1] == 'L')
    {
        wynik+=40;
        i++;
    }
    else if(zawartosc[i] == 'X' && zawartosc[i+1] == 'C')
    {
        wynik+=90;
        i++;
    }    
    else if(zawartosc[i] == 'C' && zawartosc[i+1] == 'D')
    {
        wynik+=400;
        i++;
    }
    else if(zawartosc[i] == 'C' && zawartosc[i+1] == 'M')
    {
        wynik+=900;
        i++;
    }        
    else if(zawartosc[i] == 'I')
    {
        wynik++;
    }
    else if(zawartosc[i] == 'V')
    {
        wynik+=5;
    }
    else if(zawartosc[i] == 'X')
    {
        wynik+=10;
    }
    else if(zawartosc[i] == 'L')
    {
        wynik+=50;
    }
    else if(zawartosc[i] == 'C')
    {
        wynik+=100;
    }
    else if(zawartosc[i] == 'D')
    {
        wynik+=500;
    }    
    else if(zawartosc[i] == 'M')
    {
        wynik+=1000;
    }
    else if(!(zawartosc[i]))
    {
        break;
    }
  }
  cout << wynik << endl;
}

int main()
{

		cout << "Podaj cyfre rzymska, ktora chcesz zamienic na arabska: \n\n";
		cin >> rzymska;
		cout<<"\nTa cyfra w zapisie arabskim to: \n\n";
		RzymToArab(rzymska);
		cout<<"\n"<<endl;
		system("PAUSE");        
	        return 0;

}


0

Napiszę ci kilka błędów które zauważyłem:

  • tablicę rzymska sprawdzasz od 0 do 24, gdzie powinieneś od 0 do 22(1. tablica ma 24 elementy, od 0 do 23; 2. musi być jeszcze jeden znak dla '/0' - końca cstring'u)
  • tablicę rzymska mógłbyś zadeklarować w main, potem tylko ją i jej wielkość przekazać do RzymArab(), a nie globalizować(nie wiem czy jest takie słowo)
  • zmień ostatni warunek w RzymArab() - po prostu usuń if'a i zostaw else break;.
0

Postanowiłem napisać taki kod ponieważ

  • Warto poćwiczyć proste algorytmy bo to się może przydać na co dzień
  • Dawno nic merytorycznie nie pisałem
  • Zawsze warto komuś pomóc

W czasie pisania wynikły jednak pewne problemy, związane z tym że rzymski sposób zapisywania liczb jest dość nieprecyzyjnie zdefiniowany, jakich dokładnie zasad chcesz przestrzegać?

Moje założenia:

  1. Symbole I (1), V (5), X (10), L (50), C (100), D (500), M (1000)
  2. Rangi I: 0, V: 1, X: 2, L: 3, C: 4, D: 5, M: 6
  3. Symbole w prawidłowej liczbie są uporządkowane od największej rangi do najmniejszej (za wyjątkiem wyjątków w 4)
  4. Jeżeli po symbolu o parzystej randze x następuje symbol y mający rangę większą o 1 lub 2, wartość takiego dwuznaku wynosi y - x
  5. Maksymalna ilość powtórzeń tego samego symbolu wynosi 3 dla symboli o parzystej randze i 1 dla reszty

Przetestowane dla paru przykładów, ale ofc jakieś błędy (albo nieścisłości w założeniach) mogą być. Sprawdź sam:

/*
 *  ZASADY KONWERSJI:
 * 1) Dozwolone symbole: I (1), V (5), X (10), L (50), C (100), D (500), M (1000)
 * 2) Rangi: I: 0, V: 1, X: 2, L: 3, C: 4, D: 5, M: 6
 * 3) Symbole w prawidłowej liczbie są uporządkowane od największej 
 *   rangi do najmniejszej (oprócz wyjątków w 4)
 * 4) Jeżeli po symbolu o parzystej randze x następuje symbol y mający
 *   rangę większą o 1 lub 2, wartość takiego dwuznaku wynosi y - x
 * 5) Maksymalna ilość powtórzeń tego samego symbolu wynosi 3 dla 
 *   symboli o parzystej randze i 1 dla reszty
 */

const int rankValues[] =
{
    1,   // I
    5,   // V
    10,  // X
    50,  // L
    100, // C
    500, // D
    1000 // M
};

int getSymbolRank(char symbol) 
{
    if (symbol == 'I') { return 0; }
    if (symbol == 'V') { return 1; }
    if (symbol == 'X') { return 2; }
    if (symbol == 'L') { return 3; }
    if (symbol == 'C') { return 4; }
    if (symbol == 'D') { return 5; }
    if (symbol == 'M') { return 6; }
    return -1;
}

int convert(char *text, int *result)
{
    int totalValue = 0;
    char lastChar = '\0';
    int repetitions = 0;

    while(*text)
    {
        int currRank = getSymbolRank(*text);
        int nextRank = getSymbolRank(*(text + 1));

        if (lastChar == *text) // rule 5
        {
            repetitions++;
            if ((currRank % 2) == 0 && repetitions > 3)
            { return 0; }
            if ((currRank % 2) == 1)
            { return 0; }
        }
        else
        {
            repetitions = 1;
            lastChar = *text;
        }

        if (currRank == -1) { return 0; } // rule 1
        if (nextRank > currRank) // rule 3 & 4
        {
            if (currRank % 2 != 0 || nextRank > currRank + 2)
            { return 0; }

            totalValue += rankValues[nextRank] - rankValues[currRank];
            text += 2;
        }
        else
        {
            totalValue += rankValues[currRank];
            text += 1;
        }
    }

    *result = totalValue;
    return 1;
}

int main()
{
    int a;
    if (convert("MMMCCCXXXVIII", &a))
    { printf("%d\n", a); }
    else
    { printf("BLAD!!!"); }
}
0

w momencie wpisania IIII wyskakuje że to jest 4 choć nie m takiej liczby

zapis IIII jest bardzo często używany na tarczach zegarowych, dla symetrii z VIII po przeciwnej stronie:

user image
(a teraz mnie zapuszkują za wklejenie cudzego zdjęcia ;-))

0

Wykorzystaj moje: user image

0

Do tego z tym warunkiem z ostatnim if doszedłem sam, tylko problem polega na tym, ze napisze co prawda w tym ostatnim else

 
else
cout<<"BLAD";
break;

To wyświetli się wtedy napis BLAD oraz ta wartość niepoprawna. Jak zrobić, żeby tak wartość się nie pokazywała?

0

Do tego z tym warunkiem z ostatnim if doszedłem sam, tylko problem polega na tym, ze napisze co prawda w tym ostatnim else

 
else
cout<<"BLAD";
break;

To wyświetli się wtedy napis BLAD oraz ta wartość niepoprawna. Jak zrobić, żeby tak wartość się nie pokazywała?

0
mike napisał(a)

Do tego z tym warunkiem z ostatnim if doszedłem sam, tylko problem polega na tym, ze napisze co prawda w tym ostatnim else

 
else
cout<<"BLAD";
break;

To wyświetli się wtedy napis BLAD oraz ta wartość niepoprawna. Jak zrobić, żeby tak wartość się nie pokazywała?

Hmmmmmmmm? Podałem Ci gotowy, działający kod. Nie ma w nim żadnej drabinki if-ów, żadnego break ani żadna niepoprawna wartość się nie pokazuje.
Że tak zapytam, przeczytałeś mój post?

0

tak tak czytałem, ale wiesz chciałbym dojść do tego co w tym jest źle. Jestem ci ogromnie wdzięczny za tamten kod :)

tylko ze w twoim programie liczba jest wprowadzana w kodzie, a muszę mieć program, w którym użytkownik poda liczbę . . .

0

@Mike: Oto przerobiony kod MSM:

/*
 *  ZASADY KONWERSJI:
 * 1) Dozwolone symbole: I (1), V (5), X (10), L (50), C (100), D (500), M (1000)
 * 2) Rangi: I: 0, V: 1, X: 2, L: 3, C: 4, D: 5, M: 6
 * 3) Symbole w prawidłowej liczbie są uporządkowane od największej 
 *   rangi do najmniejszej (oprócz wyjątków w 4)
 * 4) Jeżeli po symbolu o parzystej randze x następuje symbol y mający
 *   rangę większą o 1 lub 2, wartość takiego dwuznaku wynosi y - x
 * 5) Maksymalna ilość powtórzeń tego samego symbolu wynosi 3 dla 
 *   symboli o parzystej randze i 1 dla reszty
 */
 
const int rankValues[] =
{
    1,   // I
    5,   // V
    10,  // X
    50,  // L
    100, // C
    500, // D
    1000 // M
};
 
int getSymbolRank(char symbol) 
{
    if (symbol == 'I') { return 0; }
    if (symbol == 'V') { return 1; }
    if (symbol == 'X') { return 2; }
    if (symbol == 'L') { return 3; }
    if (symbol == 'C') { return 4; }
    if (symbol == 'D') { return 5; }
    if (symbol == 'M') { return 6; }
    return -1;
}
 
int convert(char *text, int *result)
{
    int totalValue = 0;
    char lastChar = '\0';
    int repetitions = 0;
 
    while(*text)
    {
        int currRank = getSymbolRank(*text);
        int nextRank = getSymbolRank(*(text + 1));
 
        if (lastChar == *text) // rule 5
        {
            repetitions++;
            if ((currRank % 2) == 0 && repetitions > 3)
            { return 0; }
            if ((currRank % 2) == 1)
            { return 0; }
        }
        else
        {
            repetitions = 1;
            lastChar = *text;
        }
 
        if (currRank == -1) { return 0; } // rule 1
        if (nextRank > currRank) // rule 3 & 4
        {
            if (currRank % 2 != 0 || nextRank > currRank + 2)
            { return 0; }
 
            totalValue += rankValues[nextRank] - rankValues[currRank];
            text += 2;
        }
        else
        {
            totalValue += rankValues[currRank];
            text += 1;
        }
    }
 
    *result = totalValue;
    return 1;
}
 
int main()
{
    int a;
    char Tekst[50];
    cin >> Tekst;
    if (convert(Tekst, &a))
    { printf("%d\n", a); }
    else
    { printf("BLAD!!!"); }
}

Ty na serio nie umiales tego przerobić.....

0

Jak już mówiłem jestem z programowania totalna noga. Mam taką prośbę jeszcze, wiem, że teraz się wygłupię, ale możesz teraz opisać krok po kroku działanie tego programu?

0

To do MSM(TezcaCośTam)! To jego program ;P Ja tylko zmieniłem 3 linijki.

1 użytkowników online, w tym zalogowanych: 0, gości: 1