Zeichen vergleichen



  • Tach zusammen

    Kurze Frage:

    char text1[9] = "DiesText";
    char text2[4] = "sTe";
    

    Es soll über prüft werden ob sTE in DiesText vorhanden ist?
    Wie könnte man das am besten machen?

    Ok, das oben habe ich. Aber angenommen es sähe so aus:

    char *text	= new char;
    	char *find	= new char;
    
    	cout	<< "Bitte geben Sie einen Text ein:";
    	cin      >> text;
    	cout	<< endl << "Nach was soll gesucht werden:";
    	cin      >> find;
    

    Wie bekomme ich dann die Länge der Arrays raus. Keine enthaltene Funktion sondern selfmade..

    Gruß



  • in deinem fall ist text bzw. find kein char-array, sondern ein zeiger auf ein zeichen.
    ich würde persönlich zu std::string raten.



  • #include <string.h>
    
    **************
    
        char *text;
        char *find;
        cout    << "Bitte geben Sie einen Text ein:";
        cin      >> text;
        cout    << endl << "Nach was soll gesucht werden:";
        cin      >> find;
    
        char* pos=strstr(text, find);
    
        if (pos==NULL) {
            cout <<endl<<"String not found";
        } else {
            cout <<endl<<"String found on position "<< int(pos-text);
        }
    

    So ungefähr sollte es gehen



  • Ach ja, wenn du daß manuell machen willst - musst du einfach die array-grenzen durchzellen. Die strings ja werden per \0 geendet.

    char* tmp = text;
    int n=0;
    while ( *(tmp++)!=NULL ) {
        n++;
    }
    

    Am ende hast du die länge des textes ohne den \0 im n.



  • Maverick89 schrieb:

    cout <<endl<<"String found on position "<< int(pos-text);
    

    Mir fällt das jetzt schon in mehreren deiner Postings auf dass du nicht castest sondern temporäre Variablen erzeugst. Hat das irgend einen besonderen Grund ?
    Würde das so machen

    cout <<endl<<"String found on position "<< (int)(pos-text);
    

    Kurt



  • Sorry, habe nicht verstanden was du meinst, bin aber für Kritik offen 🙂
    Wenn du meinst, dass ich viele neue unnötige variabeln einbinde - das war nur als beispiel - meistens bin ich mit dem speicher extrem sparsam 🙂

    Was die Korrektur angeht - naja - geschmackssache, Straustrup schrieb es in seinen Buch manchmal auch so wie ich jetzt 🙂

    Gruß,
    Mav



  • Keine Kritik eher eine Frage.
    Hab's jetzt ausprobiert. g++ macht aus beiden Versionen den gleichen code. Also nur Geschmacksache.
    Kurt



  • Super.. Danke für die zahlreichen Antworten..

    Allerdings bleibt ein Problem..

    Ich habe eine statische und eine dynamische Version des Problems.

    Die statische habe ich so gelöst:

    char text1[9]		= "DiesTest";
    	char find[4]		= "sTe";
    
    	int checkValue		= 0;
    
    	int i = 0;
    	while(i < 8)
    	{
    		if(find[0] == text1[i] && find[1] == text1[i+1] && find[2] == text1[i+2])
    		{
    			checkValue = 1;
    		}
    
    		i++;
    	}
    
    	if(checkValue > 0)
    	{
    		cout << "Gefunden" << endl;
    	}
    	else
    	{
    		cout << "Nicht gefunden" << endl;
    	}
    

    Bleibt die dynamische wo der User halt den Text eingibt in dem gesucht werden soll und dann noch eingeben kann was in dem Text gesucht werden soll..

    int getFieldCount(char *text)
    {
    	int fields = 0;
    	while(*(text++) != NULL)
    	{
    		fields++;
    	}
    
    	return fields;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
    	char *text1	= new char;
    	char *find	= new char;
    
    	cout	<< "Bitte geben Sie einen Text ein:";
    	cin		>> text1;
    	cout	<< endl << "Nach was soll gesucht werden:";
    	cin		>> find;
    
    	cout	<< endl << endl;
    
    	cout	<< text1 << endl;
    	cout	<< find << endl;
    
    	cout	<< "Anzahl der Felder in text" << " " << getFieldCount(text1) << endl;
    	cout	<< "Anzahl der Felder in find" << " " << getFieldCount(find) << endl << endl;
    
    		int checkValue		= 0;
    
    	int i = 0;
    	while(i < getFieldCount(text1))
    	{
    		if(find[0] == text1[i] && find[1] == text1[i+1] && find[2] == text1[i+2])
    		{
    			checkValue = 1;
    		}
    
    		i++;
    	}
    
    	if(checkValue > 0)
    	{
    		cout << "Gefunden" << endl;
    	}
    	else
    	{
    		cout << "Nicht gefunden" << endl;
    	}
    
    	system("PAUSE");
    	return EXIT_SUCCESS;
    }
    

    Das if() ist ja jetzt nicht mehr zu gebrauchen da die Länge des zu suchenden Teils dynamisch ist. Hat da jemand eine Idee?



  • Hat da jemand eine Idee?

    Klar!
    Mit <string.h> - strlen(char*);
    Ohne - da habe ich eine passende Funktion zum durchzählen oben schon geschrieben 😉



  • Ja aber wie durchzählen? Angenommen der text ist 8 Felder lang.. Und die zeile die gesucht werden soll 3 felder lang. Dann zähle ich in der ersten Schleife die 8 Felder und muss dann die 3 gesuchten Felder zusammenbauen und dann mit jeweils den nächsten 3 Feldern des Textes vergleichen. Nur ich kann kein statisches if wie im ersten Beispiel mehr bauen wo ich genau wusste das ich drei Felder vergleichen muss.. Wie krieg ich das denn jetzt raus? Die Funktion habe ich ja eingebaut im zweiten Bsp.. getFieldCount..



  • Hint: noch eine schleife.
    Kurt



  • ZuK schrieb:

    Maverick89 schrieb:

    cout <<endl<<"String found on position "<< int(pos-text);
    

    Mir fällt das jetzt schon in mehreren deiner Postings auf dass du nicht castest sondern temporäre Variablen erzeugst. Hat das irgend einen besonderen Grund ?
    Würde das so machen

    cout <<endl<<"String found on position "<< (int)(pos-text);
    

    Kurt

    Der Unterschied ist der, dass der Ausdruck

    int(pos-text)
    

    ein sogenanter static-cast ist und

    (int)(pos-text)
    

    ein C-Cast, bei dem es dem Compiler überlassen bleibt, welchen Cast er durchführt. D.h. hier kann auch ein reinterpret_cast oder ein const_cast geschehen, dem man vielleicht gar nicht will. In so einem Fall würde ein versuchter konkreter static_cast einen Compiler-Fehler verursachen.
    Damit man zur Laufzeit keine bösen Überaschungen erlebt, ist der static_cast immer vorzuziehen. So gesehen ist

    int(pos-text)
    

    der 'bessere' Code. In diesem konkreten Beispiel sollte der Compiler aber in beiden Fällen identischen Code erzeugen.

    Gruß
    Werner



  • Hm.. ok.. jetzt kann ich nicht mehr folgen..
    Die funktion getFieldCount gibt doch einen int zurück.. Zudem geht es mir eher um die Logik des ganzen.. Ich verstehe das mit den zwei Schleifen noch nicht so recht.. Das casten ist erstmal nebensache.. Das ist elfte Klasse Gymnasium Programmieren.. Es geht echt nur um die Logik..

    Hier bin ich schon an der Stelle, denke ich, an der das erste Zeichen aus text mit dem ersten Zeichen aus find übereinstimmt.. Ich komme aber nicht weiter..

    for(int i = 0; i < getFieldCount(text); i++)
    	{
    		for(int x = 0; x < getFieldCount(find); x++)
    		{
    			if(find[x] == text[i])
    			{
    
    			}
    			else
    			{
    				break;
    			}
    		}
    	}
    


  • if(find[x] == text[i+x])
    

    Edit: Natürlich must du schon vor der inneren schleife überprüfen ob das zeichen text[i] mit find[0] übereinstimmt. Nur dann darf die innere schleife laufen.



  • Ok.. Ich glaub ich geb's auf 😉

    Also Code Müsste demnach vor der inneren Schleife so aussehen?

    if(find[0] == text[i])
    

    Leuchtet ein.

    So jetzt sind wir in der inneren Schleife wenn das erste Zeichen von find mit einem beliebigen von text übereinstimmt.. Andernfalls kann es ja keine Übereinstimmung geben..

    Was soll jetzt in der inneren Schleife passieren. Wie kann ich jetzt abfragen ob die n Werte aus find mit den n Werten aus text übereinstimmen?

    Mein Problem ist ganz einfach das ich nicht weiß wie ich in der inneren Schleife überprüfen soll..



  • Würde das ungefähr so machen

    for(int i = 0; i < getFieldCount(text); i++) {
            if ( text[i] == find [0] ) {
               int x;
               for( x = 0; x < getFieldCount(find); x++) {
                  if(find[x] != text[i+x]) // nicht gefunden weiter mit der äusseren schleife
                     break;
               }
               if ( x == getFieldCount(find) ) // gefunden 
                  return true;
            }       
        }
        return false;
    

    Natürlich musst du in der inneren schleife noch überprüfen dass du nicht über das ende von text hinaus zugreifst
    Kurt

    Edit: Logicfehler



  • realmontanakid schrieb:

    Ok.. Ich glaub ich geb's auf 😉

    keine Panik; wir sind bei Dir 🕶

    realmontanakid schrieb:

    Mein Problem ist ganz einfach das ich nicht weiß wie ich in der inneren Schleife überprüfen soll..

    Nun Du musst entscheiden ob alle Zeichen übereinstimmen. Das tut man gemeinhin z.B. so:

    int checkValue        = 0;
    
        int find_len = getFieldCount(find);
        int ende = getFieldCount(text1) - find_len;
        for( int i = 0; i < ende && checkValue == 0; ++i )
        {
            bool gefunden = true;   // mal angenommen wir hätten den Text gefunden
            for( int j = 0; j < find_len && gefunden; ++j )
            {
                if( text1[i+j] != find[j] )  // nein; passt nicht
                    gefunden = false;
            }
            if( gefunden )
            {
                checkValue = 1;
            }
        }
    

    Die Variablen 'find' und 'text1' solltest Du zu std:.string's machen, das ist viel einfacher zu handhaben. In Deinem Original Code

    realmontanakid schrieb:

    int _tmain(int argc, _TCHAR* argv[])
    {
    	char *text1	= new char;
    	char *find	= new char;
    

    hast Du nur Platz für genau ein Zeichen.

    Gruß
    Werner



  • So ich glaub ich hab es... Man man..

    int checkValue		= 0;
    
    	for(int i = 0; i < getFieldCount(text); i++)
    	{
    		if(find[0] == text[i])
    		{
    			for(int x = 0; x < getFieldCount(find); x++)
    			{
    				if(find[x] == text[i+x])
    				{
    					checkValue++;
    				}
    			}
    		}
    		else
    		{
    			continue;
    		}
    	}
    
    	if(checkValue == getFieldCount(find))
    	{
    		cout << "Gefunden" << endl;
    	}
    	else
    	{
    		cout << "Nicht gefunden" << endl;
    	}
    

    Wenn checkValue == getFieldCount von find ist muss er ja die Anzahl an Übereinstimmungen gefunden haben die find selbst als Anzahl Felder hat..

    Vielen Dank für eure Geduld..

    (Soll nich heissen das das der letzte Post war 😉 )

    Gruß



  • realmontanakid schrieb:

    So ich glaub ich hab es...

    Überleg' mal ..
    'text' sei ".....ab....ab...." und 'find' sei "abcd". Dann behaupte ich, dass Dein Algorithmus "Gefunden" ausgibt, da er 4 mal - nämlich 2mal für jeweils 'ab' - den Wert 'checkValue' inkrementiert.

    Zudem greift der Algorithmus auch auf Zeichen zu, die hinter (!) 'text' im Speicher stehen. Das max. erreichbare 'i' ist (Länge von 'text' - 1). Zu diesem 'i' wird in der inneren Schleife noch max. (Länge von 'find' - 1) addiert und das liegt immer außerhalb von 'text'.

    Zum dritten hat Dein Algorithmus O2-Komplexität. Mit jedem Durchlauf von i bestimmst Du in

    for(int i = 0; i < getFieldCount(text); i++)
    

    'getFieldCount' wieder die Länge von 'text'. Das bedeutet, wenn der Algorithmus für 100 Zeichen 1 Sekunde braucht, so brauchst Du bei 1000 Zeichen nicht 10 Sekunden sondern 100s und bei 10000 Zeichen 10000s - also knapp drei Stunden ...
    Speichere das Ergebnis von getFieldCount(text) einfach in einer Variablen - siehe mein letztes Posting.

    Gruß
    Werner



  • Hi

    Ok.. Auch das leuchtet ein..
    Aber eins verstehe ich nicht an dem Code den du gepostet hast nicht..

    int checkValue        = 0; 
    
        int find_len = getFieldCount(find); 
        int ende = getFieldCount(text1) - find_len; 
        for( int i = 0; i < ende && checkValue == 0; ++i ) 
        { 
            bool gefunden = true;   // mal angenommen wir hätten den Text gefunden 
            for( int j = 0; j < find_len && gefunden; ++j ) 
            { 
                if( text1[i+j] != find[j] )  // nein; passt nicht 
                    gefunden = false; 
            } 
            if( gefunden ) 
            { 
                checkValue = 1; 
            } 
        }
    

    if( text1[i+j] != find[j] ) Das ist der Vergleich.. Aber hier wird doch nur ein Zeichen mit einem anderen Zeichen verglichen.. Wenn ich in DiesText sTe suche dann gefunden doch schon true wenn s gefunden wird, oder?


Anmelden zum Antworten