Hi Ich möchte zB einen String "AAA" an eine Funktion übergeben. Dann habe ich mir gedacht, diesen String in einem Array abzuspeichern und den Array durchzuiterieren und dabei immer die atoi Funktion zu benutzen. Jetzt habe ich das versucht zu realisieren, aber irgendwie habe ich Probleme dabei, die richtige Länge des Arrays anzugeben. Ich habe 2 Dinge versucht. void wandleString(uint8_t *string) { uint8_t code[] = "string"; } funktioniert ja nicht, weil ich immer wissen muss, wie lang ich den Array mache. Wenn ich jetzt eine Länge angebe als Parameter, kann man ja auch irgendetwas eingeben, was dann zu einem Fehler führen kann. void sendErrorCode(uint8_t *string) { uint8_t code[]; strcpy(code, string); } hier habe ich das Problem wieder mit der Länge. wie macht man so etwas?
Marwin schrieb: > void sendErrorCode(uint8_t *string) > { es wird ein Pointer auf "string" übergeben dessen Länge kann mit strlen(string); ermittelt werden. (ggffs. casten) strlen((char*)string); uint8_t laenge=strlen(string); // oder uint16_t oder uint32_t wie lang darfs werden? // dann Speicher reservieren malloc // nachlesen laenge+1 für Ende NULL > char* code= der reservierte Speicher aus malloc > strcpy(code, string); > > } wieso void? > void sendErrorCode(uint8_t *string) willst du code nicht zurückgeben? evtl. kannst du nach der Verarbeitung auch den reservierten Speicher von malloc freigeben.
Marwin schrieb: > wie macht man so etwas? Wenn du den Pointer übergibst und das ein String ist, dann wird ja direkt auf dem String gearbeitet und der ist (wie alle Strings in C) mit einer 0 terminiert. > wie macht man so etwas? Man fragt mit strlen() die Stringlänge ab und weiß dann, wie viele Zeichen bis zur ersten 0 (Stringende) da drin sind...
Marwin schrieb: > Dann habe ich mir gedacht, diesen String in einem Array abzuspeichern String und Array ist fast das gleiche. Du kannst den String auch direkt iterieren. Aber warum möchtest du atoi auf jedem Zeichen einzeln anwenden? Was soll atoi() auf einem String wie "AAA" bewirken? Das ist keine Zahl...
1 | void wandleString (const char* str) { |
2 | for (const char* p = str; *p; ++p) { |
3 | // Hier ist *p das aktuelle Zeichen
|
4 | }
|
5 | }
|
Dr. Sommer schrieb: > Marwin schrieb: >> Dann habe ich mir gedacht, diesen String in einem Array abzuspeichern > > String und Array ist fast das gleiche. Du kannst den String auch direkt > iterieren. Aber warum möchtest du atoi auf jedem Zeichen einzeln > anwenden? Was soll atoi() auf einem String wie "AAA" bewirken? Das ist > keine Zahl...void wandleString (const char* str) { > for (const char* p = str; *p; ++p) { > // Hier ist *p das aktuelle Zeichen > } > } Hallo miteinander Ich habe mich vllt. etwas unverständlich ausgedrückt, weil ich direkt in der Aufgabe vertieft war. Ich möchte zB ein Text 0-F, also 0-15 in einzelne Ziffern wandeln. zB AAA, BBB, B10 etc. Das möchte ich aber so direkt an eine Funktion übergeben zB "C99". Joachim B. schrieb: > Marwin schrieb: >> void sendErrorCode(uint8_t *string) >> { > > es wird ein Pointer auf "string" übergeben > dessen Länge kann mit strlen(string); ermittelt werden. (ggffs. casten) > strlen((char*)string); > > uint8_t laenge=strlen(string); // oder uint16_t oder uint32_t wie lang > darfs werden? > // dann Speicher reservieren > malloc // nachlesen laenge+1 für Ende NULL > >> char* code= der reservierte Speicher aus malloc >> strcpy(code, string); >> >> } > > wieso void? >> void sendErrorCode(uint8_t *string) > > willst du code nicht zurückgeben? Nein, ich will vorerst nur eine Umwandlung erreichen. Das ist die Aufgabe.
Marwin schrieb: > Ich möchte zB ein Text 0-F, also 0-15 in einzelne Ziffern wandeln. > zB AAA, BBB, B10 etc. atoi() ist hier nicht geeignet Eher schon strtol(), oder einer seiner Brüder, denn dort kann man die Zahlenbasis (hier 16) angeben.
Ich habe da mal etwas versucht. Funktioniert das so oder ist das kompletter Unsinn? Bitte um Hilfe void wandleUm(char *string) { uint8_t str_length; char str[10]; uint8_t code[10]; strcpy(str, string); uint8_t i=0; while(str[i] != '0') { code[i] = atoi(&str[i]); i++; } }
Marwin schrieb: > strcpy(str, string); Hier kann ein Buffer Overflow eintreten. Dein Kopieren ist komplett überflüssig, du kannst atoi auch direkt auf "string" anwenden. Allerdings funktioniert atoi so grundsätzlich nicht, da es immer gleich den ganzen String und nicht nur ein Zeichen verarbeitet. Wie wäre es so:
1 | void wandleString (const char* str) { |
2 | for (const char* p = str; *p; ++p) { |
3 | uint8_t digit; |
4 | if (*p >= '0' && *p <= '9') { |
5 | digit = *p - '0'; |
6 | } else if (*p >= 'a' && *p <= 'f') { |
7 | digit = *p - 'a'; |
8 | } else if (*p >= 'A' && *p <= 'F') { |
9 | digit = *p - 'A'; |
10 | } else { |
11 | puts ("Fehler: Ungültiges Zeichen in Eingabestring"); |
12 | digit = 0; |
13 | }
|
14 | // Hier mit "digit" weiter rechnen
|
15 | }
|
16 | }
|
So entfällt jegliches Kopieren und du kannst jede Ziffer direkt verarbeiten.
Marwin schrieb: > Ich habe da mal etwas versucht. > Funktioniert das so oder ist das kompletter Unsinn? Probiere es aus.
Marwin schrieb: > oder ist das kompletter Unsinn? Es ist kompletter Unsinn, da Du atoi wie folgt verwendest:
1 | atoi("string"); |
2 | atoi("tring"); |
3 | atoi("ring"); |
4 | atoi("ing"); |
5 | atoi("ng"); |
6 | atoi("g"); |
Dr. Sommer schrieb: > Marwin schrieb: >> strcpy(str, string); > > Hier kann ein Buffer Overflow eintreten. Dein Kopieren ist komplett > überflüssig, du kannst atoi auch direkt auf "string" anwenden. > Allerdings funktioniert atoi so grundsätzlich nicht, da es immer gleich > den ganzen String und nicht nur ein Zeichen verarbeitet. > > Wie wäre es so:void wandleString (const char* str) { > for (const char* p = str; *p; ++p) { > uint8_t digit; > if (*p >= '0' && *p <= '9') { > digit = *p - '0'; > } else if (*p >= 'a' && *p <= 'f') { > digit = *p - 'a'; > } else if (*p >= 'A' && *p <= 'F') { > digit = *p - 'A'; > } else { > puts ("Fehler: Ungültiges Zeichen in Eingabestring"); > digit = 0; > } > // Hier mit "digit" weiter rechnen > } > } > So entfällt jegliches Kopieren und du kannst jede Ziffer direkt > verarbeiten. Hallo Dr. Sommer Genau das brauche ich. Jetzt muss ich es nur noch verstehen. for (const char* p = str; *p; ++p) Als Startwert gibst du die Anfangsadresse von str an den pointer p. Warum ist aber der Wert, bei dem die Schleife beendet werden soll gleich dem aktuellen Wert vom pointer p? Und weshalb inkrementierst du schon vorher?
Marwin schrieb: > Warum ist aber der Wert, bei dem die Schleife beendet werden soll gleich > dem aktuellen Wert vom pointer p? Ein String endet mit einem 0x00. Die Ausführungsbedingung der For-Schleife ist solange erfüllt, wie das Zeichen unter dem Zeiger p (also *p) ungleich 0x00 ist. Und weshalb inkrementierst du schon > vorher? Wie vorher? ++p wird am Ende des Schleifenrumpfes aufgeführt.
Marwin schrieb: > Und weshalb inkrementierst du schon > vorher? Macht er nicht. Bitte einmal For Schleife lernen. Vielleicht ist dieses einfacher zu verstehen: Effektiver ist es wohl kaum. Aber etwas flexibler ist es, denn es arbeitet zur Zahlenbasis 2 bis 36
1 | char *quelle = "C99"; |
2 | uint8_t ziel[3]; // <<< muss gross genug sein |
3 | |
4 | |
5 | void wandel(char *quelle,uint8_t *ziel,int base) |
6 | {
|
7 | char temp[2] = {0,0}; |
8 | while(*quelle) |
9 | {
|
10 | temp[0] = *quelle; |
11 | *ziel = strtol(temp,nullptr,base); |
12 | quelle++; |
13 | ziel++; |
14 | }
|
15 | }
|
16 | |
17 | |
18 | void setup() |
19 | {
|
20 | Serial.begin(9600); |
21 | Serial.println("Start"); |
22 | wandel(quelle,ziel,16); |
23 | for(uint8_t t:ziel)Serial.println(t); |
24 | }
|
25 | |
26 | void loop() |
27 | {
|
28 | |
29 | }
|
Marwin schrieb: > Ich möchte zB einen String "AAA" an eine Funktion übergeben. > > Dann habe ich mir gedacht, diesen String in einem Array abzuspeichern > und den Array durchzuiterieren und dabei immer die atoi Funktion zu > benutzen. Warum? Warum willst du den String erst kopieren und dann über die Kopie iterieren? Du kannst doch direkt über den übergebenen String laufen? Und was willst du mit atoi() und einzelnen Zeichen aus dem String? > Jetzt habe ich das versucht zu realisieren, aber irgendwie habe ich > Probleme dabei, die richtige Länge des Arrays anzugeben. Wenn du einen String kopieren willst, dann verwende unbedingt eine der Standardfunktionen dafür. Und zwar im Idealfall nicht strcpy(), sondern strncpy(). Geh jetzt los und lies die Beschreibung dieser Funktionen. Hinweis: du wirst auch strlen(), malloc() und Kenntnis über Zeiger brauchen, um damit etwas anfangen zu können. Ja, Strings in C sind kompliziert. Vor allem fehlerträchtig. > wie macht man so etwas? Wie macht man was? Du hast bis jetzt nicht deine eigentliche Aufgabe beschrieben. Was willst du mit dem Inhalt des Strings anstellen? Es ergibt auf jeden Fall schon mal gar keinen Sinn, den String überhaupt zu kopieren.
Axel S. schrieb: > Und zwar im Idealfall nicht strcpy(), sondern strncpy(). Besser noch wäre strlcpy, aber das hat es leider immer noch nicht in den Standard geschafft. strncpy hat nämlich eine unappetitliche Eigenschaft, die man nicht erwartet; ist der zu kopierende String länger als die Anzahl der zu kopierenden Zeichen, wird kein abschließendes '\0' angehängt.
Arduino Fanboy D. schrieb: > Marwin schrieb: >> > { > temp[0] = *quelle; > *ziel = strtol(temp,nullptr,base); > quelle++; > ziel++; > } > } > > void setup() > { > Serial.begin(9600); > Serial.println("Start"); > wandel(quelle,ziel,16); > for(uint8_t t:ziel)Serial.println(t); > } > > void loop() > { > > } Hallo arduino fan Ja das habe ich schon, aber die for-loop wird nirgends mit pointern erklärt, leider. Deshalb auch die Frage. Zählt bei *p als Abbruchbedingung wieder das Prinzip, dass die Schleife bei einer '0' abgebrochen wird?
Marwin schrieb: > Zählt bei *p als Abbruchbedingung wieder das Prinzip, dass die Schleife > bei einer '0' abgebrochen wird? Der Schleifenrumpf wird ausgeführt, solange die Bedingung erfüllt ist. Erfüllt heißt, das Ergebnis der Bedingung muss ungleich 0 sein. Da wird nichts abgebrochen.
Marwin schrieb: > Ich möchte zB ein Text 0-F, also 0-15 in einzelne Ziffern wandeln. > zB AAA, BBB, B10 etc. > Das möchte ich aber so direkt an eine Funktion übergeben zB "C99". Und was soll die Funktion in diesem/n Fall/Fällen dann zurückgeben?
Marwin schrieb: > Ich habe da mal etwas versucht. merkt man aber ohne Verständnis > Funktioniert das so oder ist das kompletter Unsinn? > > void wandleUm(char *string) > { > uint8_t str_length; ohne init, das geht zwar meist gut ABER uint8_t str_length=0; //wäre besser > char str[10]; > uint8_t code[10]; warum 2x? > strcpy(str, string); ohne Überlaufprüfung? wenn schon nach Prüfung ob der Platz reicht > uint8_t str_length; dann doch strncpy(str, string, str_length); wenn sichergestellt ist das es passt ohne Überlauf
Joachim B. schrieb: > Marwin schrieb: >> Ich habe da mal etwas versucht. > > merkt man aber ohne Verständnis Hallo Joachim Ja stimmt, ich habe da an die Ascii Tabelle auch nicht gedacht. Auch wenn es mit atoi funktioniert hätte, hätte ich falsche ascii Werte gehabt. Aber ich habe durch eure Tipps jetzt dazugelernt. Das glaube ich zumindest. Ich muss die vorgeschlagenen Dinge hier nochmals selbst ausprobieren. > >> Funktioniert das so oder ist das kompletter Unsinn? >> >> void wandleUm(char *string) >> { >> uint8_t str_length; > > ohne init, das geht zwar meist gut ABER > uint8_t str_length=0; //wäre besser > >> char str[10]; >> uint8_t code[10]; > > warum 2x? > >> strcpy(str, string); > > ohne Überlaufprüfung? > wenn schon nach Prüfung ob der Platz reicht > >> uint8_t str_length; > > dann doch strncpy(str, string, str_length); > wenn sichergestellt ist das es passt ohne Überlauf Muss ich eben mal ausprobieren, sobald ich Zeit finde. Vielen Dank euch allen
Marwin schrieb: > void sendErrorCode(uint8_t *string) > { > uint8_t code[]; > strcpy(code, string); > > } Die Frage ist aber, warum Du überhaupt eine Kopie anlegen willst? Alle C-Operationen funktionieren genauso gut auf dem Original.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.