Mit "Sscanf" String auf Int durchsuchen



  • Richtige Programmierer, für die ist C gemacht, können die Bits auch in Oktal- und Hex-Darstellung sehen. 😃

    Bei der Ausgabe auf den Bildschirm/Datei wäre putchar('0'); bzw putchar('1'); angebracht.
    Mit printf ist da nix.

    Es sei denn du baust dein eigenes itoa. Da wird das ergebniss als String abgelegt.
    Da kannst du dann printf("%s", itoa(x,str,2)); machen. (oder ein itoa2, das nur in Dualzahlen wandelt)

    Eine Möglichkeit:
    Du hast eine Bitmaske, in der nur ein Bit gesetzt ist. Am Besten das MSB, da dies ja zuerst ausgegeben werden soll.

    Diese Maske verundest du mit deinem Wert. An der Stelle, wo beide Zahlen das geliche Bit gesetzt haben, bleibt diese Bit auch gesetzt.

    10100101 Wert
    10000000 Maske
    -------- &
    10000000 Ergebnis ist ungleich 0 -> Bit ist 1. '1' ausgeben oder im String speichern

    Dann wird die Maske um eine Stelle nach rechts verschoben und der Vorgang wiederholt
    10100101 Wert
    01000000 Maske
    -------- &
    00000000 Ergebnis ist 0 -> Bit ist 0. '0' ausgeben oder im String speichern

    Wieder eine Stelle verschiebn, verunden, ... usw, bis die Maske 0 ist.

    Das ganze bitte mit unsigned Werten, denn nur da ist garantiert, das beim rechtsschieben auch eine 0 vorne eingschoben wird.



  • 10100101 Wert
    10000000 Maske
    -------- &
    10000000 Ergebnis ist ungleich 0 -> Bit ist 1. '1' ausgeben oder im String speichern

    Dann wird die Maske um eine Stelle nach rechts verschoben und der Vorgang wiederholt
    10100101 Wert
    01000000 Maske
    -------- &
    00000000 Ergebnis ist 0 -> Bit ist 0. '0' ausgeben oder im String speichern

    Das werd ich mal ausprobieren.
    Dann sehen wir weiter. Evtl. lass ich dann die %=2 bzw. /=2 Sache bleiben...... 🙄 ➡ 🕶



  • Nachtrag... Mir ist noch was eingefallen. Für meinen Ursprünlichen Gedanken, also mit % und / ... da wollte ich auch gleich mit putchar ausgeben...
    Geht ja nicht, müsste das "Ergbnis" ja erst drehen...
    Gibt´s nen ROL befehl?

    5%2 != 0 ? putchar("1") : putchar("0")
    ....
    Weißt du wie ich meine?



  • Habs jetzt mal "my-Way" gemacht...also die "Teilen" Variante.

    Ist noch nicht ganz fertig, funktioniert aber erstmal.

    #include <stdio.h>
    #include <stdlib.h>
    #define _MEM  (sizeof(int)*8)
    #define LSB (sizeof(int)*8-1)
    #define HIGH '1'
    #define LOW '0'
    
    void tobin(void){
    
    char bin[_MEM], *show;
    int init, i,j, erg;
    
    bin[_MEM]='\0';
    for(init=0; init<_MEM; init++)
                bin[init]='0';
    
    i=2569;
    j=0;
    do{
       if ((i%2)!=0){
                    puts("Rest");
                    printf("i : %d\n", i);
                    bin[LSB-j]=HIGH;
                    j++;
                    i/=2;
                    printf("i : %d\n", i);
    
           }
           else{
                puts("kein Rest");
                bin[LSB-j]=LOW;
                    j++;
                    i/=2;
                }
        system("pause");
    
    }while (i!=0); 
    j--; 
    show=&bin[LSB-j];   
    
    puts(show);     
    }
    

    Die Puts("rest")... und system("Pause") sind / waren nur zum Beobachten.
    Jetzt muss ich dann noch das Ergebnis zurückgeben und uint verwenden.
    Kann man den Rest so lassen?

    Die Variante mit >> << & | ist glaub ich eleganter, mit der setzte ich mich noch auseinander :p



  • Wie war das bei Arrays?

    // Wenn du ein Array hast
    char bin[_MEM]; // dann hat das _MEM Elemente.
                    // bezeichnet von 0 bis _MEM-1
    bin[_MEM]='\0'; // Das Element mit dem Index _MEM gibt es nicht !!!
    

    Alles was im if- und else-Zweig gleich ist, kannst du raus ziehen

    do {
        if ((i%2)!=0) {  // kann nur 1 sein
            bin[LSB-j]=HIGH;
        } else {
            bin[LSB-j]=LOW;
        }    
        j++;
        i/=2;
    
    } while (i!=0);
    

    Was bleibt ist dann

    do {
        bin[LSB-j]=(i%2)+'0';
        j++;  // Das könnte sogar noch bei bin[LSB-j++] stehen
        i/=2;
    } while (i!=0);
    


  • Und wenn du die 2 durch eine Variable ersetzt, kannst du so schon mal Zahlen bis zur Basis 10 anzeigen.

    Für andere Basen (bis 36) geht das so:

    static const char ziffern = "01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    
    do {
        bin[LSB-j]=ziffern[i%basis]
        j++;  
        i/=basis;
    } while (i!=0);
    


  • Wie war das bei Arrays?

    ...Shit, ich sollte nichts tippen oder veröffentlichen, wenn ich schon ein paar Bier getrunken habe.
    Mann ist das peinlich. Das sollte eigentlich nicht passieren 😡 😡 😡

    DIe verkürzungen, bzw. was raus kann /muss hab ich jetzt noch gemacht.
    Auch die String Rückgabe. (Dazu noch die Frage : Ist gängig so oder? Also nen String zurück geben, wird schon meist so gemacht oder? Der Aufrufer kümmert sich um den Speicher, nicht die Funition?)

    Hier der Code:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define _MEM  ((sizeof(int)*8)+1)      
    #define LSB ((sizeof(int)*8)-1)            
    #define HIGH '1'
    #define LOW '0'
    
    char* tobin(char *str, unsigned int value){
    
    char bin[_MEM], *show;
    int init, j=0, erg;
    
    bin[_MEM-1]='\0';   
    for(init=0; init<_MEM-1; init++)     // ich hab inits gern :-)
                bin[init]='0';
    
    do{
       if ((value%2)!=0){
                    bin[LSB-j]=HIGH;                
           }
           else{
                    bin[LSB-j]=LOW;
                }
        j++;
        value/=2;
    
    }while (value!=0); 
    
    show=&bin[LSB-(--j)];   
    
    strcpy(str, show);
    
    return (str);
    }
    

    Ich habe jetzt bewusst nicht weiter verkürzt, mir ist :

    do {
        bin[LSB-j]=(i%2)+'0';
        j++;  // Das könnte sogar noch bei bin[LSB-j++] stehen
        i/=2;
    } while (i!=0);
    

    klar, aber ich kann den obrigen Code in 2 Jahren auch noch ohne "nachdenken" lesen. Generell... mich persönlich stören ein paar Zeilen mehr nicht sooo, wenn ich mich später mal leichter mit lesen tu.



  • beginner88888 schrieb:

    Auch die String Rückgabe. (Dazu noch die Frage : Ist gängig so oder? Also nen String zurück geben, wird schon meist so gemacht oder? Der Aufrufer kümmert sich um den Speicher, nicht die Funition?)

    Ja.

    Einfacher wäre

    #define _MEM  ((sizeof(int)*8)    
    
    char bin[_MEM+1]; // und nur bei der Definition Einen mehr.
    

    Du kannst auch gleich auf str arbeiten, dann brauchst du bin nicht. (evtl musst du den String zum Schluss umdrehen)

    return ist keine Funktion, daher braucst du die Klammern nicht.

    beginner88888 schrieb:

    aber ich kann den obrigen Code in 2 Jahren auch noch ohne "nachdenken" lesen.

    Da ist show=&bin[LSB-(--j)]; aber schwieriger zu verstehen als bin[LSB-j]=(i%2)+'0';
    Wobei das größte Problem dabei das LSB-j ist.



  • evtl musst du den String zum Schluss umdrehen

    hmm... gibt´s da was fertiges oder muss ich das selbst basteln?



  • beginner_oofl schrieb:

    hmm... gibt´s da was fertiges oder muss ich das selbst basteln?

    Schau mal in der string.h

    Ich würde die Funktion strrev nennen.

    Wenn du nichts findest, musst du es selber machen. Ist aber nicht schwer, da du das Ende vom String schon hast.
    Da hast du ja eine '0' oder '1' abgelegt.



  • Werde morgen die "Shift" Variante probieren.

    Frage vorab, passt die "Maske" so?

    #include <stdio.h>
    #include <stdlib.h>
    #define _MEM sizeof(int)*8
    
    void shift(void){
    
    int mask;
    unsigned int value;
    
    mask= 0x1;
    mask<<=_MEM-1;
    

    Wenn ich das MSB "setzen" will , wäre das ja 0x80000000
    Also müsste das mit sizeof(int) ja passen?

    OFF Topic: eine potenzier funktion für INT hab ich auch nicht wirklich gefunden. Hab schon mal eine selber gemacht, aber etwas wie value= 2^5 geht nicht oder?



  • mask sollte auch unsigned sein.
    Deine Variante geht. Oder als Einzeiler mask = 1 << _MEM-1;

    beginner88888 schrieb:

    aber etwas wie value= 2^5 geht nicht oder?

    Doch, klar.
    Aber dafür braucht es keine Funktion. Du machst das da oben doch schon.
    Überleg mal, was ein links-Shift bedeutet. (Fang mit der 1 an und schiebe um eine Stelle)



  • 😡 Arr.... Wie war das mit dem Wald und den Bäumen...
    Klar, SHL 😡

    Aber etwas wie 5^7 krieg ich mit Shiften nicht hin...



  • Ich hab jetzt 2 Varianten mit der Rückgabe gemacht.
    Eine arbeitet direkt auf dem "Übergebenen" String, die andere nutzt nen "lokalen" String.

    Wie wäre das favorisierte Vorgehen? Bin ziemlich unschlüssig, irgendwie gefällt mir keine der beiden Farianten.

    V1:

    char* sh_bin(unsigned int value, char *str){
    
    unsigned int mask;
    char *show=NULL, *buffer=str;
    int erg=0 ;
    
    mask=0x1;      // =>   LSB is set 
    mask<<=_BITS-1;
    
    printf("Value in Dez :  %u\n", value);     
    str[_BITS]='\0';     
    
    while (mask !=0){
    
               if ((erg=value&mask)==0){                
                    *str='0';
                  } 
                    else{
                          *str='1';
                          if (show == NULL){
                              show=str;                           
                            }
                         }
             str++;     
             erg==0 ? putchar('0') : putchar('1');
             mask>>=1;
    
           }  
    *str='\0' ; 
    puts("\nValue in BIN 'cleared':");  
    puts(show);   
    str=buffer;  // set pointer back to starting adress
    strcpy(str, show);  
    
    return str;  
    
    }//END
    

    V2:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #define _BITS sizeof(int)*8
    
    char* to_bin4(unsigned int value, char* string){
    
    unsigned int mask ;
    unsigned int convert; 
    char str[_BITS+1], *show=NULL;  
    int erg=0, i=0 ;
    
    str[_BITS]='\0';
    
    mask=0x1;      // =>   LSB is set 
    mask<<=_BITS-1;
    
    printf("Value in Dez :  %u\n", value);     
    
    while (mask !=0){
    
               if ((erg=value&mask)==0){                
                    str[i]='0';
                  } 
                    else{
                          str[i]='1';
                          if (show == NULL){
                              show=&str[i];                           
                            }
                         }
             i++;     
             erg==0 ? putchar('0') : putchar('1');
             mask>>=1;
    
           }  
    
    puts("\nNow in Binary:\n"); 
    puts(str);
    puts(show); // Starts with "Leading" '1';
    strcpy(string, show);
    return string ;
    
    }
    

    Es gab auch noch ne 3. Variante, ähnlich der ersten, die direkt auf dem Übergebenen String , aber mit index arbeitet.
    Hmm....



  • Noch was... Wie würdet Ihr die "Rückwandlung" von dem String (10010 z.b.) in Dezimal machen?

    Habs jetzt mal mit " strtoul(string, NULL, 2) " gelöst...
    Dachte daran es selbst zu machen mit einer Maske wo jede Stelle Ihrem Wert zugedacht ist... 😕



  • Sind die beiden Varianten soo schlecht?? 😞



  • Verzichte auf das strcpy und den lokalel String.

    strcpy schrieb:

    destination ... should not overlap in memory with source.

    Zur Rückwandlung:
    Genau dafür wurde strtoul ja gemacht.

    Wenn du es trotzdem Probieren willst:

    char binzahl[] = "10100101";
    char *pc = binzahl;
    
    unsigned int result = 0;
    
    while (*pc) {
      result *= 2;
      result += (*pc -'0');
      ++pc;
    }
    

    Da fehlt aber noch der Test, ob es wirklich nur '0' oder '1' ist.
    Du bist aber nicht auf die 2 als Basis beschränkt. Bis 10 geht das auch.

    Und wenn du dich an http://www.c-plusplus.net/forum/p2376529#2376529 erinnerst, dann kannst du mit strchr und toupper sogar höhere Basen als 10 machen



  • Ok, Danke!

    Die Meldung gab mein DevC++ nicht aus.
    Ich weiß , das ist nicht die beste IDE, aber ich brauch was ziemlich kleines, was sich auch auf Arbeit auf unsere PC´s installieren lässt, ohne das die EDV mault..



  • Eventuell einfach alles, was nicht '0'-'9' ist auf space setzen, dann sollte es
    auf Anhieb funktionieren. Hab ich auch schon mal irgendwo gemacht.



  • Welche Meldung?
    Meinst du die von strcpy?
    Die gibt nicht der Compiler. Das steht in der Refernz / man-page zu strcpy.

    Schau mal auf der Startseite vom diesem Unterforum.
    Da gibt es eine Linkliste für Neulinge mit Links zu solchen Referenzen und auch zu den letzten Drafts von den verschidenen C Standards.


Anmelden zum Antworten