Konwersja systemów liczbowych

0

Witam!

Potrzebuję napisać program, który będzie mógł dokonywać konwersji pomiędzy systemem dwójkowym, ósemkowym, dziesiętnym i heksadecymalnym. Postanowiłem, że do problemu podejdę w następujący sposób. Z dowolnego systemu liczbowego zawsze będę dokonywać konwersja na system dziesiątkowy i dopiero z niego jeśli zajdzie konieczność dalej przekonwertuję liczbę na jakiś inny. Oto mój kod do tej pory. Wszystko muszę wykonać w C. Komentarzami proszę się nie przejmować.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

//{
char Characters[16] =
        {'0','1','2','3','4','5','6','7',
         '8','9','A','B','C','D','E','F'};

int UserInput;

//}

int main(void)
{

GetUserInput();
ConvertFromDecimal(UserInput,2);

getchar();
  return 0;
}


void GetUserInput(void)
{
    printf("\nEnter the number: ");
    scanf("%d", &UserInput);
}

int ConvertToDecimal(int DesiredBase)
{

    int Counter;
    int Temp;


}

void ConvertFromDecimal(int NumberToConvertFromDecimal,int DesiredBase) //Function used to convert decimal numbert to any base
{
    //Variables initialization
    int NumberAfterConversion[126];
    int Counter;
    //Reseting counter
    Counter = 0;

    //Conversion part. Unless number is zero, this funtion will convert decimal number to any base using
    //this simple algorithm:
    if (NumberToConvertFromDecimal != 0)
    {
        while (NumberToConvertFromDecimal != 0)
        {
            NumberAfterConversion[Counter] = NumberToConvertFromDecimal % DesiredBase;
            NumberToConvertFromDecimal = NumberToConvertFromDecimal / DesiredBase;
            ++Counter;
        }

        --Counter;
        printf("\nNumer after base conversion: ");
        for( ; Counter >= 0 ; Counter--)
        {
            printf("%c", Characters[NumberAfterConversion[Counter]]);
        }
        printf("\n");
    }
    else
    {
        printf("\nNumer after base conversion: 0");
    }

}

Znalazłem taki oto kod, który jest w Pascalu i robi dokładnie to o co mi chodzi. Jednak ze względu na to, że jestem świeży w C proszę was o pomoc w przystosowaniu tego na moje potrzeby. Najbardziej boję się użycia wskaźników ponieważ nie do końca ogarniam ten temat.

function DowolnyNaDec(Liczba : String ; Podst : Integer) : Cardinal ;
var
  Dana : Integer ;
  i : Integer ;
begin
  Result := 0 ;
  
  if (Liczba = '') or (Podst < 2) or (Podst > 35) then Exit ;  // 1

  for i := 1 to Length(Liczba) do
  begin
    if Liczba[i] in ['A'..'Z'] then Dana := Ord(Liczba[i]) - Ord('A') + 10 // 2
    else Dana := StrToInt(Liczba[i]) ;
    
    if Dana >= Podst then // 3
    begin
      Result := 0 ;
      Exit ;
    end ;

    Result := Result + Dana * Trunc(Exp((Length(Liczba) - i) * Ln(Podst))) ; // 4
  end ;
end ;
2

Uwaga odnośnie pomyśłu nie kodu. Jeśli chcesz zawsze konwertować na jeden system to czy lepszym rozwiązaniem nie byłby wybór systemu dwójkowego?

0

Kolega ma racje. Co do tej uwagi, z systemu dwójkowego możesz łatwo przejść na kolejne systemy np 8kowy, poprzez grupowanie bitów...

0

Generalnie system dziesiątkowy wydaje mi się najbardziej naturalny i najmniej zachodu było z napisaniem funkcji która dokonuje konwersji na inne systemy. Problem stanowi dla mnie napisanie drugiej funkcji, która będzie dokonywać konwersji z dowolnego spośród opisanych systemów na system dziesiątkowy.

Kombinowałem trochę z tym. Przede wszystkim chciałbym żeby użytkownik wpisywał liczbę w jakimś systemie i podawał jaki to system. Myślałem nad użyciem tablicy char do tego. Potem mógłbym sobie coś takiego przekazać jako parametr i coś próbować z tym działać. Nawet nie musi być jakieś kontroli poprawności od taki najprostszy program.

0
Wazka260196 napisał(a):

Generalnie system dziesiątkowy wydaje mi się najbardziej naturalny i najmniej zachodu było z napisaniem funkcji która dokonuje konwersji na inne systemy. Problem stanowi dla mnie napisanie drugiej funkcji, która będzie dokonywać konwersji z dowolnego spośród opisanych systemów na system dziesiątkowy.

Tobie się wydaje bo jesteś człowiekiem i pewnie nim się najwięcej posługujesz. Nie wiem czy najmniej zachodu. Mając liczbę w systemie dwójkowym dzielisz ją od lewej po 3 bity i obliczasz dla każdej trojki wartość orzymując w ten sposób liczbę w ósemkowym. Dla szesnastkowego analogicznie tylko grupujesz po 4 a dla dziesiętnego liczysz tak, że dodajesz wszystkie wagi na bitach z 1.

0

Część z konwersją na inne systemy z dziesiętnego już mam. Tylko nie wiem w jaki sposób w C, jakich funkcji itp użyć by móc wczytywać liczby z dowolnego systemu do pamięci a następnie obrabiać je do dziesiętnego. Np. w heksadecymalnym mamy też literki więc użycie typu int do zapisania tej zmiennej odpada. Myślałem nad char ale potem miałem problemy z pobieraniem tych liczb od użytkownika i dokonywania na nich konwersji. Jakieś cuda się działy i non stop dostawałem śmieci. Po prostu nie jestem zaznajomiony z C.

0

Cały czas piszesz o C, jezeli mógłbyś użyć C++ to jest tam całkiem przydatny kontener bitset, całkiem przydatny przy niektórych konwersjach.

0

W tym problem, że właśnie nie mogę użyć C++.

0

A czemu nie zrobić bezpośredniej konwersji z jednego systemu na drugi?
Masz tu algorytm z dowolnego systemu na dowolny, dla liczby która nie koniecznie mieści się w int'a http://4programmers.net/Forum/Newbie/151329-poprawa_-_wskazowki_do_programu?p=986462#id986462
Jak poszukasz to znajdziesz to samo w jeżyku C.

0

Czemu nie użyć już zawartych funkcji konwertujących?

#include <stdio.h>
#include <conio.h>
int main(int, char**)
{
    int liczba;
    printf("Z jakiego systemu liczbowego:\n[1] Dec\n[2] Hex\n[3] Oct\n[4] Bin\n");
    int znak = _getch();
    printf("Liczba: ");
    if(znak == '1') 
    {
        scanf("%d", &liczba);
    }
    else if(znak == '2')
    {
        scanf("%x", &liczba);
    }
    else if(znak == '3')
    {
        scanf("%o", &liczba);
    }
    else if(znak == '4')
    {
        char* szBuffer = new char[33];
        scanf("%s", szBuffer);
        unsigned long result = 0;
        unsigned long powed = 1;
        for(int i = strlen(szBuffer); i > 0; i--)
        {        
            if(szBuffer[i-1] == '1')
            {
                result = result | powed;
            }
            powed *= 2;
        }
        liczba = result;
        delete[] szBuffer;
    }
    printf("\ndec = %d", liczba);
    printf("\nhex = %x", liczba);
    printf("\noct = %o", liczba);
    printf("\nbin = ");
    bool ShowZeros = false;
    for(unsigned long m = 2147483648; m > 0; m >>= 1) 
    {
        if((liczba & m))
        {
            printf("1");
            ShowZeros = true;
        }
        else if(ShowZeros) printf("0");
    }
    int stop;
    scanf("%d", &stop);
    return 0;
}

Proste, łatwe, przyjemne ;-)

0


Zapoznaj się z tym materiałem,może Ci ułatwić sprawę

0
// Use 'gcc <program name>.c -o <program name> -lm' to compile

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>

int inrange(int num, int from, int to) {
    return num >= from && num <= to;
}

int main() {
    char *strnum = malloc(sizeof(*strnum) * 11), *convnum = malloc(sizeof(*convnum) * 111);
    memset(strnum, '\0', 11);
    memset(convnum, '\0', 111);
    int num, base, convbase;
    
    printf("Number to convert: ");
    scanf("%10s", strnum);
    printf("Number's base: ");
    scanf("%i", &base);
    
    if (base > 50) {
        printf("Invalid base '%i'. Max base is 50", base);
        exit(1);
    }
    int i;
    for (i = 0; i < strlen(strnum); i++) {
        char ch = strnum[i];
        if (inrange(ch, 48, 57)) {
            ch -= 48;
        } else if (inrange(ch, 65, 90)) {
            ch -= 55;
        } else {
            printf("Invalid character on position %i: '%c'\n", i, ch);
            exit(1);
        }
        if (ch >= base) {
            printf("Invalid character on position %i: '%c'. Character's value greater than base\n", i, ch);
            exit(1);
        }
    }
    
    for (i = 0; i < strlen(strnum); i++) {
        char ch = strnum[i];
        if (inrange(ch, 48, 57)) {
            ch -= 48;
        } else {
            ch -= 55;
        }
        num += ch * pow(base, strlen(strnum) - i - 1);
    }
    
    printf("Base to convert: ");
    scanf("%i", &convbase);
    
    for (i = 0; num > 0; i++) {
        int r = num % convbase;
        num /= convbase;
        if (inrange(r, 0, 9)) {
            convnum[i] = r + 48;
        } else {
            convnum[i] = r + 55;
        }
    }
    for (i = 0; i < strlen(convnum) / 2; i++) {
        char tmp = convnum[i];
        convnum[i] = convnum[strlen(convnum) - i - 1];
        convnum[strlen(convnum) - i - 1] = tmp;
    }
    
    printf("\n");
    printf("Converted number: %s\n", convnum);
    
    return 0;
}
7

To straszne, te rozwiązania to jakiś okropny bezsens!

#include <string.h>

char *sysconv(unsigned sysin,unsigned sysout,const char *in,char *out)
  {
   static char digits[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
   unsigned p,m;
   char *end,*pos,tmp;
   for(*out='0',end=out+1;*in;++in)
     {
      p=strchr(digits,toupper(*in))-digits;
      for(pos=out;pos<end;*(pos++)=digits[m-(p=m/sysout)*sysout]) m=(strchr(digits,*pos)-digits)*sysin+p;
      while(p) *(end++)=digits[m-(p=(m=p)/sysout)*sysout];
     }
   for(*end=0,pos=out;pos<end;tmp=*(--end),*end=*pos,*(pos++)=tmp) {}
   return out;
  }

int main()
  {
   unsigned sysin,sysout;
   static char in[1024],out[36*1024];
   for(;;)
     {
      printf("\rsystem wejsciowy: ");
      scanf("%u",&sysin);
      printf("\rsystem wyjsciowy: ");
      scanf("%u",&sysout);
      printf("\rliczba wejsciowa: ");
      scanf(" %1023s",in); // wypada jeszcze sprawdzić czy to poprawna liczba w systemie sysin ale to banał
      if(2>sysin||sysin>36||2>sysout||sysout>36) return 0;
      printf("\rliczba wyjsciowa: %s\n\n",sysconv(sysin,sysout,in,out));
     }
  }

http://ideone.com/75OXQ2

0

Bardzo dziękuję za wszystkie sugestie! Zaraz idę przeanalizować kody i jak pojawią się jakiekolwiek wątpliwości to zapytam. Na razie dziękuję wszystkim.

0

Doszedłem do czegoś takiego. Wiem że samo rozwiązanie nie jest dobre ale ważne żeby to działało do wtorku. Jednak mam mały problem ponieważ program ma konwertować dowolne dodatnie 32bit int a konwersja liczb większych niż 1023 w systemie binarnym wykrzacza go. Czy ma ktoś jakieś sugestie.

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>


//{
char Characters[16] =
        {'0','1','2','3','4','5','6','7',
         '8','9','A','B','C','D','E','F'};

long int UserInput;
long int Temp;


//}

int main(void)
{
    int Choice;

    while (Choice != 5)
    {
        system("cls");
        printf("\n\n");
        printf("Select current base of your number.\n");
        printf("[1] Binary\n");
        printf("[2] Octal\n");
        printf("[3] Decimal\n");
        printf("[4] Hexadecimal\n\n");
        printf("[5] Quit\n\n");
        printf("Your choice: ");

        scanf("%ld", &Choice);

        switch(Choice)
        {
            case 1:
                GetUserInput(0);
                ConvertBinaryToDecimal(UserInput);
                ConvertFromDecimal(Temp,8);
                ConvertFromDecimal(Temp,16);
                printf("\n");
                system("pause");
                system("cls");
                break;
            case 2:
                GetUserInput(0);
                ConvertOctalToDecimal(UserInput);
                ConvertFromDecimal(Temp,2);
                ConvertFromDecimal(Temp,16);
                printf("\n");
                system("pause");
                system("cls");
                break;
            case 3:
                GetUserInput(0);
                ConvertFromDecimal(UserInput,2);
                ConvertFromDecimal(UserInput,8);
                ConvertFromDecimal(UserInput,16);
                printf("\n");
                system("pause");
                system("cls");
                break;
            case 4:
                GetUserInput(1);
                ConvertHexadecimalToDecimal(UserInput);
                ConvertFromDecimal(UserInput,2);
                ConvertFromDecimal(UserInput,8);
                printf("\n");
                system("pause");
                system("cls");
                break;
            case 5:
                break;
        }
    }
  return 0;
}

void GetUserInput(int Hex)
{
if(Hex == 0)
    {
        printf("\n\nEnter number: ");
        scanf("%ld",&UserInput);
        printf("\n");
    }
else
    {
        printf("\n\nEnter number: ");
        scanf("%lx",&UserInput);
        printf("\n");
    }
}
int ConvertOctalToDecimal(long int OctalNumber)
{
    long int DecimalNumber =0;
    int Counter = 0;

    while(OctalNumber!=0){
         DecimalNumber = DecimalNumber + (OctalNumber % 10) * pow(8 , Counter++);
         OctalNumber = OctalNumber / 10;
    }

    printf("Decimal: %ld\n",DecimalNumber);
    Temp = DecimalNumber;

}
int ConvertBinaryToDecimal(long int BinaryNumber)
{
    long int DecimalNumber = 0;
    long int Counter = 0;

    system("cls");

    while(BinaryNumber!=0){
         DecimalNumber = DecimalNumber + (BinaryNumber % 10) * pow(2 , Counter++);
         BinaryNumber = BinaryNumber / 10;
    }

    printf("\nDecimal: %ld\n",DecimalNumber);
    Temp = DecimalNumber;

}
void ConvertHexadecimalToDecimal(long int HexadecimalNumber)
{
printf("\nDecimal: %d", HexadecimalNumber);
printf("\n");
Temp = HexadecimalNumber;

}
void ConvertFromDecimal(int NumberToConvert, int DesiredBase) //Function used to convert decimal numbert to any base
{
    //Variables initialization

    int NumberAfterConversion[127];
    int Counter;
    //Reseting counter
    Counter = 0;

    //Conversion part. Unless number is zero, this funtion will convert decimal number to any base using
    //this simple algorithm:
    if (NumberToConvert != 0)
    {
        while (NumberToConvert != 0)
        {
            NumberAfterConversion[Counter] = NumberToConvert % DesiredBase;
            NumberToConvert = NumberToConvert / DesiredBase;
            ++Counter;
        }

        --Counter;

        if (DesiredBase == 2) {printf("\nBinary: ");}
        if (DesiredBase == 8) {printf("\nOctal: ");}
        if (DesiredBase == 16) {printf("\nHexadecimal: ");}

        for( ; Counter >= 0 ; Counter--)
        {
            printf("%c", Characters[NumberAfterConversion[Counter]]);
        }
        printf("\n");
    }
    else
    {
        if (DesiredBase == 2) {printf("\nBinary: 0");}
        if (DesiredBase == 8) {printf("\nOctal: 0");}
        if (DesiredBase == 16) {printf("\nHexadecimal: 0");}
    }
}

EDIT: Jestem na tyle zdesperowany że chyba zlecę wykonanie tego programu komuś. Pełna treść zadania brzmi następująco:"Konwertuj dodatnią liczbę typu 32bit int pomiędzy dowolnymi z wymienionych systemów liczbowych: dwójkowy, ósemkowy, dziesiątkowy i heksadecymalny. Program ma działaś w "menu mode", w którym poszczególne konwersje są pozycjami menu. Program zapętla się dopóki użytkownik nie zdecyduje się wyjść." Jeśli ktoś chciałby się tego podjąć to prosiłbym o kontakt na [email protected]. Zdaje sobie sprawę, że trochę późno (bo ma być na wtorek) to mówię ale lepiej tak niż wcale. I ostatnia prośba. Program musi być napisany łopatologicznie (jak najprościej), ponieważ muszę wiedzieć dokładnie co się w nim dzieje i dlaczego tak a nie inaczej.

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