[c++] 1. Zeichen in char* löschen

Aloisia

Mitglied
Hallo, mein Problem ist das folgende: Ich bekomme einen char* number (Länge unterschiedlich) und will alle "führenden 0en" weghaben - Aus "00ef98vgF3" soll "ef98vgF3" werden (aber "0" bleibt "0", "00" wird "0")
Mein Ansatz ist:
l = Berechne die Länge des Strings
wenn l= 1, dann fertig
wenn nicht, dann prüfe ob 1. Zeichen 0 ist
wenn nein, fertig
wenn doch, dann "streiche es"; das heißt erschaffe einen buffer und schreib das 2te Element in das 1te des Buffers usw.
verwende nun die Werte des Buffers und lösche den Buffer
Starte den Test mit der neuen Zeichenkette erneut.

Was mache ich da falsch?

C++:
int l=strlen(number);

      while(l>1){
      if (number[0]=='0'){
         
      char* buf=new char[l-1];
         for (int i=0;i<l;i++){
         buf[i]=number[i+1];
         }
         
         number=buf;

         delete[] buf;
         l=strlen(number);
      }
      else{
      break;
      }
 
Hi und Willkommen bei tutorials.de,

andere Lösung:
Zähl zuerst die '0'´s, zB. in die Variable i.
Die ganze Bufferallozierung und Einzelumschichtung der chars dann ist
a) nicht pro 0 zu machen, sondern einfach ggf. mehrere Stellen auf einmal verschieben
b) Unnötig, weil das viel kürzer geht

C++:
//Zählen
int i = 0;
while(number[i] == '0')
    i++;

//dann:
memmove(number, &(number[i]), 1 + strlen(&(number[i])) );
 
Falls nein, mach vor der ganzen 0-Entferne-Aktion mal das:
C++:
printf("Laenge: %d\n", strlen(number));
puts(number);
getchar();
Ausgabe davon?
(Das Programm wartet dann auf einen Enter-druck, bevor es zur Problemstelle weitergeht.)

Und zeig, um sicher zu gehen, doch mal die Codestelle(n) her, wo number
angelegt/alloziert/übergeben wird.
 
Hallo Aloisia,

Du hast als Tag in deinem Titel "C++" angegeben, ich sehe da jetzt den Zusammenhang zu deinem Code, da hast du effektiv C verwendet. Variante mit C++
C++:
std::string removeLeadingZero(const std::string& number) {
	std::string::const_iterator itr = std::find_if(number.begin(), number.end(), 
		[](const char& c) {
			return c != '0';
		}
	);

	if(itr != number.end() && itr != number.begin()) {
		std::string tmp;
		std::copy(itr, number.end(), std::back_inserter(tmp));
		return tmp;
	} else if(itr == number.end() && number.size() > 1) {
		return "0";
	}

	return number;
}

...
	std::cout << removeLeadingZero("00ef4300aa") << std::endl;
	std::cout << removeLeadingZero("00") << std::endl;
	std::cout << removeLeadingZero("0") << std::endl;

Ausgabe:
ef4300aa
0
0

Grüsse
Cromon
 
Ich muss das als Übung programmieren: Eine Klasse die mit sehr großen natürlichen Zahlen rechnen kann... z.B.
C++:
Nat a= "123456789098765432";
Nat b= "3456545678765";
Nat c = a*b;
als natürliche Zahl berechnen...
Der Aufruf
C++:
Nat a = "1234567890987653";
muss funktionieren -> ich habe einen Konstruktor in meiner Klasse deklariert:
C++:
Nat(char* number="0");
(Standard ist laut Aufgabe 0)
Diesen Konstruktor habe ich dann außerhalb der Klassendeklaration definiert.
C++:
   Nat::Nat(char* number){
      number = sectZero(number);
...
}
Da keine führende 0 vorkommen soll dieser Schritt.
Weiterer Teil der Aufgabe ist dann die (verbleibende) char* Zeichenkette zu zerschneiden (je 2 Ziffern) und in ein Array einpflegen und dann damit rechnen.

Die Funktion
C++:
char * sectZero(char* number);
ist ebenfalls in der Klasse deklariert, außerhalb habe ich sie jetzt mit
C++:
    char* Nat::sectZero(char* number){


int i = 0;
while(number[i] == '0')
    i++;
 
//dann:
memmove(number, &(number[i]), 1 + strlen(&(number[i])) );
      return number;
   }
definiert.

Ich habe in meiner Recherche NATÜRLICH schon die verschiedensten Lösungen mit der String-Klasse gesehen, da wir diese in der Vorlesung noch nicht hatten will ich die eigentlich unbedingt vermeiden...Die Vorlesung führt von C(******!) ++ also fast nur C zum Objektorientierten C++ Programmieren. Generell ist das OO für mich nicht das große Problem, doch in Java und VB.net habe ich nur mit Strings gearbeitet, und die sind meiner Meinung nach viel handlicher als diese char*!
 
C++:
std::string removeLeadingZero(const std::string& number) {
	std::string::const_iterator itr = std::find_if(number.begin(), number.end(), 
		[](const char& c) {
			return c != '0';
		}
	);

	if(itr != number.end() && itr != number.begin()) {
		std::string tmp;
		std::copy(itr, number.end(), std::back_inserter(tmp));
		return tmp;
	} else if(itr == number.end() && number.size() > 1) {
		return "0";
	}

	return number;
}

...
	std::cout << removeLeadingZero("00ef4300aa") << std::endl;
	std::cout << removeLeadingZero("00") << std::endl;
	std::cout << removeLeadingZero("0") << std::endl;

Urgs, sei mir nicht böse, aber das ist extrem unlesbar. Und es ist C++11, das hat man auch evtl. nicht zur Verfügung.

Code:
std::string removeLeadingZero( const std::string& number ) 
{
  size_t  firstNotZeroPos = number.find_first_not_of( "0" );
  if ( firstNotZeroPos == std::string::npos )
  {
    // nur Nullen oder leer
    return "";
  }
  return number.substr( firstNotZeroPos );
}
 
Trotzdem noch kurz zu den char*:

zB. das:
C++:
Nat a = "1234567890987653";
und dein gezeigter Standardkonstruktor sind fixe Stringliterale...

Gib der Klasse ihren eigenen Speicher und kopier so übergebene Werte da rein,
bevor du sie änderst. Dann gehts.
 
Zurück