Probleme beim Einlesen



  • Guten Tag!

    Ich habe Probleme mit dem Einlesen von Werten. Ich programmiere in C.
    Folgender Code soll mein Problem schildern:

    unsigned short zahl1 = 0;
    unsigned short zahl2 = 0;
    printf("Bitte geben Sie eine Zahl von 0-255 ein!\n");
    scanf_s("%d", &zahl1);
    scanf_s("%d", &zahl2);
    

    Wenn ich diesen Code nun kompiliere und ausführe, schreibt er mir lediglich zahl2 in die Speicheradresse.
    zahl1 bleibt beim Wert '0'.
    Wenn ich nun den zweiten scanf_s Befehl wegnehme, schreibt er mir den korrekten Wert in die Speicheradresse von zahl1.

    Auch folgende Variante beschreibt mir nur die Speicheradresse von zahl2.

    scanf_s("%d%d", &zahl1, &zahl2);
    

    Was mache ich falsch?

    Vielen Dank für eure Hilfe!



  • @lebenso
    http://www.cplusplus.com/reference/cstdio/scanf/
    Ich schätze, Dein scanf sollte so aussehen:

    scanf_s("%hu", &zahl1);
    


  • @lebenso

    C++

    std::cin >> zahl1 >> zahl2;
    


  • @lebenso Der Formatspecifier %d ist zum einlesen von signed int in Dezimaldarstellung da.

    scanf beschreibt dabei ab der angegebenen Adresse (&zahl1) entsprechend viele Byte (sizeof(unsigned int)).

    Wenn jetzt sizeof(unsigned short) kleiner als sizeof(unsigned int) ist, werden falsch Speicherstellen überschrieben. (auf aktuellen Systemen ist das meist 2 und 4)

    Wenn du in deinem Beispiel mal eine negative Zahl eingibst, dann wird zahl1 auch einen anderen Wert haben.

    BTW: Wie überprüfst du denn den Inhalt von zahl1 und zahl2?



  • @lebenso sagte in Probleme beim Einlesen:

    Ich programmiere in C.

    Und warum postest du dann im C++ Unterforum?



  • Hallo @lebenso,

    Erstens: wähle das richtige Unterforum (dieses hier ist "C++", nicht "C" - wichtiger Unterschied).
    Zweitens: du solltest bei deinem Compiler Warnungen aktivieren! Bei gcc geht das mit -Wall -Wextra (für Visual Studio wahrscheinlich /W4, musst du mal schauen). Wenn du damit compilierst, bekommst du folgende Ausgabe (oder ähnlich), in welcher die Ursache und die Abhilfe beschrieben wird.

    <source>: In function 'main':
    <source>:7:13: warning: format '%d' expects argument of type 'int *', but argument 2 has type 'short unsigned int *' [-Wformat=]
        7 |     scanf("%d", &zahl1);
          |            ~^   ~~~~~~
          |             |   |
          |             |   short unsigned int *
          |             int *
          |            %hd
    <source>:8:13: warning: format '%d' expects argument of type 'int *', but argument 2 has type 'short unsigned int *' [-Wformat=]
        8 |     scanf("%d", &zahl2);
          |            ~^   ~~~~~~
          |             |   |
          |             |   short unsigned int *
          |             int *
          |            %hd
    


  • @DirkB

    Vielen Dank für deine Antwort und Erklärung, jetzt wird mir einiges klarer. So etwas in die Richtung hatte ich mir schon gedacht , da %c ja auch einen char als Eingabe erwartet. Mir waren noch nicht alle format-specifier bekannt.
    In meinem Programm habe ich mir die letzten beiden Bits jeweils in eine Variable gepackt (mit %2 und /2%2 ausgerechnet) und diese dann ausgegeben zur Uberprüfung (natürlich nur Werte eingegeben die auch mit diesen zwei Bits darstellbar sind) und dort hat er eben nur die Bitstellen der zahl2 richtig ausgegeben. Hier das Codebeispiel:

    z1_0 = zahl1 % 2; //zahl1 0. Bit
    z1_1 = (zahl1 / 2) % 2; //zahl1 1.Bit
    z2_0 = zahl2 % 2; //zahl2 0.Bit
    z2_1 = (zahl2 / 2) % 2; //zahl2 1.Bit
    //Ausgabe für zahl1 = 3 und zahl2 = 3:  z1_1 = 0, z1_0 = 0, z2_1 = 1 und z2_0 = 1.
    

    @wob Es war schon etwas später und ich habe das Unterforum auf Anhieb nicht entdeckt. Habe es aber nun gefunden und werde in Zukunft natürlich dort posten.
    Aber auch dir vielen Dank für deine Antwort und den Tipp. Werde ich gleich umsetzen, genau das hätte mir den Gang zum Forum erspart lach

    LG



  • @lebenso

    BTW: Wie überprüfst du denn den Inhalt von zahl1 und zahl2?

    Damit meinte ich eigentlich, welchen Formatspecifier du bei printf genutzt hast.
    Denn auch da muss der zum Variablentyp passen, allerdings werden da Typen, die kleiner als int sind in int umgewandelt.
    Darum fallen da Fehler noch weniger auf.

    scanf undprintf sind aber unterschiedliche Funktionen und die Formatspecifier unterscheiden sich durchaus.



  • @DirkB sagte in Probleme beim Einlesen:

    @lebenso

    BTW: Wie überprüfst du denn den Inhalt von zahl1 und zahl2?

    Damit meinte ich eigentlich, welchen Formatspecifier du bei printf genutzt hast.
    Denn auch da muss der zum Variablentyp passen, allerdings werden da Typen, die kleiner als int sind in int umgewandelt.
    Darum fallen da Fehler noch weniger auf.

    scanf undprintf sind aber unterschiedliche Funktionen und die Formatspecifier unterscheiden sich durchaus.

    Achso, bei printf habe ich auch den %d specifier benutzt, da mir der für unsigned und short nicht bekannt war.



  • @lebenso sagte in Probleme beim Einlesen:

    z1_0 = zahl1 % 2; //zahl1 0. Bit
    z1_1 = (zahl1 / 2) % 2; //zahl1 1.Bit
    z2_0 = zahl2 % 2; //zahl2 0.Bit
    z2_1 = (zahl2 / 2) % 2; //zahl2 1.Bit
    //Ausgabe für zahl1 = 3 und zahl2 = 3:  z1_1 = 0, z1_0 = 0, z2_1 = 1 und z2_0 = 1.
    

    Ja nee.

    z1_0 =    zahl1 & 0x01;
    z1_1 = !!(zahl1 & 0x02);
    // ...
    

    Läuft zwar bei einem nicht ganz doofen Compiler wahrscheinlich auf den selben generierten Opcode raus, aber so ist es menschenlesbarer und damit vorzuziehen.

    PS: Vielleicht überlegst Du Dir schönere Namen für Deine Variablen. Arrays gibt es auch.

    PPS: Es ist zwar schon darüber geschrieben worden aber um es klarzustellen: Passen deine Conversion Spezifier im Formatstring von scanf() nicht zu den Argumenten dann hat dein Programm Undefined Behaviour. Es darf dann alles mögliche passieren und Dein Programm ist dann auch strenggenommen kein C-Programm mehr.


Log in to reply