# Dual/Dezimal-Umrechner



## zoj (17. April 2006)

Hallo, ich bin neu hier.
Ich habe da ein Problem mit meinem Dual / Dezimal Umrechner.

Das Programm sollte zuerst die Dualzahl als Array einlesen und es dann als
Dezimalzahl ausgeben.

Leider klappt es nicht ganz. Das Programm gibt mir falsche Werte aus;-] 

Kann mir da einer helfen? Oder kennt vielleicht einer irgendwelche Quellen?

Danke im Vorraus
Hier der Source


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

int fDezimal (int dual[])
{
    int i,x,wert,Ergebnis,I;
    
    
    
    x=1;
    for(i=0;i<10;i++)
    {
                     
                     wert = dual[i]* x;
                     Ergebnis = Ergebnis + wert;
                     x*2;                          
    }
   printf("%d\n\n",Ergebnis); 
}
int main(int argc, char *argv[])
{
  int abfrage;
  int Ergebnis;
  int dual [10];
  int i;
  printf("RECHNER FÜR DIE UMRECHNUNG VON ZAHLENSYSTEMEN\n\n");
  
  printf("\n\nBitte geben Sie jetzt die Dualzahl ein\n\n");
  for(i=0; i<10; i++)
           {
                 scanf("%d",& dual[i]);
           }                              
 
 
 
           printf("Die Dualzahl lautet: ");
           printf("%d",dual[0]); 
           printf("%d",dual[1]);
           printf("%d",dual[2]);
           printf("%d",dual[3]);
           printf("%d",dual[4]);
           printf("%d",dual[5]);
           printf("%d",dual[6]);
           printf("%d",dual[7]);
           printf("%d",dual[8]);  
           printf("%d\n\n\n",dual[9]);

    
  
  printf("Bite die gewünschte umrechnung auswählen!\n\n\a");
  printf("<1> Umrechnung in Dezimal\n");
  printf("<2> Umrechnung in Hexadezimal\n");
  printf("<3> Umrechnung in Oktal\n\n");
  
  printf("<4> Programm beenden\n\n");
  
  printf("Bite die gewünschte umrechnung auswählen! < >\b\b");
  scanf("%d",& abfrage);
  
  switch(abfrage)
  {
                 case 1:      printf("\n\nAuswahl 1\n\n");
                              
                              Ergebnis = fDezimal(dual);
                              
                              break;          
                 
                 case 2:      printf("\n\nAuswahl 2\n\n");
                              
                              
                              break;          
                
                 case 3:      printf("\n\nAuswahl 3\n\n");
                              
                              break;
                 
                 case 4:      printf("\n\nAuswahl 4\n\n");
                              
                              break;                                       
                 
                 default:     printf("\n\nUnbekannte Auswahl\n\n");
  }                                                                                                                               
                              
                                        
  system("PAUSE");	
  return 0;
}
```


----------



## rohrbold (17. April 2006)

Du musst mal sehen, was hier herauskommt, wenn ich Deinen Programmcode (habe ihn noch etwas reformatiert) mit allen Warnstufen unter Linux kompiliere:

```
martin@bart:~$ gcc -W -Wall -pedantic dual.c -o dual
dual.c: In Funktion »fDezimal«:
dual.c:11: Warnung: Anweisung ohne Effekt
dual.c:6: Warnung: Variable »I« wird nicht verwendet
dual.c:14: Warnung: Kontrollfluss erreicht Ende einer Nicht-void-Funktion
dual.c: Auf höchster Ebene:
dual.c:16: Warnung: nicht benutzter Parameter »argc«
dual.c:16: Warnung: nicht benutzter Parameter »argv«
```

Das fängt schonmal damit an, dass Du eine Anweisung hast, die überhaupt keine Auswirkung zeigt: x*2;. Ich vermute Du willst hier die Variable x erhöhen, so nach dem Motto x = x * 2; o.ä.
Weiters benutzt Du die Variablen I, argc und argv nicht -- kannst Du also weglassen.
Ein weiteres großes Problem besteht darin, dass Du die Funktion fDezimal() als int deklarierst, aber keinen Wert zurückgibst (eine return Anweisung fehlt!), so dass die Zeile 
Ergebnis = fDezimal(dual);
lange auf ein Ergebnis warten kann ...
Vielleicht kann ich nochmal einen genaueren Blick auf Dein Programm werfen und später eine genaue Fehleranalyse schicken, aber die beiden oben genannten Fehler sind schonmal elementar.


----------



## zoj (17. April 2006)

rohrbold hat gesagt.:
			
		

> Vielleicht kann ich nochmal einen genaueren Blick auf Dein Programm werfen und später eine genaue Fehleranalyse schicken, aber die beiden oben genannten Fehler sind schonmal elementar.



Das wäre super Vielen Dank im Vorraus


----------



## rohrbold (17. April 2006)

Hallo nochmal,
hatte den Tag über noch Fußball, konnte nicht früher antworten.

Hier ist mal eine Version, wie ich sie geschrieben hätte. Beim Einlesen von Eingabedaten unter C gibt es einige Besonderheiten oder Stolperfallen zu berücksichtigen. Zum Beispiel ob der Eingabepuffer vor einer neuen Eingabe leer ist oder auch, dass sich die Zahlen 1 und 0 im ASCII Zeichnsatz an den Stellen 48 bzw. 49 befinden. Beim Einlesen einer Zeile oder eines Zeichens würde ich die Variante bevorzugen, mit fgets() eine ganze Zeile einzulesen (also mit von uns festgelegter Größe), und daraus dann die Daten zu extrahieren.
Sieh Dir mal folgendes Programm an, es liest die ersten zehn Zeichen der Zeile von der Standardeingabe (alles darüber hinaus wird nicht betrachtet) oder hört dann auf, wenn Enter gedrückt wurde; bei fehlerhaften Eingaben bricht das Programm direkt ab, also auch bei Zahlen ungleich 0 oder 1, da wir ja hier Binärzahlen wollen. 
Da wir für das folgende switch-Statement Zeichen und keine Ziffern betrachten, müssen die Zahlen in Hochkommata!
Ich habe Dir eine Funktion gebaut, die die Binärzahl dezimal ausgibt (dec()) -- die anderen beiden kannst Du ja noch hinzufügen. Es ist eine geläufige Praxis, die Größe eines Datenbereichs an eine Funktion mit zu übergeben -- so habe ich das mit der Anzahl der Bits auch gemacht.
Poste doch noch, wie Du die folgenden Funktionen hex() und oct() implementieren würdest. 


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

int dec(int bin[], int bits);

int main(void)
{
        char buf[11];
        int bin[10];
        int i, ergebnis, bits = 0;

        /* Erstmal den Puffer ausnullen */
        memset(buf, '\0', sizeof(buf));

        printf("Binärzahl eingeben: ");
        /* Achtung, Zahlen werden im ASCII Code gelesen */
        fgets(buf, sizeof(buf), stdin);

        for (i = 0; i < 10; ++i) {
                if (buf[i] == '\n' || buf[i] == '\0')
                        break;
                if (buf[i] != '1' && buf[i] != '0') {
                        fprintf(stderr, "Nur 1 oder 0 erlaubt!\n");
                        exit(EXIT_FAILURE);
                }
                /* Minus 48 wg. ASCII Repräsentation */
                bin[i] = buf[i] - 48;
                ++bits;
                printf("%d ", bin[i]);
        }

        printf("\n\nUmrechnung auswählen:\n");
        printf("<1> Umrechnung in Dezimal\n");
        printf("<2> Umrechnung in Hexadezimal\n");
        printf("<3> Umrechnung in Oktal\n");
        printf("<4> Programm beenden\n");

        memset(buf, '\0', sizeof(buf));
        fgets(buf, sizeof(buf), stdin);

        switch(buf[0]) {
        case '1':
                ergebnis = dec(bin, bits);
                break;
        case '2':
                break;
        case '3':
                break;
        case '4':
                break;
        default:
                fprintf(stderr, "Unbekannte Auswahl!\n");
                exit(EXIT_FAILURE);
        }

        printf("\nErgebnis: %d\n", ergebnis);

        return 0;
}

int dec(int bin[], int bits)
{
        int i, tmp, ergebnis = 0, pos = 1;

        /* Jetzt wird runtergezählt */
        for (i = bits - 1; i >= 0; --i) {
                tmp = bin[i] * pos;
                ergebnis += tmp;
                pos *= 2;
        }

        return ergebnis;
}
```


----------



## zoj (18. April 2006)

Vielen Dank für deine Hilfe

ich habe das Programm ein wenig erweitert, also die Umrechnung in Hexadezimal und
Oktal.

Leider habe ich schon wieder Probleme :suspekt: 

Da ich mich noch nicht so lange mit C beschäftige fält mir das ganze noch ein wenig schwer.

Warum werden die Hexadezimal und Oktalwerte nicht ausgegeben  

Hier  der code:

```
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
	 
int dec(int bin[], int bits);
	 
int main(void)
    {
	        char buf[11];
	        int bin[10];
	        int i, ergebnis, bits = 0;
	 
	        /* Erstmal den Puffer ausnullen */
	        memset(buf, '\0', sizeof(buf));
	 
	        printf("Binarzahl eingeben: ");
	        /* Achtung, Zahlen werden im ASCII Code gelesen */
	        fgets(buf, sizeof(buf), stdin);
	 
	        for (i = 0; i < 10; ++i) 
            {
	                if (buf[i] == '\n' || buf[i] == '\0')
	                        break;
	                if (buf[i] != '1' && buf[i] != '0') 
                    {
	                        fprintf(stderr, "Nur 1 oder 0 erlaubt!\n");
	                        exit(EXIT_FAILURE);
	                }
                /* Minus 48 wg. ASCII Reprasentation */
	                bin[i] = buf[i] - 48;
	                ++bits;
	                printf("%d ", bin[i]);
	        }
	 
	        printf("\n\nUmrechnung auswahlen:\n");
            printf("<1> Umrechnung in Dezimal\n");
	        printf("<2> Umrechnung in Hexadezimal\n");
	        printf("<3> Umrechnung in Oktal\n");
	        printf("<4> Programm beenden\n");
	 
            memset(buf, '\0', sizeof(buf));
            fgets(buf, sizeof(buf), stdin);
	 
	        ergebnis = dec(bin, bits);
	 
             switch(buf[0]) 
             {
                       case '1':
                            printf("\nErgebnis: %d\n", ergebnis);                
                       break;
	                   case '2':
                            hex(ergebnis);
                       break;
                       case '3':
	                        okt(ergebnis);
                       break;
	                   case '4':
	                   break;
	                   default:
                       fprintf(stderr, "Unbekannte Auswahl!\n");
                       exit(EXIT_FAILURE);
	        }
	 
	        
	        system("PAUSE");
	        return 0;
	}
	 
	int dec(int bin[], int bits)
	{        
             int i, tmp, ergebnis = 0, pos = 1;         
             /* Jetzt wird runtergezahlt */        
             for (i = bits - 1; i >= 0; --i) 
             {                
                              tmp = bin[i] * pos;                
                              ergebnis += tmp;                
                              pos *= 2;        
             }         
             return ergebnis;
    } 
    int hex(int ergebnis)
    {
        int Rest;
        if(ergebnis <0)
        {
                    printf("Fehler!\n");
        }else {
              printf("Hex-Zahl: ");          
                    while (ergebnis < 0)
                    {
                          Rest = ergebnis %16;
                          ergebnis = ergebnis / 16;
                          if (Rest < 10)
                          {
                                   printf("d",Rest);
                          }else{
                                   switch (Rest)
                                   {
                                         case 10: printf("A");break;
                                         case 11: printf("B");break;
                                         case 12: printf("C");break;
                                         case 13: printf("D");break;
                                         case 14: printf("E");break;
                                         case 15: printf("F");break;
                                         default: printf(" :-)\n");break;
                                   }
                                }
                          }
                          
                          
                    }
                    printf("\n\n");
                    return 0;
              
    }
    
    
    int okt(int ergebnis)
    {
        
        if(ergebnis <0)
        {
                    printf("Fehler!\n");
                    while (ergebnis < 0)
                    {
                          int Rest;
                          Rest = 0;
                          Rest = ergebnis %8;
                          Rest *8;
                          printf("%d",Rest);
                          ergebnis = ergebnis / 8;
                    }
                    
                    return 0;
        }      
    }
```


----------



## deepthroat (18. April 2006)

Hi.


			
				zoj hat gesagt.:
			
		

> ```
> int hex(int ergebnis)
> {
> if(ergebnis < 0)
> ...


Wenn ergebnis kleiner 0, dann gebe "Fehler" aus, ansonsten (ergebnis >= 0) solange wie ergebnis *kleiner* 0 ... ?

Verwende doch bitte auch weiterhin die Code Tags.

Gruß


----------



## rohrbold (18. April 2006)

zoj hat gesagt.:
			
		

> Warum werden die Hexadezimal und Oktalwerte nicht ausgegeben
> 
> ```
> printf("\n\nUmrechnung auswahlen:\n");
> ...



Naja, also das kein anderes Ergebnis ausgegeben wird, ist ja logisch, da Du zum einen den printf() Aufruf mit dem Ergebnis ausschließlich für den switch-Fall '1' laufen läßt (Zeile 15) und zum anderen der Variablen ergebnis auch nie einen anderen Wert zuweist, als bei ergebnis = dec(bin, bits); in Zeile 10.
Du deklarierst die beiden Funktionen hex() und okt(), so dass sie eine Ganzzahl zurückliefern sollen, benutzt diesen Wert aber gar nicht.

Folgendes solltest Du machen: 
(1) Du brauchst eine gemeinsame Basis, von der Du in die einzelnen Werte umrechnest -- ich würde Dir das Binärsystem empfehlen, mit dem der Anwender ja auch die Werte eingibt. Also alle Funktionssignaturen entsprechend ändern (int hex(bin, bits) bzw. int okt(bin, bits)). Du wählst im Moment das Dezimalsystem, entsprechend müsstest Du Deine Funktionen zur Berechnung natürlich ändern.
(2) Die Funktionen müssen dem Compiler eigentlich bekannt sein, bevor sie aufgerufen werden. Deswegen musst Du entweder die Funktionssignaturen wie in meinem Beispiel mit dec() an den Anfang schreiben, oder die gesamten Funktionen selbst vor der main() Funktion, in der diese dann aufgerufen werden.
(3) Ich würde vorschlagen Du versuchst es wie folgt zu realisieren:

```
memset(buf, '\0', sizeof(buf));
        fgets(buf, sizeof(buf), stdin);

        switch(buf[0]) {
        case '1':
                ergebnis = dec(bin, bits);
                break;
        case '2':
                ergebnis = hex(bin, bits);
                break;
        case '3':
                ergebnis = okt(bin, bits);
                break;
        case '4':
                return 0;
        default:
                fprintf(stderr, "Unbekannte Auswahl!\n");
                exit(EXIT_FAILURE);
        }

        printf("\nErgebnis: %d\n", ergebnis);
```
Entsprechend erstellst Du dann die beiden kleinen Funktionen, die Dir eine Oktazahl oder Hexadezimalzahl aus einer Binärzahl erstellen.

Ein letzter Hinweis noch. Informiere Dich mal, wie Du bei Deinem Compiler einstellen kannst, dass er sämtliche Warnungen ausspricht. Mit dem gcc sieht ein Aufruf dann beispielsweise so aus: gcc -W -Wall -pedantic ... Dadurch lernst Du von vornherein sauberes Programmieren und wirst auch mal auf Schwachstellen hingewiesen (z.B. Anweisungen, die schlicht keinen Sinn ergeben oder Variablen, die nicht genutzt werden, etc.)


----------



## zoj (19. April 2006)

Vielen Dank für deine Hilfe! 
Du hast mir sehr geholfen, das Programm läuft  

FRalls es geht, könntest du mir vielleicht noch die Sache mit dem Buf erklären?


----------



## rohrbold (20. April 2006)

zoj hat gesagt.:
			
		

> FRalls es geht, könntest du mir vielleicht noch die Sache mit dem Buf erklären?



Naja, da gibt es nichts besonderes dran. Wir deklarieren einfach ein Array buf der Größe 11 vom Datentyp char, dessen Elemente wir mit buf[0] bis buf[10] erreichen können. Ein char-Array nehmen wir, weil die Funktion fgets(char * restrict str, int size, FILE * restrict stream) ein solches als ersten Parameter erwartet. Mit der Funktion memset(void *b, int c, size_t len) nullen wir dann erstmal alle Elemente aus ('\0' ist die binäre Null), so dass nicht zufällig ein anderer Wert irgendwo steht. sizeof(buf) liefert in diesem Fall die Größe des Arrays, also 11 zurück, so dass maximal 10 Elemente in unseren Puffer geschrieben werden (das ist aus Sicherheitsaspekten wichtig, damit nicht über den allozierten Speicherbereich hinaus geschrieben werden kann). Warum 10 und nicht 11 Elemente? Es wird von fgets so gehandhabt, dass das letzte Zeichen von der Funktion als '\0' gesetzt wird. Außerdem stoppt fgets das Einlesen beim Lesen eines '\n' (Newline) oder eines EOF. So sind wir nicht auf 10 binäre Ziffern festgelegt.
Die Elemente können wir dann eben über buf[0] bis buf[10] auslesen (wobei buf[10] mit '\0' belegt ist). Da die Elemente als char gespeichert wurden, befinden sich die gewünschten Zahlen in der ASCII Tabelle und dort liegt die Null auf Position 48 und die Eins auf Position 49. Du solltest Dir also über den Unterschied von 1, '1' und "1" in C bewußt sein (Zahl, Zeichen und Zeichenkette).
Mehr fällt mir auch nicht ein, oder gibt es noch Unklarheiten?


----------

