Strings vergleichen

Tag,

ich will Strings vergleichen:

char myStrings[]={'This is string 1', 'This is string 2', 'This is string 3',
'This is string 4', 'This is string 5','This is string 6'};

char suchwort = 'This is string 5';

void setup(){

}

void loop(){

	int resl = stringnummer(suchwort) ;

}


int stringnummer(char suchw){
	int c = 0;
	int status = 0;
	while(status == 0){
		char strng = myStrings[c] ;
		if (strng == suchw){
			status = 1;
		} else {
		c +=1;
		}
	}
	return c;
}

Als Ergebnis sollte 4 rauskommen, jedoch bekomme ich 5 raus. Warum ist das so?

char strng = myStrings[c] ;

strng kann nur 1 Zeichen aufnehmen

if (strng == suchw)

Du vergleichst da irgendwas, aber keine Strings....

Siehe:

Schon deine Deklaration ist völlig falsch. C Strings sind Null-terminierte char Arrays.

Korrekt:

char suchwort[] = "This is string 5";

Doppelte Anführungszeichen beachten!! Einfache Anführungszeichen ist ein einzelner char

Arrays aus Strings sind zwei-dimensionale Arrays oder Arrays aus Zeigern. Korrekt:

char* myStrings[] = { "This is string 1", "This is string 2" };

Array-Variablen sind Zeiger auf das erste Element (deshalb das Array aus char* für ein String Array). Aus dem Grund kann man C Strings nicht mit = zuweisen und nicht mit == vergleichen! Eine Zuweisung kopiert nur den Zeiger (was manchmal aber genau das ist was man braucht) und ein Vergleich vergleicht nur den Zeiger (was fast immer nicht ist was man braucht).

C Strings werden mit einer Reihe von Funktionen bearbeiten. Zum Vergleichen gibt es strcmp() (string compare):
http://www.cplusplus.com/reference/cstring/strcmp/

staivoup:
Als Ergebnis sollte 4 rauskommen, jedoch bekomme ich 5 raus. Warum ist das so?

Dein Programm enthält HAUFENWEISE Anfängerfehler. Und wegen der vielen Fehler funktioniert es nicht.

Das fängt damit an, dass Du im Programm die Strings falsch deklarierst:

Ein EINZELNES ZEICHEN vom Typ 'char' wird in EINZELNE HOCHKAMMAS eingeschlossen.
Beispiel: char x='X';

Ein STRING vom Typ 'C-String' bzw. 'Char-Array' wird immer in DOPPELTE HOCHKOMMAS eingeschlossen. Beispiel:

char suchwort[] = "This is string 5";

Dementsprechend ist am Anfang bereits Dein String-Array komplett falsch definiert.

Da ein einzelner String bereits ein Char-Array ist, wäre ein String-Array ein "zweidimensionales char-Array", z.B.:

char myStrings[][19]={"This is string 1", "This is string 2", "This is string 3",
"This is string 4", "This is string 5","This is string 6","no digit in string"};

Bei einem zweidimensionalen Array müßten alle Elemente im Array gleich groß sein, in diesem Fall mindestens so groß wie der längste String plus sein abschließendes Nullzeichen. Außer der ersten Dimension (Anzahl der Elemente im Array) müßten alle Dimensionen im Array fest deklariert werden (in diesem Fall die maximale Stringlänge).

Die andere Möglichkeit der Deklaration wäre, ein Array von String-Pointern zu deklarieren:

char* myStrings[]={"This is string 1", "This is string 2", "This is string 3",
"This is string 4", "This is string 5","This is string 6","no digit in string"};

In diesem Fall besteht das Array selbst nur aus 2-byte großen "Zeigern", die auf die eigentlichen Strings verweisen. Von der Programmierung her ist das kein großer Unterschied, denn ein deklariertes char-Array ist an sich auch nichts anderes als ein Zeiger. Vom RAM-Speicherverbrauch wäre es im Umgang mit konstanten Strings ein Unterschied: Das 2-dimensionale Array verbraucht für jedes Element im Array so viel Platz, wie der längste String belegt. Das eindimensionale Char-Pointer Array belegt für jeden String nur tatsächlich so viel Platz im RAM, wie der String lang ist (einschließlich abschließendes 0-byte).

Willst Du nochmal probieren, etwas zu programmieren?
Oder brauchst Du einen fertigen Code zur Demonstration?

Wenn du fertigen Code zur Hand hast, wäre das sehr Knorke. Damit würde ich sicher viel Zeit sparen, mußt du aber nicht machen.

Ich kann leider erst morgen abend weiter Testen. Ich mache das nur als Hobby und in meiner Freizeit.

staivoup:
Wenn du fertigen Code zur Hand hast, wäre das sehr Knorke.

Wenn ich Code zur Hand habe, dann habe ich den Code vorher auch geschrieben, der fliegt mir nicht einfach zu.

Erstmal mußt Du wissen, was Du eigentlich möchtest:
Möchtest Du nur in den Strings nach Ziffern suchen?
Oder möchtest Du tatsächlich ganze Strings vergleichen?

Beispielcode: "Ziffern suchen in einem zweidimensionalen char-Array" (String-Array mit fester Länge für jedes Element):

char myStrings[][19]={"This is string 1", "This is string 2", "This is string 3",
"This is string 4", "This is string 5","This is string 6","no digit in string"};

int stringnummer(char* suchw){
  for (int i=0;i<strlen(suchw);i++)
  {
    if (isdigit(suchw[i])) return suchw[i]-'0'; // ASCII-code in byte umwandeln und zurückliefern
  }
  return -1;
}

void setup(){
  Serial.begin(9600);
  for (int i=0;i<7;i++)
  {
    Serial.print(myStrings[i]);
    Serial.print('\t');
    Serial.println(stringnummer(myStrings[i]));
  }
}

void loop(){
}

Der Code sucht Zeichen für Zeichen in einem String nach einer Ziffer, und liefert die gefundene Ziffer als Byte-Wert zurück, andernfalls -1.

Hier nochmal quasi derselbe Code, allerdings als Array von char-Pointern deklariert:

char* myStrings[]={"This is string 1", "This is string 2", "This is string 3",
"This is string 4", "This is string 5","This is string 6","no digit in string"};

int stringnummer(char* suchw){
  for (int i=0;i<strlen(suchw);i++)
  {
    if (isdigit(suchw[i])) return suchw[i]-'0'; // ASCII-code in byte umwandeln und zurückliefern
  }
  return -1;
}

void setup(){
  Serial.begin(9600);
  for (int i=0;i<7;i++)
  {
    Serial.print(myStrings[i]);
    Serial.print('\t');
    Serial.println(stringnummer(myStrings[i]));
  }
}

void loop(){
}

Im Code ändert sich nichts, nur das Array ist anders deklariert. Zu beachten wäre, dass wenn Du einen String als Char-Array zur Verarbeitung an eine Funktion übergibst, dann übergibst Du als Typ immer einen Char-Pointer, also "char*". Entweder so:

int stringnummer(char* suchw)

oder so:

int stringnummer(char *suchw)

D.h. ob das Pointerzeichen '*' num beim Typnamen oder beim Namen der Variablen steht und wo sich das Leerzeichen befindet, wäre dem Compiler in dem Fall egal.

Und hier jetzt noch eine Variante, bei der nicht nach einer einzelnen Ziffer gesucht wird, sondern bei der ein Suchstring vorgegeben wird, und es wird nach dem String gesucht:

char* myStrings[]={"This is string 1", "This is string 2", "This is string 3",
"This is string 4", "This is string 5","This is string 6","no digit in string"};

#define NUMSTRINGS (sizeof(myStrings)/sizeof(myStrings[0]))

char suchwort[] = "This is string 5";

void setup(){
  Serial.begin(9600);
  for (int i=0;i<NUMSTRINGS;i++)
  {
    if (strcmp(myStrings[i], suchwort)==0)
    {
      Serial.print("Suchwort gefunden mit Array-Index: ");
      Serial.println(i);
    }
  }
}

void loop(){
}

Die Funktion aus der AVR libc Library, mit der Strings verglichen werden, heißt "strcmp", was für "string compare" steht.

Funktion strcmp im Manual der AVR LIBC

D.h. um zwei Strings auf Gleichzeit zu testen, brauchst Du Dir überhaupt keine eigene Funktion zu schreiben, sondern das ist eine Standardfunktion aus der Library. Und daher würdest Du im Falle eines Stringsvergleichs auch einfach eine Standardfunktion (z.B. 'strcmp') aufrufen und keine eigene Funktion dafür schreiben.

Übrigens genau so, wie ich in der zuerst geposteten Variante (Suchen nach einer Ziffer im String) für die Prüfung, ob ein Zeichen eine Ziffer ist, auch keine eigene Funktion geschrieben habe, sondern die 'isdigit' Funktion verwendet habe.

Wenn Du mit Arduino programmierst, dann ist die "AVR LIBC" neben den Arduino Core-Libraries erstmal der wichtigste Fundus an Library-Funktionen, in dem Du viele grundlegenden Operationen für Mathematik, Stringbehandlung und so weiter findest. Die Library-Referenz ist online hier verfügbar.

Stimmt, ich habe das Ziel nicht genau benannt. Ich will die Position eines Strings im Array finden. Dein letztes Beispiel sieht gut aus. Ich muss das erstmal testen und etwas verstehen.

Hier als Funktion:

const char* myStrings[] = { "This is string 1", "This is string 2", "This is string 3",
                            "This is string 4", "This is string 5", "This is string 6", "This is string 7"
                          };

const int NUMSTRINGS = sizeof(myStrings) / sizeof(myStrings[0]);

char searchString[] = "This is string 6";

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

  int index = findString(searchString);
  if (index >= 0)
  {
    Serial.print(F("Index: ")); Serial.println(index);
    Serial.print(F("String: ")); Serial.println(myStrings[index]);
  }
  else
    Serial.println(F("String not found"));
}

void loop()
{}

int findString(const char* str)
{
  for (int i = 0; i < NUMSTRINGS; i++)
  {
    if (strcmp(str, myStrings[i]) == 0)
      return i;
  }

  return -1;
}

Gibt -1 zurück wenn der String nicht enthalten sind

Auch eventuell relevant ist strcasecmp() falls dir die Groß/Kleinschreibung egal ist

P.S.:
String Arrays aus char* müssen eigentlich als const deklariert werden. Sonst gibt es eine Warnung. Das vergesse ich auch ständig

Oh ja, oops. Man sollte vielleicht auf >= 0 abfragen

Hallo, eure Antworten haben mir sehr weitergeholfen. Insbesondere die ' und " Hinweise.

Vielen Dank auch speziell an Serenifly und Jurs fuer die Arbeit und anschaulichen Beispiele.