Wieder einmal Array to int Problem: Ich verwenden Atmega8 und möchte die Zeichenkette die an die UART-Schnittstelle gesendet wird auswertn und dabei die letzten beiden Ziffern als Integer Werte weiterverarbeiten. Im Klartext: An der UART des Atmels kommt zB an: Baumhaus 25 -> Baumhaus wird abgeschnitten (bereits realisiert siehe Listing) -> 2 -> 5 -> sollen nun die Integer Zahl y=25 ergeben Wie stelle ich das an? Habe mein Glück schon mit atoi() versucht, werde aber darus nicht schlau...
Mal ein Beispiel: char Text[] = "Baumhaus 25"; int Wert; Wert = atoi(Text + strlen("Baumhaus ")); Oder: char Buffer[] = "Baumhaus 25"; char *Pointer; int Wert; Pointer = Buffer + strlen("Baumhaus "); Wert = atoi(Pointer); Hilft das?
Oder falls der Text vor der Zahl nicht bekannt ist
1 | int i, zahl; |
2 | for(i=0;text[i]!='\0'&&!isdigit(text[i]);i++) ; |
3 | zahl = atoi(text[i]); |
Danke für die schnellen Antworten, bin allerdings nicht weitergekommen. Würde den Wert gerne über uart_send(Wert); als Test ausgeben aber da tut sich gar nichts.. Verstehe einfach nicht woran das liegt!?
Was macht denn "uart_send"? Das ist eine Funktion, die einzelne Zeichen an die serielle Schnittstelle ausgibt. "Wert" hat in Deinem Beispiel den Wert 25, das ist ein Steuerzeichen, das ein Terminalprogramm in der Regel gar nicht darstellen kann. Damit Dein Wert in einer für Dich verständlichen Form angezeigt wird, müsstest Du ihn in eine Zeichenfolge "2" und "5" umwandeln und diese Zeichen nacheinander mit "uart_send" ausgeben.
@Rufus, das mit dem "zahl = atoi(text + i);" ist mir persönlich nicht aussagekräftig genug. Dass es sich bei text um einen zeiger handelt wird verschleiert. Der weg über &text[i] ist zwar mehr tipparbeit aber "sprechender". Der compiler genereriert in beiden fällen den gleichen code, also ist es im grunde genommen egal. Dass ich relativ grossen wert auf "sprechenden" sourcecode lege ersiehtst Du auch schon aus "text[i]!='\0'"; Es wird explizit mit dem NULL - character verglichen und nicht einfach mit 0. (-: Werner
> Der weg über &text[i] ist zwar mehr tipparbeit aber > "sprechender". Geschmackssache. Ich finde, dass für jeden, der das Kapitel über Zeiger und Felder im K&R verstanden hat, text + i auf Grund der geringeren Häufung kryptischer Zeichen die bessere Übersichtlichkeit bietet.
Hmm. Ich programmiere schon so lange in C, daß ich Dinge, die mir so selbstverständlich wie das Atmen erscheinen, nicht explizit hinschreibe. Dazu gehört ein Vergleich mit 0, '\0' oder NULL (die letzten beiden sind übrigens etwas unterschiedliches). Dafür strukturiere ich Quelltext durch an bestimmten Stellen eingefügte Leerzeichen.
1 | for (i = 0; text[i] && !isdigit(text[i]); i++); |
So sähe das bei mir aus. Um auf Deine eingängliche Kritik einzugehen: Die Variable "text" würde, wenn sie denn in einem vergleichbaren Kontext verwendet wird, von mir nicht "text", sondern höchstwahrscheinlich "pText" genannt werden. All' das aber sind philosophische Betrachtungen, es gibt unendliche Streitereien zwischen verschiedenen Fraktionen von C-Programmierern über die Quelltextformatierung; entscheidend ist, daß man für sich selbst ein konsistentes System verwendet. Hält man das konsistent durch, besteht mit einiger Übung die realistische Chance, daß man auch mehrere Jahre alte Quelltexte problemlos warten kann.
Wenn statt Baumhaus was anderes stehen kann, es aber ein Wort ist geht auch: char tmp[20]; int wert; sscanf(text,"%s %d",tmp,&wert); Zahlt sich aber nur aus, wenn scanf schon dazugelinkt wurde, sonst frisst dir das so 1-2 kByte.
Ok, vielen Dank hat funktioniert! Was mir noch absoulut unklar ist wie ich nun aus dem erhaltenen Wert (dezimal) einen Wert in Hexadezimal erhalte (mit dem Hex-Wert möchte ich dann einzelne Ports meines Atmels ansteuern). Geht das ohne weiteres überhaupt oder muss man den "normalen" Weg der DEZ -> HEX Umrechnung gehen?
Der von atoi (oder sscanf) gelieferte Wert ist ein binärer Wert und kann einfach so in ein Portregister geschrieben werden (sofern auf den möglichen Wertebereich geachtet wird). Die Konvertierung von dezimal in binär hat bereits atoi (bzw. sscanf) durchgeführt.
Zum Einscannen einer Ganzzahl sollte man möglichst nie atoi nehmen, weil das keine Hexadezimalzahlen einliest. Stattdessen sollte man immer strtol nehmen: int i=strtol(argv[1], (char **)NULL, 0); wobei argv[1] nur ein Beispiel für eine einzuscannende Zahl, in Form eines nullterminierten Strings, ist. Damit werden auch Oktalzahlen richtig eingelesen.
> Zum Einscannen einer Ganzzahl sollte man möglichst nie atoi > nehmen, weil das keine Hexadezimalzahlen einliest. Ein viel wichtiger Grund ist, daß atoi einen schwerwiegenden Designfehler hat, nämlich, daß man nicht erkennen kann, ob die Konvertierung erfoglreich war (sprich: ob der String überhaupt eine Zahl enthalten hat).
Ja, eigentlich hätte atoi auch deshalb zumindest aus den Lehrbüchern verschwinden sollen, aber Traditionen halten sich lange, wie man auch an gets und anderen sieht.
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.