einzelne Ziffern einer Zahl auslesen



  • Hallöchen

    wie kann ich die einzelnen Ziffern einer int zahl auslesen?

    also z.b. 235

    z1 = 2;
    z2 = 3;
    z3 = 5;

    ich habe bischen mit % rumprobiert aber da bekomme ich ja immer nur die letzte zahl oder?

    vielen Dank



  • Hi,

    % 10 ist eine gute Idee. Wenn Du jetzt vorher noch durch 10 hoch (Stelle - 1) teilst, kannst Du auch die Stelle auswählen.



  • Otz110 schrieb:

    ich habe bischen mit % rumprobiert aber da bekomme ich ja immer nur die letzte zahl oder?

    Der Ansatz ist schon mal nicht schlecht. Du hast recht, man bekommt nur die letzte Zahl. Wäre das nicht toll, wenn man die letzte Zahl jetzt abschneiden könnte? Dann könnte man nämlich gleich noch mal die letzte Zahl auslesen. Und so weiter. yay. 😉

    Edit @Eisflamme
    Sag doch nicht gleich alles, ist doch viel befriedigender wenn man es selbst rausfindet. -.-



  • int zahl = 12345;
    	while(zahl){
               cout<<zahl%10 << endl;
    	   zahl/=10;
    	}
    

    ausgabe:
    5
    4
    3
    2
    1

    wie gesagt benötige ich aber zuerst die höchstwertige ziffer also in dem beispiel die 1 da ich die zahl in ein array eintragen möchte...



  • Otz110 schrieb:

    wie gesagt benötige ich aber zuerst die höchstwertige ziffer also in dem beispiel die 1 da ich die zahl in ein array eintragen möchte...

    Das geht nicht. Also es geht schon, aber da musst du zu erst errechnen wie viele Stellen die Zahl in dem gewünschten Zahlensystem hat, und das Array dann rückwärts beschreiben. (Die "einfache" Lösung wäre halt die Zahlen so in ein Array zu schreiben und dann mit z.B. std::reverse() umzudrehen.)



  • cooky451 schrieb:

    (Die "einfache" Lösung wäre halt die Zahlen so in ein Array zu schreiben und dann mit z.B. std::reverse() umzudrehen.)

    ahh das klingt nicht schlecht... das teste ich mal. melde mich gleich wieder 🙂



  • cooky: Er musste ja immerhin das eine und das andere noch hintereinanderschreiben und er hat keinen Code bekommen... :>

    Aber schau, es hat ihn ja eh nicht befriedigt.



  • Mit Rekursion ginge das hübsch:

    void print_vertically(unsigned x) {
      if(x >= 10) {
        print_vertically(x / 10);
      }
    
      std::cout << x % 10 << '\n';
    }
    

    Die Einbindung des Arrays ist Übungsaufgabe.



  • nochmal ne Frage 🙂

    wie finde ich raus wie groß ich das Array machen muss in dass ich die Zahl reinschreibe. Dazu benötige ich ja die Anzahl der Deziamalstellen der Zahl.

    Im Netz habe ich jetzt etwas mit dem Log gefunden. Dazu benötige ich aber die math.h und ich will das Ganze ohne Stl machen.

    Dann dachte ich mir ich zähle einfach durch:

    int count = 0;
    
    	while(zahl){
    
    	zahl= zahl/10;
    	count++;
    
    	}
    

    und geb den Zählwert als Länge an das Array.
    -> Fehler, der Wert muss konstant sein 🙂

    habt ihr hierfür auch nochn Tipp für mich?



  • Ich hab ein paar Methoden ausprobiert. Ich habe keinen effizienten Algorithmus gefunden daher würde es denke ich schneller sein das ganze als ein string zu betrachten. 😕

    {
                int zahl = 12345;
                int zahlLänge = GetZahlLänge(zahl);
                int[] ziffern = new int[zahlLänge];
    
                for(int i = 0;i < zahlLänge;i++)
                {
                    ziffern[i] = zahl % 10;
                    zahl /= 10;
                }
    
                for (int i = zahlLänge-1; i >= 0; i--)
                {
                    MessageBox.Show(string.Format("Ziffern: {0}",ziffern[i]));
    
                }
    
            }
    
            private int GetZahlLänge(int zahl)
            {
                int länge = 0;
                int teiler = 1;
                while (zahl / teiler >= 1)
                { länge++; teiler = teiler * 10; }
    
                return länge;
            }
        }
    


  • Patrickssj6 schrieb:

    Ich hab ein paar Methoden ausprobiert. Ich habe keinen effizienten Algorithmus gefunden daher würde es denke ich schneller sein das ganze als ein string zu betrachten. 😕

    {
                int zahl = 12345;
                int zahlLänge = GetZahlLänge(zahl);
                int[] ziffern = new int[zahlLänge];
    
                for(int i = 0;i < zahlLänge;i++)
                {
                    ziffern[i] = zahl % 10;
                    zahl /= 10;
                }
    
                for (int i = zahlLänge-1; i >= 0; i--)
                {
                    MessageBox.Show(string.Format("Ziffern: {0}",ziffern[i]));
                
                }
    
            }
    
            private int GetZahlLänge(int zahl)
            {
                int länge = 0;
                int teiler = 1;
                while (zahl / teiler >= 1)
                { länge++; teiler = teiler * 10; }
    
                return länge;
            }
        }
    

    will keine STL benutzen und ne eigene Stringklasse möchte ich auch nicht schreiben 🙂

    dass muss irgendwie anderst gehen.



  • Du kannst natürlich auch von vorne anfangen, dazu musst du wissen, wieviele Stellen deine Zahl hat (bekommt man mit log10 raus). Alles weitere wie oben, musst aber ein bisschen mehr rechnen.



  • für log benötige ich doch auch die math.h oder??



  • Otz110 schrieb:

    dass muss irgendwie anderst gehen.

    klar geht das auch anders - etwa so:

    #include <iostream>
    #include <cassert>
    
    template< typename T, typename Out >
    Out to_digits( T zahl, Out out )
    {
        assert( zahl >= 0 );
        char ziffer = '0' + zahl%10; // hier wird die Ziffer der letzten(!) Stelle bestimmt
        if( (zahl /= 10) != 0 )
            out = to_digits( zahl, out ); // daher zuerst die Ziffern vor(!) der letzten Stelle bestimmen
        *out++ = ziffer; // und erst danach die letzte Ziffer wegschreiben
        return out;
    }
    
    int main()
    {
        using namespace std;
        char ziffern[200]; // wir wissen ja nicht wie gross die Zahl wird !?
        for( int x; cout << "> ", cin >> x; )
        {
            *to_digits( x, ziffern ) = char(0); // String-Ende setzen
            cout << "Ziffern: " << ziffern << endl; // zur Kontrolle die Ziffernfolge ausgeben
        }
        return 0;
    }
    


  • Genau so hätte ich es dann auch getan aber der code ist einfach so häßlich...alleine das array mit unbestimmter Größe.



  • Patrickssj6 schrieb:

    Genau so hätte ich es dann auch getan aber der code ist einfach so häßlich...alleine das array mit unbestimmter Größe.

    stimmt - aber hier ist ja einer der es gerne kompliziert, aufwendig und fehlerträchtig haben möchte:

    Otz110 schrieb:

    will keine STL benutzen und ne eigene Stringklasse möchte ich auch nicht schreiben 🙂



  • Hübsch wär es mit std::stringstream.

    Wenn man allerdings darauf besteht, C mit anderen Headern zu schreiben, geht das auch mit variabler Bufferlänge - man muss halt nur mitzählen. Beispielsweise:

    #include <iostream>
    
    char *my_itoa_aux(unsigned x, unsigned &pos, unsigned depth) {
      char *buffer;
    
      if(x >= 10) {
        buffer = my_itoa_aux(x / 10, pos, depth + 1);
      } else {
        buffer = new char[depth + 1];
        buffer[depth] = '\0';
      }
    
      buffer[pos] = '0' + x % 10;
      ++pos;
      return buffer;
    }
    
    char *my_itoa(unsigned x) {
      unsigned pos = 0;
      return my_itoa_aux(x, pos, 1);
    }
    
    int main() {
      char *p = my_itoa(1234);
    
      std::cout << p << std::endl;
    
      delete[] p;
    }
    


  • seldon schrieb:

    Mit Rekursion ginge das hübsch

    Das ist immer noch nicht schön. -.-
    Und überhaupt, was ist los mit dir, mit new allozierten Speicher aus einer Funktion zurückgeben? 😮



  • In Produktionscode würde ich solchen Unfug natürlich nie einsetzen - für so was gibt's die Standardbibliothek. Unter den gegebenen Beschränkungen sehe ich aber nichts bedeutend besseres. Das Problem ist ja, dass ich erst in der innersten Rekursionsebene weiß, wie viel Speicher ich brauche - vorher allozieren ist also nicht drin.

    Ich hätte jetzt noch einen RAII-Wrapper um den Zeiger herumschreiben können, und wenn ich etwas derartiges einsetzen hätte wollen, hätte ich es auch getan, aber hier, für solchen Kram? Lassen wir die Kirche im Dorf, in der Stadt können wir sie nicht gebrauchen.

    Was Heap-Speicher aus einer Funktion angeht: Das macht (fast) jede Factory so. Wie sollte sie es auch anders machen? Man kann im Einzelfall darüber nachdenken, gleich Smart-Pointer zurückzugeben, aber immer ist das auch nicht praktikabel. Außerdem: Wenn man Heap-Objekte in Containern ablegt, überleben sie häufig auch die Funktion, in der sie angefordert wurden. Es ist eines der kennzeichnenden Merkmale von Heap-Objekten, dass sie den Stapelrahmen, in dem sie angelegt werden, überdauern.

    Was dagegen (meistens) wenig Sinn macht, ist, Heap-Objekte in der selben Funktion anzulegen, in der man sie wieder löschen will - da sollte man besser den Stack bemühen. Und wenn man mit Arrays arbeitet, deren Länge man zur Compilezeit nicht kennt, benutzt man besser std::vector als nacktes new[] und delete[].



  • seldon schrieb:

    Unter den gegebenen Beschränkungen sehe ich aber nichts bedeutend besseres.

    Was waren denn die Bedingungen? Kein std::string, keine Container, keine STL, ..?
    Trotzdem, warum nicht gleich ein typisches C Interface?

    char* my_itoa(unsigned n, char *buf)
    {
      char *p = buf, *q = buf;
      do {
        *p++ = '0' + n % 10;
        n /= 10;
      } while (n != 0);
      *p = '\0';
      while (p > q) // std::reverse() oO
      {
        char c = *q;
        *q++ = *(--p);
        *p = c;
      }
      return buf;
    }
    


  • Woher weißt du da, wie groß buf sein muss?


Anmelden zum Antworten