Konwersja liczb rzymskich na arabskie

COOLTER

Prosta metoda na konwersję liczb rzymskich na arabskie.

#include <iostream>
#include <stdlib.h>

/******************************************************************************/
using namespace std;
char rzymska[24];
void RzymToArab(char *);
/******************************************************************************/
int main(int argc, char *argv[])
{
  cout << "LiczbChanger\n";
  cout << "Podaj liczbe rzymska, ktora chcesz zamienic na arabska: ";
  cin >> rzymska;
  RzymToArab(rzymska);
  system("PAUSE");	
  return 0;
}
/******************************************************************************/
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 << zawartosc << " to " << wynik << endl;
}
/******************************************************************************/

10 komentarzy

to dodam swój, sorry że nie jako funkcja :
int main(int argc, char* argv[])
{
int k=0,b=0,i,l1=0,t=0,l[] = {5,1} ,l10[] = {1000,100,10,1};
char r[] = {'5','M','D','C','L','X','V','I'};
char c;
c = getchar();
do {
for (i=0;i<8;i++)
if (c == r[i]) {
t = l10[i/2]* l[i-i/22];
break;
}
if ( t > l1 && b) l1 = t - l10[i/2+i-i/2
2];
else {k += l1;
l1 = t; }
c = getchar();
if (!b) b++;
} while(c != '\n');
k += l1;
printf("%d\n",k);
system("PAUSE");
return 0;
}

A może w taki sposób?

/zapisuje odczytywane symbole do tablicy i odczytujc od tylu
sumuje wartosc poszczeglnych symboli, w przypadku gdy poprzedni symbol
ma wartosc wiksza od aktualnie sprawdzanego (dla liczb 4, 9, 40 itd) odejmuje od ogolnej sumy wartosc elementu aktualnie sprawdzanego
program nie sprawdza poprawnosci liczby rzymskiej
/

#include <stdio.h>
#include <conio.h>

int konwersja(char symbol);

main()
{
const int max = 20; /maxymalna ilosc cyfr rzymskich/
char rzymska[max]; /tablica do przechowywania cyfr rzymskich/
char znak; /wczytywana litera reprezentujca cyfre rzymska/
int arab , /wartosc liczby arabskiej/
biezaca , /wartosc aktualnie sprawdzanej cyfry/
poprzednia, /warto poprzedniej cyfry/
i, /zmienna kontrolna petli/
delta = 32, /roznica midzy malymi i duzymi literami/
wlk_tab; /rzeczywista ilosc wczytanych elementow/

do {
clrscr();
arab = 0; biezaca = 0; poprzednia = 0; wlk_tab = 0;
printf("Program zamienia liczby rzymskie na arabskie\n\n");
printf("Podaj liczb w postaci cyfr rzymskich ");
printf("..... : ");
i = 0;
/wczytywanie symboli, zamiana na duze litery, i zapis do tablicy jezeli podane znaki naleza do cyfr rzymskich/
do {
znak = getch();
if ((znak >= 97)&&(znak <= 122))
znak -= delta;
if ((znak == 'I')||(znak =='V')||(znak =='X')||(znak =='L')||(znak =='C')||(znak =='D')||(znak =='M')) {
putchar(znak);
rzymska[i] = znak;
i += 1;
wlk_tab = i;
}
} while ((znak != 13)&&(i < max));
i = 0;
printf("\n\n w kolejnosci ");
while (i < wlk_tab) {
printf("%5d", konwersja(rzymska[i]));
i++;
}
i = wlk_tab;
while (i) {
biezaca = konwersja(rzymska[i-1]);
if (poprzednia > biezaca)
arab -= biezaca;
else
arab += biezaca;
poprzednia = biezaca;
i--;
};
printf("\n\n Warto dziesitna wprowadzonej liczby to %d \n\n\n\n\n", arab);
printf("Czy chcesz zakonczy program t/n ");
znak = getch();
} while ((znak !='t')&&(znak !='T'));

return 0;
}

int konwersja(char symbol)
{
int wartosc;
switch (symbol)
{
case 'I': wartosc = 1;
break;
case 'V': wartosc = 5;
break;
case 'X': wartosc = 10;
break;
case 'L': wartosc = 50;
break;
case 'C': wartosc = 100;
break;
case 'D': wartosc = 500;
break;
case 'M': wartosc = 1000;
break;
}
return wartosc;
}

Dziwne ze nikt tego nie zauwazyl:
piszac if(a==b==c) nie sprawdzasz czy wszystkie 3 są równe. Najpierw o ile się nie mylę wykonane zostanie porównanie b==c i zwrócona zostanie wartość true/false następnie poddana konwersji chyba na char(0/1) a więc nic z tego nie wyjdzie. Poprawny zapis to if(a==b && b==c).

TamaszK, w if powinno byc (a==b==c)
A poza tym to masz absolutna racje

Masz zle skonstruowana petle for (powinno byc albo i<=23 albo i<23)

A czy nikt nie uwzględnił że trzeba jeszcze sprawdzić czy przypadkiem liczba nie jest błędna?
Przecież nie może być IIII albo VVVVVVVV.

Trzeba użyć petli do tego programu. Przy każdym kolejnym obejsciu pętli sprawdzając czy rzymska[i] niejest równa rzymska[i-1] albo rzymska[i-2].

bool sprawdzacz(char a, char b, char c)
if(a == b == c)
{
return true;
}
else
{
return false;
}

}

A wyżej na końcu pętli:

sprawdzacz(rzymska[i],rzymska[i-1],rzymska[i-2])
If (sprawdzacz==true)
{
continue;
}
}

jest też taki sposób. Wymyślony w nocy więc w sumie może dałoby się go jakoś przerobić.

#include<stdio.h>
#include<conio.h>
#include<string.h>
main()
{
char ciag[20];
int i,dlug,licz,k;
licz=0;
k=0;
scanf("%s",&ciag);
dlug=strlen(ciag);

  for(i=0;i<=dlug-1;i++)   {

if(ciag[i]=='I') {
licz+=1;
k=1;continue;
}
if(ciag[i]=='V') {
if(k<=5) licz+=5-(2k);
else licz+=5;
k=5;continue;
}
if(ciag[i]=='X') {
if(k<10) licz+=10-(2
k);
else licz+=10;
k=10;continue;
}
if(ciag[i]=='L') {
if(k<50) licz+=50-(2k);
else licz+=50;
k=50;continue;
}
if(ciag[i]=='C') {
if(k<100) licz+=100-(2
k);
else licz+=100;
k=100;continue;
}
if(ciag[i]=='D') {
if(k<500) licz+=500-(2k);
else licz+=500;
k=500;continue;
}
if(ciag[i]=='M') {
if(k<1000) licz+=1000-(2
k);
else licz+=1000;
k=1000;continue;
}
}
printf("%d",licz);
return 0;
}

Troche liczenia,ale mnie zmiennych;)
Taki sam miałem cel jak COOLTER z tym programikiem.Sposób jak sposób. Programik napisany po tygodniu znajomości C więc stąd ten haos.

Tu trochę inna wersja (chyba troche bardziej spójna) tego samego programu, napisana w C:

#define N 100
#include <stdio.h>
#include <conio.h>

void rzym2arab(char[]);

const int I=1,V=5,X=10,L=50,C=100,D=500,M=1000;
int arab,tab[N];
char rzym[N];

int main()
{
printf("Podaj liczbe rzymska\n");
scanf("%s",&rzym);
rzym2arab(rzym);
getch();
}

void rzym2arab(char rzym[])
{
int dl=0;
while (rzym[dl] != '\0')
{
switch(rzym[dl])
{
case 'I': {tab[dl] = I;break;}
case 'V': {tab[dl] = V;break;}
case 'X': {tab[dl] = X;break;}
case 'L': {tab[dl] = L;break;}
case 'C': {tab[dl] = C;break;}
case 'D': {tab[dl] = D;break;}
case 'M': {tab[dl] = M;break;}
default : {printf("BLAD\n");break;}
}
dl++;
}
arab = tab[dl-1];
while (dl != 1)
{
if (tab[dl-1] <= tab[dl-2])
arab += tab[dl-2];
else arab -= tab[dl-2];
dl--;
}
printf("%d\n",arab);
}

A nie wygodniej byłoby użyć switch/case ?

Program napisany na zadanie domowe dla kolegi, może komuś sięprzyda w podobnym celu.