Zahl ala 0001 im String inkrementieren



  • Hey, wie der Titel schon sagt, habe ich mehrere Zahl der Form "0001" vorliegen.
    Ich möchte jetzt einem String die Zahl aus einem anderen um 1 erhöht zuweisen.

    Bsp: 2. String ist 0013, dann soll erster String 0014 werden.

    Vorschläge? 🙂

    EDIT: Die Zahlen liegen nicht als richtiger String vor, sondern sind in meiner selbst geschriebenen Stringklasse mit dem Member char* pBuf.



  • Nachdenken.



  • vorschlagor schrieb:

    Nachdenken.

    Mein Vorschlag wäre ja, den zweiten String erstmal mit atoi() in einen Int zu verwandeln und diesen dann zu erhöhen. Und wie bekomm ich die Zahl von int dann wieder in meine String-Klasse, dazu noch in der richtigen Form?


  • Mod

    Kennst du diese Zählwerke, wo man eine Taste drückt und dann zählen sie eins hoch? So:
    http://en.wikipedia.org/wiki/File:CountersMechanical.agr.jpg

    Wie haben es die Ingenieure wohl hinbekommen, diese Wunderwerke ohne atoi und ints zu bauen? 😉



  • Also so etwas wie string1[3]=9? -> string2[3]=0; string2[2]++;

    Von der Art her? Gibts da keine leichtere Möglichkeit?
    Z.b. eine Art Stream, wo ich die als int umgewandelte und inkrementierte Zahl wieder in ein char* laden kann und vorher mit setfill('0') und setw(4) manipulieren kann?


  • Mod

    psp-mufflon schrieb:

    Also so etwas wie string1[3]=9? -> string2[3]=0; string2[2]++;

    Von der Art her?

    Ja. Kann man natürlich auch in geschickt machen, anstatt mit einer Reihe Einzelprüfungen.

    Gibts da keine leichtere Möglichkeit?
    Z.b. eine Art Stream, wo ich die als int umgewandelte und inkrementierte Zahl wieder in ein char* laden kann und vorher mit setfill('0') und setw(4) manipulieren kann?

    Möglich wäre das, aber das kommt dir leichter vor? 😕
    Da fehlen als Zwischenschritte mindestens noch ausdrucken, abfotografieren, Foto einscannen, Scan durch OCR jagen, OCR-Ergebnis an einen Webservice in der Cloud schicken, Ergebnis per Briefpost als Barcode zuschicken lassen, Barcode einscannen, am Bildschirm anzeigen, mit Handy den Barcode vom Bildschirm lesen, Ergebnis an Faxservice schicken, Fax an sich selber schicken, Modem an Faxgerät anschließen, vom Modem das Endergebnis einlesen.
    Das wäre einfach.



  • Das hilft mir irgendwie grad alles nicht weiter, ich steh total auf dem Schlauch^^ Ich schau mal ne Folge Dexter und denk in Ruhe drüber nach, vielleicht ist das dann bisschen verständlicher 😉



  • Kaum getestet:

    #include <iostream>
    #include <cstring>
    
    int increment_digit(char* p, int carry)
    {
    	// Annahme: Die Ziffern 0-9 folgen im Zeichensatz aufeinander
    	int digit = *p - '0' + carry;
    
    	*p = (digit % 10) + '0';
    
    	return digit / 10;
    }
    
    int increment_iterative(char* str)
    {
    	char* p = str + std::strlen(str) - 1;
    	int carry = 1;
    
    	do
    	{
    		carry = increment_digit(p--, carry);
    	}
    	while (p - str >= 0 && carry);
    
    	return carry;
    }
    
    int increment_recursive(const char* str, char* p, int carry)
    {
    	carry = increment_digit(p--, carry);
    
    	if (p - str >= 0 && carry)
    		return increment_recursive(str, p, carry);
    	else
    		return carry;
    }
    
    int increment(char* str, bool recursive)
    {
    	// Annahme: Der String besteht garantiert nur aus Ziffern und ist nicht leer
    	if (recursive)
    		return increment_recursive(str, str + std::strlen(str) - 1, 1);
    	else
    		return increment_iterative(str);
    }
    
    int main()
    {
    	char str[] = "00";
    
    	for (int i = 0; i <= 100; ++i)
    	{
    		std::cout << "Str: " << str;
    		if (increment(str, false))
    			std::cout << " Overflow";
    		std::cout << "\n";
    	}
    }
    


  • Hab es jetzt so gelöst:

    char* increment(char* other)
    {
        int tmp=atoi(other);
        tmp++;
        char* res=new char[strlen("0000")];
        if(tmp<10) sprintf(res,"000%d",tmp);
        if(tmp<100)  sprintf(res,"00%d",tmp);
        if(tmp<1000) sprintf(res,"0%d",tmp);
        else sprintf(res,"%d",tmp);
        return res;
    }
    


  • GyroGearloose schrieb:

    Kaum getestet:

    #include <iostream>
    #include <cstring>
    
    int increment_digit(char* p, int carry)
    {
    	// Annahme: Die Ziffern 0-9 folgen im Zeichensatz aufeinander
    	int digit = *p - '0' + carry;
    
    	*p = (digit % 10) + '0';
    
    	return digit / 10;
    }
    
    int increment_iterative(char* str)
    {
    	char* p = str + std::strlen(str) - 1;
    	int carry = 1;
    
    	do
    	{
    		carry = increment_digit(p--, carry);
    	}
    	while (p - str >= 0 && carry);
    
    	return carry;
    }
    
    int increment_recursive(const char* str, char* p, int carry)
    {
    	carry = increment_digit(p--, carry);
    
    	if (p - str >= 0 && carry)
    		return increment_recursive(str, p, carry);
    	else
    		return carry;
    }
    
    int increment(char* str, bool recursive)
    {
    	// Annahme: Der String besteht garantiert nur aus Ziffern und ist nicht leer
    	if (recursive)
    		return increment_recursive(str, str + std::strlen(str) - 1, 1);
    	else
    		return increment_iterative(str);
    }
    
    int main()
    {
    	char str[] = "00";
    
    	for (int i = 0; i <= 100; ++i)
    	{
    		std::cout << "Str: " << str;
    		if (increment(str, false))
    			std::cout << " Overflow";
    		std::cout << "\n";
    	}
    }
    

    Oh danke, hatte gar nicht gesehen, dass du noch geschrieben hattest.. Meine Lösung ist deiner ja ähnlich, nur ein bisschen einfacher gehalten.. 😃



  • psp-mufflon schrieb:

    Oh danke, hatte gar nicht gesehen, dass du noch geschrieben hattest.. Meine Lösung ist deiner ja ähnlich, nur ein bisschen einfacher gehalten.. 😃

    Nee, die sind sich überhaupt nicht ähnlich. :p Außerdem schreibt deine Lösung sonstwo in den Speicher, da dein res nicht vernünftig initialisiert ist.

    Mein Code sieht nur soviel aus, weil ich zwei verschiedene Verfahren vorgeschlagen habe. Wenn man die iterative Lösung etwas komprimiert, sieht sie so aus:

    #include <cstring>
    #include <cctype>
    
    bool increment(char* str)
    {	
    	int carry = 1;
    
    	for (char* ptr = str + std::strlen(str) - 1; carry && ptr - str >= 0 && std::isdigit(*ptr); --ptr)
    	{
    		// Annahme: Die Ziffern 0-9 folgen im Zeichensatz aufeinander
    		int digit = *ptr - '0' + carry;
    		*ptr = (digit % 10) + '0';
    		carry = digit / 10;
    	}
    
    	return carry;
    }
    

    Die sollte mit beliebig langen Strings, mit leeren Strings und mit Strings, die ggf. was anderes als Ziffern enthalten (bricht dann ab), klar kommen.



  • psp-mufflon schrieb:

    Hab es jetzt so gelöst:

    char* increment(char* other)
    {
        int tmp=atoi(other);
        tmp++;
        char* res=new char[strlen("0000")];
        if(tmp<10) sprintf(res,"000%d",tmp);
        if(tmp<100)  sprintf(res,"00%d",tmp);
        if(tmp<1000) sprintf(res,"0%d",tmp);
        else sprintf(res,"%d",tmp);
        return res;
    }
    

    😮

    Sorry, aber das ist eine recht bescheidene "Lösung". So geht man nicht mit Resourcen (wie z.B. dynamisch reservierten Speicher) um. So ist die Speicherleckgefahr einfach zu hoch. Dazu hast du auch noch zuwenig Speicher reserviert. Lass diesen new char[soundso] -Kram ganz sein und verwende stattdessen std::string oder arbeite wenigstens in-place.

    Du kannst doch zählen, oder? Wie geht das denn? Fällt dir da kein System auf? Du fängst bei der letzten Ziffer an. Eine Schleife. Wenn die aktuelle Ziffer kleiner als 9 ist, erhöhst du sie einfach und brichst ab (weil fertig). Wenn sie 9 ist, setzt du sie auf 0 und machst links daneben weiter. Und wenn es irgendwann kein "links daneben" gibt, hast du einen Überlauf, den man ignorieren oder sonst wie anders behandeln kann, je nachdem, was du willst.



  • psp-mufflon schrieb:

    Hab es jetzt so gelöst:

    char* increment(char* other)
    {
        int tmp=atoi(other);
        tmp++;
        char* res=new char[strlen("0000")];
        if(tmp<10) sprintf(res,"000%d",tmp);
        if(tmp<100)  sprintf(res,"00%d",tmp);
        if(tmp<1000) sprintf(res,"0%d",tmp);
        else sprintf(res,"%d",tmp);
        return res;
    }
    

    Kannst du dir nicht mal die Doku zu printf durchlesen?
    Das f am Ende von printf steht übrigens für formated.
    Und das hat seinen Grund.
    Ein sprintf(res,"%04d",tmp); macht alles was du willst: 4 Stellen und führende Nullen.
    Eine schöne formatierte Ausgabe.


Log in to reply