Umrechnen von Hexzahlen



  • Guten morgen zusammen,

    ich habe den Auftrag bekommen ein Programm zu schreiben was Hexadezimalzahlen in Dezimalzahlen umrechnet.. Nun habe ich mal eine einfache Schleife zum einlesen der Dezimalzahlen gemacht..

    #include <stdio.h>
    #include <ctype.h>
    
    #define MAXCHAR 100
    
    void main()
    {
    
    	// char hex[MAXCHAR];
    	// char Zeichen;
    	// double dezimalzahl = 0;
    
    	int iEingabe = 0;
    	int iAusgabe = 0;
    
    	while((iEingabe = getchar()) != EOF)
    	{
    		if(iEingabe != '\n')
    		{
    			if(isxdigit((char) iEingabe))
    			{
    				if(iEingabe == 'A')
    				{
    					iAusgabe = 10;
    				}
    				else if(iEingabe == 'B')
    				{
    					iAusgabe = 11;
    				}		
    				else if(iEingabe == 'C')
    				{
    					iAusgabe = 12;
    				}
    				else if(iEingabe == 'D')
    				{
    					iAusgabe = 13;
    				}
    				else if(iEingabe == 'E')
    				{
    					iAusgabe = 14;
    				}	
    				else if(iEingabe == 'F')
    				{
    					iAusgabe = 15;
    				}	
    				else
    				{
    					iAusgabe = iEingabe - 48;
    				}
    				printf("Der Wert ist: %d", iAusgabe);
    			} 
    			else
    			{
    				printf("Iss nisch hex-zahl");
    			}
    		}
    	}
    }
    

    Da ich noch immer nicht aus dem Anfängerstatus rausgekommen bin, verzweifel ich noch an der Einbindung eines Vektors, bzw. der Rechnung. Für die Rechnung habe ich mir folgendes Überlegt.
    Bsp.:
    Eingabe ist: AAA

    Rechnung 10 * 1 = 10
    10 * 16 = 160
    10 * 256 = 2560 jetzt addieren = 2730

    Wie würdet ihr jetzt weiter machen? Bin dankbar über jede Hilfe..



  • Wenn du es unbedingt in einer Schleife lösen willst, sieht das ungefähr so aus:

    int iEingabe,iAusgabe=0,ixZiffer;
    while((iEingabe = getchar()) != EOF && iEingabe !='\n')
    {
      if(isxdigit(iEingabe)
      {
        //Eingabe in Hex-Ziffer umwandeln
    
        iAusgabe = 16*iAusgabe+ixZiffer;
      }
      else break;
    }
    

    PS: Wenn du darfst, würde ich statt einer eigenen Funktion strtol() verwenden 😉



  • danke für die schnelle Antwort, was aber hat ixZiffer zu bedeuten?

    gruß



  • i - int (ich weiß, ungarische Notation ist verpönt, aber ich passe mich deinem Stil an :D), xZiffer - Hex-Ziffer. Du kannst eine Variable nur für einen Zweck verwenden, deshalb brauchst du eine Hilfsvariable, in die du die aktuell gültige Hex-Ziffer unterbringen kannst (d.h. anstelle direkt 'iAusgabe' zu überschreiben, packst du deine Ziffer erstmal in eine eigene Variable und addierst sie am Ende auf den Zwischenwert drauf).

    PS: Übrigens kannst du die ganzen if(iEingabe==..) Blöcke zusammenfassen zu einem:

    if(isdigit(iEingabe))
      ixZiffer = iEingabe - '0';//Ziffern 0..9
    else
      ixZiffer = toupper(iEingabe) - 'A' + 10;//Ziffern aA..fF (mit toupper erwischst du auch die Kleinbuchstaben
    


  • wäre froh wenn ich schon einen eigenen Stil hätte. das alles habe ich aus dem Buch. Werde das mal ausprobieren was du mir geschrieben hast.. hoffe ich bekomme das hin.. vielen dank an dieser Stelle..

    gruß



  • Hi Mimas,

    da Du noch Anfänger zu sein scheinst, noch mal ein leichter OT-Tipp von mir:

    Mimas schrieb:

    ...

    if(iEingabe != '\n')
    		{
    			if(isxdigit((char) iEingabe))
    			{
    				if(iEingabe == 'A')
    				{
    					iAusgabe = 10;
    				}
    				else if(iEingabe == 'B')
    				{
    					iAusgabe = 11;
    				}		
    				else if(iEingabe == 'C')
    				{
    					iAusgabe = 12;
    				}
    				else if(iEingabe == 'D')
    				{
    					iAusgabe = 13;
    				}
    				else if(iEingabe == 'E')
    				{
    					iAusgabe = 14;
    				}	
    				else if(iEingabe == 'F')
    				{
    					iAusgabe = 15;
    				}	
    				else
    				{
    					iAusgabe = iEingabe - 48;
    				}
    				printf("Der Wert ist: %d", iAusgabe);
    			} 
    			else
    			{
    				printf("Iss nisch hex-zahl");
    			}
    		}
    	}
    }
    

    ...

    geht sehr viel einfacher z.B. per "switch-case":

    iAusgabe = -1;
       switch(iEingabe) {
          case '\n' : break;
          case 'A': iAusgabe = 10; break
          case 'B': iAusgabe = 11; break;
          case 'C': iAusgabe = 12; break;
          case 'D': iAusgabe = 13; break;
          case 'E': iAusgabe = 14; break;
          case 'F': iAusgabe = 15; break;
          case '0':
          case '1':
          case '2':
          case '3':
          case '4':
          case '5':
          case '6':
          case '7':
          case '8':
          case '9': iAusgabe = iEingabe - 48; break;
          default: printf("Iss nisch hex-zahl");
    	}
       if(iAusgabe != -1) printf("Der Wert ist: %d", iAusgabe);
    

    Die "if-else-Schachtelei" wird bei Vergleich gegen Strings und "variable Ausdrücke" notwendig, aber für so feste Vergleichswerte wie hier, ist switch-case ganz praktisch/übersichtlich.

    Aber wie schon gesagt: Wenn es nur um die Problemlösung geht, gibt es auch vorgefertigte Lösungen...

    Gruß,

    Simon2.



  • Hallo Simon2,

    bin gerade dabei mir das Thema switch/case anzueigenen.. 😃 Finde die Variante wie du sie aufgeführt hast auch besser..

    Wenn ich die erste Variante (if-else) fertig habe, versuche ich das Programm mal mit deinem Tipp, neu zu gestalten.

    Vielen herzlichen dank Simon2..

    Gruß,

    Mimas



  • Simon2 schrieb:

    case '9': iAusgabe = iEingabe - 48; break;
    

    Schreibt doch lieber '0' statt der 48, da sieht man sofort was gewollt ist...

    <pedantic>
    ... und außerdem ist nicht unbedingt garantiert, dass die '0' den Dezimalwert 48 hat, auch wenn das auf den meisten Systemen der Fall ist
    </pedantic>



  • <nochpedantischer>
    Und 'A'-'F' könnte man ebenso zusammenfassen, mit iEingabe - 'A' + 10 (sogar in EBCDIC :D)
    </nochpedantischer>



  • Ich habe das ganze jetzt mal ein wenig umgeschrieben.. habe eure Tipps erstmal außen vor gelassen und mein "Ursprungsprogramm" genommen.. eine neue Versoin schreibe ich wenn das hier funktioniert.

    Hier der Code.

    #include <stdio.h>
    #include <ctype.h>
    #include <math.h>
    #include <stdlib.h>
    #include <string.h>
    
    #define BASIS 16                // Basis bzw. Zähler
    #define MAXCHAR 100             // maximale Zeichen
    
    void main()
    {
    	char    hex[MAXCHAR];   // für Hex-Eingabe
      char    zeichen;        // Zeichen
      double  dezimalzahl = 0;      // Gesamtsumme, am Ende ausgegebene Dezimalzahl
      int     arrayende = 0;      // neues Array-Ende
      int     nenner = 0;         // Nenner
      int     summand = 0;        // einzelner Summand
      int     iZaehler = 0;              // Zähler
      int     iAusgabe;       
    
      arrayende = nenner = summand = iZaehler = 0;
    
      // Zeichen einlesen und überprüfen, ob es Hex-Ziffern sind.
     // neues Array-Ende setzen
       for (iZaehler = 0; iZaehler <=MAXCHAR && (zeichen=getchar()) != EOF; iZaehler++)
       {
          if (zeichen != '\n' && !isxdigit(zeichen))
          {
         	 	printf("Keine Hex-Ziffer an der Stelle %d\n", iZaehler + 1);
           	exit(0);
          }
          if (zeichen == '\n')
          {
          	hex[iZaehler] = '\0';
            arrayende = iZaehler - 1;
          }
          else
          {
          	hex[iZaehler] = zeichen;
          }
       }
    
            // Array von hinten beginnend auslesen; 
            // Die Werte in den entsprechenden
            // Dezimal-Wert umwandeln.
            // Dezimal-Zahl ausgeben
       for (iZaehler = arrayende; iZaehler >= 0; iZaehler--)
       {
       		if (hex[iZaehler] == 'A')
          {
        	  iAusgabe = 10;
          }
          else if (hex[iZaehler] == 'B')
          {
          	iAusgabe = 11;
          }
          else if (hex[iZaehler] == 'C')
          {
          	iAusgabe = 12;
          }
          else if (hex[iZaehler] == 'D')
          {
          	iAusgabe = 13;
          }
          else if (hex[iZaehler] == 'E')
          {
         	  iAusgabe = 14;
          }
          else if (hex[iZaehler] == 'F')
          {
          	iAusgabe = 15;
          }
          else
          {
          	iAusgabe = hex[iZaehler] - '0';
    			}
                    summand = (iAusgabe * (pow(BASIS,nenner)));
                    nenner++;
                    dezimalzahl += summand; // Jedoch wird mir das hier nicht klar?? warum "+=" 
        }																		// Weiß jemand Rat?
    
            				printf("Dezimal-Zahl: %0.f", dezimalzahl);
    }
    

    Jedoch fehlt mir das Verständnis für die letzten Zeilen. Habe das mit der Funktion pow aus einem anderen Programm rauskopiert.

    Gruß,
    Mimas



  • Erstens: pow() berechnet die Potenz einer Zahl (aber es ist imho schneller, du fängst vom anderen Ende der Eingabe an und schiebst die Zahl stückweise nach oben - siehe mein Beitrag weiter oben.

    Zweitens: += ist eine kombinierte Zuweisung (die gibt's für fast alle Operatoren) und vereinigt = und + zu einer Operation (die Zeile ist äquivalent zu dezimalzahl=dezimalzahl+summand; )

    Drittens: Warum das Rad immer neu erfinden? Anstelle der Eingabeschleife kannst du auch vorgefertigte Funktionen verwenden (z.B. fgets()).



  • LordJaxom schrieb:

    <nochpedantischer>
    Und 'A'-'F' könnte man ebenso zusammenfassen, mit iEingabe - 'A' + 10 (sogar in EBCDIC :D)
    </nochpedantischer>

    <extrempedantisch>
    Es ist nicht garantiert, dass das Alphabet in seiner Reihenfolge durchdummeriert wird 😃
    </extrempedantisch>



  • Ich würde diese Funktion gerne nehmen, nur muss ich mich Schritt für Schritt an C heran arbeiten. Sprich mein Ausbilder erlaubt es mir immer nur das zu nehmen, was ich auch schon kenne bzw. wie weit ich im Buch bin..

    👍 Cstoll du bist Spitze! 👍



  • TactX schrieb:

    Simon2 schrieb:

    case '9': iAusgabe = iEingabe - 48; break;
    

    Schreibt doch lieber '0' statt der 48, da sieht man sofort was gewollt ist...

    <pedantic>
    ... und außerdem ist nicht unbedingt garantiert, dass die '0' den Dezimalwert 48 hat, auch wenn das auf den meisten Systemen der Fall ist
    </pedantic>

    Das ist mir vollkommen klar und gerade bei solche Sachen muss ich hier sogar portabel programmieren (und würde das deswegen überhaupt nicht so machen).
    Ich wollte ihm als Anfänger nur mal das "switch" zeigen ... und das erkennt er am Besten, wenn ich sonst möglichst wenig an seinem Programm ändere (OK, die endl- und die isxdigit()-Abfragen habe ich auch gleich mit reingepult - aber auch das diente der Demonstration vom switch).

    Gruß,

    Simon2.



  • Bezog sich auch nicht speziell auf dich 🙂



  • TactX schrieb:

    Bezog sich auch nicht speziell auf dich 🙂

    Ach soooo. 💡

    (Immerhin hast Du auch den Imperativ Plural verwendet, wie mir erst jetzt auffiel). 😋

    Gruß,

    Simon2.



  • Hallo nochmal,

    erstmal vielen dank für die zahlreichen und wirklichen guten Beiträge von gestern.

    Habe das Programm auch erfolgreich mit euren Tipps "umgeschrieben".

    Nur muss ich heute vor Feierabend meinem AUsbilder das "Ursprungs-Programm" zeigen.

    Nun habe ich folgende Frage.

    Alles funktioniert so wie ich will, jetzt muss ich aber noch einbauen das ich in der Eingabe z.B. ein "0x" oder "0X" davor setzen kann.

    Ungefähr so: 0xAF oder ähnlich

    Hier der Code:

    #include <stdio.h>
    #include <ctype.h> // Bibliothek für die Funktion isxdigit
    #include <math.h>  // Bibliothek für die Funktion pow
    
    #define BASIS 16                // BASIS (später für die Rechnung)
    #define MAXCHAR 100             
    
    void main()
    {
    	char    hex[MAXCHAR];   	// für Hex-Eingabe
      char    cEingabe;        	// Eingabevariable
      double  dezimalzahl = 0;  // Umgerechnete Dezimalzahl
      int     iArray = 0;      	// neues Array-Ende
      int     nenner = 0;       // Nenner
      int     summand = 0;     	// einzelner Summand
      int     iZaehler = 0;     // Zähler
      int     iAusgabe;       
    
       for (iZaehler = 0; iZaehler <=MAXCHAR && (cEingabe=getchar()) != EOF; iZaehler++)// Zeichen werden eingelesen
       {																																								// überprüfen ob es sich um eine
          if (cEingabe != '\n' && ! isxdigit(cEingabe))																	// Hex-Ziffer handelt!
          {
         	 	printf("Keine Hex-Ziffer eingegeben! %d\n", iZaehler);
          }
          	if (cEingabe == '\n')
          	{
          		hex[iZaehler] = '\0';
            	iArray = iZaehler - 1;
          	}
          	else
          	{
          		hex[iZaehler] = cEingabe;
          	}
       	}
    
       			for (iZaehler = iArray; iZaehler >= 0; iZaehler--) // Array auslesen.
       			{																									 // Hex-Ziffern in entsprechende Dezimalzahl umwandeln
       				if (hex[iZaehler] == 'A')												// und ausgeben.
         			{
        	  		iAusgabe = 10;
          		}
          		else if (hex[iZaehler] == 'B')
          		{
          			iAusgabe = 11;
          		}
          		else if (hex[iZaehler] == 'C')
          		{
          			iAusgabe = 12;
          		}
          		else if (hex[iZaehler] == 'D')
         	 		{
          			iAusgabe = 13;
          		}
          		else if (hex[iZaehler] == 'E')
          		{
         	  		iAusgabe = 14;
          		}
          		else if (hex[iZaehler] == 'F')
          		{
          			iAusgabe = 15;
          		}
          		else
          		{
          			iAusgabe = hex[iZaehler] - '0'; // Ziffern von 0 bis 9
    					}
                    summand = (iAusgabe * (pow(BASIS, nenner)));
                    nenner++;
                    dezimalzahl = summand;  
        		}																		
    
            				printf("Dezimal-Zahl: %0.f", dezimalzahl);
    }
    

    Hatte mir gedacht das in etwa so einzubauen:

    if(hex[iZaehler] == 0)
    	{
    		iAusgabe = ' ';
    	}
    	else if(hex[iZaehler] == 'x' || hex[iZaehler] == 'X')
    	{
    		iAusgabe = ' ';
    	}
    

    Nur ist dann das Problem, das ich ein Fehler bekomme, wenn ich eine 0 an dritter Stelle eingebe.

    Hat jemand einen Tipp für mich wie ich das einbinde das nur die ersten 2 Stellen berücksichtigt werden?

    Gruß
    Mimas



  • Du kannst vor der eigentlichen Rechenschleife eine Spezialüberprüfung vorsetzen:

    if(hex[0]=='0' && toupper(hex[1]=='X')
      ende=2;
    else
      ende=0;
    ...
    for (iZaehler = iArray; iZaehler >= ende; iZaehler--) // Array auslesen.
      ...
    


  • Gibt es auch eine Möglichkeit das toupper wegzulassen? darf das eigentlich noch nicht benutzen?
    Wasrum hast du hex[l] genommen?

    Gruß
    Mimas



  • Mimas schrieb:

    Gibt es auch eine Möglichkeit das toupper wegzulassen? darf das eigentlich noch nicht benutzen?

    Ja: (hex[1]=='X'||hex[1]=='x')

    Wasrum hast du hex[l] genommen?

    Wenn die Eingabe eine Hex-Kennung (0x...) enthält, dann steht sie in den ersten beiden Zeichen deines Eingabestrings (in hex[0] die '0' und in hex[1] das 'x')


Log in to reply