String in Integer?

Hallo schon wieder.

Langsam komm ich mir echt ein bisschen dumm vor. Ich versuche gerade einen String (enthält eine IP-Adresse) in einen Integer (vielmehr einen ganzen Haufen Integer) zu bekommen... Leider ohne Erfolg.

der String sieht folgender Maßen aus:

String ip = " 192.168.111.123";

jetzt hab ich Schlauerle gedacht, man könnte das ja mit atoi() machen:

const char *myar1 = ip[1];
const char *myar2 = ip[2];

int erstesdigit = atoi(myar1);
// jetzt sollte hier eigentlich eine Eins in der Variable stehen (wegen des Leerzeichens am anfang des Strings stimmt auch die "Eins" in der Referenzierung.

int zweitesdigit = atoi(myar2); /hier sollte eine 9 stehen.

... und so weiter. Aber es bleibt immer bei 0.

Also wenn Du schon soweit bist dass Du einzelne Zahlen vergleichen willst, dann kannst Du auch sowas machen:

int erstesdigit = ip[1]-'0';

funktioniert - danke.
Erklär mir bitte noch, warum das funktioniert?

Hallo Marcus,

haben wir nicht gerade im anderen Thread darüber diskutiert, dass ein Arduino-String KEIN array von chars ist? :wink: :wink: :wink:

atoi() und deine Zuweisung hätten aber doch ganz gerne chars bzw. einen Pointer darauf. Zwar gibt es in der String-Klasse den operator[] bzw. die Methode charAt(), um auf ein einzelnes Zeichen mit einem Index zuzugreifen, aber ich würde dir vorschlagen, den Arduino-String einfach komplett in ein char-Array zu wandeln und dann atoi() aufzurufen. Siehe Beispiel:

String ip = "192.168.111.123";    // ich habe das Leerzeichen am Anfang weggenommen!

void setup()
{
    Serial.begin(9600);

    char IPPuffer[100];
    ip.toCharArray(IPPuffer, sizeof(IPPuffer));    // Arduino-String in char-Array wandeln
    
    Serial.println("IP-Adresse aus char-Array:");
    Serial.println(IPPuffer);   // char-Array ausgeben
    
    int ip1, ip2, ip3, ip4;      // hier könnte man natürlich auch ein int-Array nehmen
    
    ip1 = atoi(IPPuffer);       // Ziffern müssen natürlich an fester Position stehen!
    ip2 = atoi(IPPuffer+4);
    ip3 = atoi(IPPuffer+8);
    ip4 = atoi(IPPuffer+12);
    
    Serial.println("IP-Adresse aus Einzelteilen:");
    Serial.print(ip1); Serial.print(".");
    Serial.print(ip2); Serial.print(".");
    Serial.print(ip3); Serial.print(".");
    Serial.print(ip4); Serial.println();
}

void loop()
{
}

Wolfgang

also gut... ich geb auf. Ich dachte ja wirklich, dass ich etwas vom Programmieren verstehe, aber die String-Klasse und die Konvertierungen in C machen mich alle.

Ich sitz jetzt seit 09:00Uhr früh dran, weil ich folgendes Problem versuche zu lösen:

Eingabe:
IP-Adresse als String mit vorangehendem Leerzeichen.

Verarbeitung:
IP-Adresse wird im ersten und zweiten Oktet um Decimal 1 erhöht. (192 auf 193, 168 auf 169);

Ausgabe:
String mit führendem Leerzeichen und neuen Werten.

Ich hack ab - jedesmal wenn ich einem Schritt näher komm, funktioniert der andere nicht mehr.

Sowas ist mir echt noch nie passiert - und ich hab schon viel programmiert, aber ich weiß jetzt schon wieso ich mich jahrelang um C gedrückt hab und erst zu C# wieder damit angefangen hab.

Erbarmt sich jemand, und hilft mir grob auf die Sprünge?

Ja, Marcus!

Aber beantworte bitte zuerst mal die Frage: Muss es denn unbedingt der Arduino-String sein? Tut es es nicht einfach das, was man unter C landläufig als String bezeichnet (Array von chars). Dann kann man alle die Funktionen für die Konvertierung und Formatiereung verwenden, die die C-Runtime zur Verfügung stellt.

Ich fürchte, du hast die ganzen Möglichkeiten, die Arduino-Strings bieten, an den Strings unter C# (oder besser gesagt .NET) gemessen und da liegen Welten zwischen.

Ich komme dann ggfs. auf dein Problem zurück.

Wolfgang

welchen Datentyp ich im endeffekt benutze ist eigentlich egal.

Zur Funktion:

Arduino wird seriell mit einigen Datensätzen (IP-Adressen, Routen, Traffic, etc) gefuttert. diese Datensätze schreibt er in ein Array Namen z.B. "IPDaten". Das erste Feld im Array ist die Host-IP, das zweite die Destination, das Dritte die Route etc...

Ich will jetzt den ersten Datensatz abändern und ihn anschließend seriell an den Client zuurücksenden. Daten Ein- und Ausgabe funktionieren tadellos, auch der Clientdeamon steht, nur die Umbastelung der Daten macht mir graue Haare.

EDIT:
meine Tastatur gibt jetzt bald endgültig den geißt auf - hab die letzten zwei Tage fast 500kb Code geschrieben (nicht nur für den Arduino :wink: - jetzt sind die Tasten ein wenig "ausgeleiert", Groß- und Kleinschreibung will nicht so Recht, weil die linke Shift nur noch mit draufdreschen und böse kucken funktioniert :wink:

nochmal die EDIT:
ich glaube, ich bin auf dem richtigen Weg. hab das Datenaray jetzt von string myarray[6] auf char *myarray[6] umgebastelt...

Ok... es funktioniert.

Lösung wie folgt:

char *myarray[4];
myarray[0] = "192.168.111.123";
myarray[1] = "192.168.111.254";
myarray[2] = "192.168.111.254";
myarray[2] = "255.255.255.000";

int editByte;
int digit = 2;

editByte= myarray[0][digit]-'0';
editByte++;
myarray[0][digit] = editByte> 9 ? 0:editByte;
myarray[0][digit] += '0';
ip = myarray[0];

nur weiß ich immer noch nicht, was ich eigentlich mache, wenn ich den Char mit '0' subtrahiere bzw. anschließend addiere. Ich seh nur, dass er mir dann stat dem int-wert des Ascii-Chars(Byteadresse) die jeweilige Zahl in die Variable editByte reinschreibt. Aber wieso das so ist, versteht nur Gott (wenn er C-Coder ist ;))

Müssen die einzelnen IP-Adressen in einem Array stehen? Kannst du nicht jeweils einzelne (Zeichenketten-)Variablen für die verschiedenen IP-Adressen nehmen?

Versuchs doch für die Erhöhung der Host-IP mal so:

char HostIP[] = " 192.168.111.123";   // ich habe das Leerzeichen am Anfang wieder drin!

void setup()
{
    Serial.begin(9600);

    Serial.println ("Input: ");
    Serial.println(HostIP);   // char-Array
    
    int ip1, ip2, ip3, ip4;
    
    ip1 = atoi(ip+1);
    ip2 = atoi(ip+5);
    ip3 = atoi(ip+9);
    ip4 = atoi(ip+13);
    
    // alternativ und einfacher statt der 4 atoi() geht es auch so
    // sscanf (HostIP, "%d.%d.%d.%d", &ip1, &ip2, &ip3, &ip4);   // man beachte die & vor den Variablen-Namen!
    
    ip1 = ip1 + 1;
    ip2 = ip2 + 1;
    
    // Ausgabe-Zeichenkette zusammenbauen
    char NeueHostIP[30];
    sprintf (NeueHostIP, " %03d.%03d.%03d.%03d", ip1, ip2, ip3, ip4);   // die %3d sind Formatierungskennzeichen
    
    Serial.println("IP-Adresse mit erhoehten Oktetts:");
    Serial.println(NeueHostIP);
}

void loop()
{
}

Au weja...

kannst du mir kurz erklären, was das %d eigentlich genau bedeutet? ich seh das immer wieder in C, verstehe auch, dass es der Platzhalter für die nachfolgenden Werte ist, aber nicht wieso immer %d und nicht %x, %y; 'd' für dezimal? %03d wären dann also eine 3-stellige Dezimalzahl?

Deine Lösung gefällt mir irgentwie besser, als meine. Gerade das 'sscanf' und das 'sprintf' haben es mir angetan, da versteh ich wenigsten im Ansatz, was passiert.

%03d: 3-stellige dezimale Ganzzahl; wenn weniger als 3 Ziffer-> mit führenden Nullen auffüllen
%3d: dito, aber keine führenden Nullen, stattdessen führende Leerzeichen
%d: Anzahl der Stellen abhängig vom Wert (variabel)
%x: Ausgabe der Ganzzahl als Hexadezimalzahl mit Kleinbuchstaben (variable Stellenzahl)
%X: Ausgabe der Ganzzahl als Hexadezimalzahl mit Großbuchstaben (variable Stellenzahl)
%3x: dito mit 3 Stellen
%y: kenn ich nich :wink: :wink: :wink:
%f: für float-variable
%lf: für double-Variablen
Bei float/double kann man noch herrlich die Anzahl der Vor- und Nachkommastellen manipulieren.
%s: für Zeichenketten
"normale" Zeichen (z.B. die Punkte) im Formatstring werden unverändert in die Ausgabe übernommen

Ansonsten schaue man z.B. hier:
http://www.cplusplus.com/reference/clibrary/cstdio/printf/

Superklasse. Danke.
Wenn du mir jetzt noch sagen kannst, was mein (oder Joghurts) "int zahl = char - '0';" macht, wirst du in mein Abendgebet aufgenommen :wink:

der char '0' ist int-Wert 42 oder so, '1' der danach, also z.B. 43,

mit char -'0' kann man genau den richtigen int-Wert erhalten, 1 für '1' usw.


Bete für google, der hat das gefunden :grin:

ASCII-Code von '1' (=dezimal 49) minus ASCII-Code von '0' (=dezimal 48) gleich integer-Wert 1;
ASCII-Code von '2' (=dezimal 50) minus ASCII-Code von '0' (=dezimal 48) gleich integer-Wert 2;
ASCII-Code von char (=dezimal ??) minus ASCII-Code von '0' (=dezimal 48) gleich integer-Wert der char entspricht;

Meine Nachtruhe scheint gesichert zu sein :wink:

Gute Nacht!
Wolfgang

LOL