Anzahl von einem String in einem anderen String



  • Ich soll ein Programm schreiben, dass zählt wieoft ein String in einem anderen String enthalten ist.

    Ich bin bis jetzt soweit gekommen:

    // Zählt Vorkommen von einem String in einem anderen
    
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
    	int result = 0, count = 0;
    	char quelle[160];
    	char suche[160];
    	char *location;
    
    // EINGABE	
    	puts("Geben Sie bitte den String ein, der durchsucht werden soll: ");
    	gets(quelle);
    
    	puts("Geben Sie bitte den zu suchenden Begriff ein: ");
    	gets(suche);
    
    // BERECHNUNG
    	while ( 1 )
    	{ 
    		location = strstr((quelle+count), suche);
    		count += (location-quelle);
    		if ( location != NULL )
    			result++;
    		else
    			break;
    	}
    
    	// AUSGABE
    	printf("\"%s\" wurde %d mal gefunden", suche, result);
    	return 0;
    }
    

    Das funktioniert auch soweit ABER:
    - Wenn ein Wort nur einmal vorkommt wird trotzdem 2 mal angezeigt. Daher stimmt die Anzeige erst wenn das Wort tatsächlich 2 mal vorkommt.
    - Wenn der Suchbegriff dem ersten Wort des Strings entspricht hängt sich das Programm auf (kommt irgendwie nicht mehr aus der Schleife raus).

    Ich habe viel rumprobiert, doch konnte das Problem leider nicht lösen.



  • Die Rumrechnerei in der Endlosschleife ist mir irgendwie suspekt. Sie ist v.a. auch total unnötig. Ich würde das z.B. so machen:

    while( (temp = strstr(temp, suche)) ){
        result++;
        temp++;
    }
    


  • Ich habe temp jetzt als char-Zeiger definiert und die Schleife übernommen.

    Doch das zählen klappt immernoch nicht richtig.



  • Simonek schrieb:

    Doch das zählen klappt immernoch nicht richtig.

    Was klappt genau noch nicht richtig?

    PS: Die [cpp]-Tags sind schöner als die öden [code]-Tags.

    Edit: Und gets() solltest du gar nicht nehmen. Nimm man: fgets.



  • Es zeigt immer nur 1 mal an egal ob es garnicht oder mehrmals vorkommt.

    P.S. Warum soll ich fgets verwenden?
    Sorry bin noch Anfänger...



  • Zeig nochmal den ganzen Code. Ich glaube du hast da was beim einbauen der Schleife übersehen.

    Zu gets(): gets() ist böse, weil man ihr (der Funktion) keine Angabe über die Länge/Größe des Zielpuffers mitgeben/übergeben kann. Deshalb liest gets() so lange von stdin (Standardeingabe, also idR die Tastatur) bis ein Enter kommt. Da kann es passieren, dass der eingelesene String länger ist als der Zielpuffer selbst und das Programm schreibt über die Grenzen des reservierten Speichers hinaus. Diesen Effekt nennt man "Buffer-Overflow". fgets() kann man die Größe des Zielpuffers übergeben, somit besteht da das Problem (bei fachgerechter Nutzung) nicht.



  • Ich habe einfach meine Schleife durch Deine ersetzt und einen Zeiger *temp deklatiert und mit quelle initialisiert.

    So sieht das jetzt aus:

    // Zählt Vorkommen von einem String in einem anderen
    
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
    	int result = 0, count = 0;
    	char quelle[160];
    	char suche[160];
    	char *temp; // Deklarierung
    		temp = quelle; // Initialisierung
    
    // EINGABE	
    	puts("Geben Sie bitte den String ein, der durchsucht werden soll: ");
    	fgets(quelle, 159, stdin);
    
    	puts("Geben Sie bitte den zu suchenden Begriff ein: ");
    	fgets(suche, 159, stdin);
    
    /*	DEAKTIVIERT
    while ( 1 )
    	{ 
    		location = strstr((quelle+count), suche);
    		count += (temp-quelle);
    		if ( temp != NULL )
    			result++;
    		else
    			break;
    	}
    	ENDE DEAKTIVIERT */
    
    	// BERECHNUNG
    		while( (temp = strstr(temp, suche)) )
    	{ 
        result++; 
        temp++; 
    	}
    
    	// AUSGABE
    	printf("\"%s\" wurde %d mal gefunden", suche, result);
    	return 0;
    }
    


  • Ah sorry, da hab ich was nicht bedacht. Bei einem normalen Aufruf von fgets() wird das '\n' im String mitgespeichert, deswegen findet er auch den Suchstring praktisch nicht, ausser wenn der Suchstring direkt am Ende des Quellstrings liegt (oder natürlich exakt dieser ist). Das '\n' entfernen macht man am besten mit der Funktion strchr(), kannst ja mal selber hirnen 😉



  • Ich habe das '\n'-Zeichen entfernt und es klappt wunderbar.
    Hier der fertige Code:

    // Zählt Vorkommen von einem String in einem anderen
    
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
    	int result = 0; 		// Für die Anzahl der Vorkommen
    	char quelle[160];		// Quellstring
    	char suche[160];		// Suchstring
    	char nsuche[160];		// Suchstring ohne '\n'
    	char *nullzeichen;	// Ermittelt Position von '\n'
    	int position = 0;		// Position von '\n' im Suchstring
    	char *temp; 				// Deklarierung
    	temp = quelle; 			// Initialisierung
    
    // EINGABE	
    	puts("Geben Sie bitte den String ein, der durchsucht werden soll: ");
    	fgets(quelle, 159, stdin);
    
    	puts("Geben Sie bitte den zu suchenden Begriff ein: ");
    	fgets(suche, 159, stdin);
    
    // '\n' im Suchstring entfernen
    	nullzeichen = strchr(suche, '\n');
    	position = nullzeichen-suche;
    	strncpy(nsuche, suche, position);
    
    // BERECHNUNG
    		while( (temp = strstr(temp, nsuche)) )
    	{ 
        result++; 
        temp++; 
    	}
    
    // AUSGABE
    	printf("\nDer Begriff \"%s\" wurde %d mal gefunden\n", nsuche, result);
    	return 0;
    }
    

    Vielen Dank für die Hilfe!!
    :xmas1:



  • Bei fgets() sollst du schon die echte Länge des Arrays übergeben, nicht länge-1. Die Funktion "denkt" von selbst an die '\0'. Aber tröste dich, das machen fast alle Anfänger falsch 🙂

    Und die Rumrechnerei und Stringkopiererei beim entfernen des '\n' ist auch unnötig. Ein einfaches

    if ( (nullzeichen = strchr(suche, '\n')) ){
        *nullzeichen = '\0';
    }
    

    hätte auch gereicht.
    :xmas1:



  • Hi
    Ich mach das immer so:

    array[strlen(array)]='\0'
    

    Ist das so auch gut, oder überseh ich da was?



  • Jay schrieb:

    Hi
    Ich mach das immer so:

    array[strlen(array)]='\0'
    

    Ist das so auch gut, oder überseh ich da was?

    ja, das ist schon 0 😉
    :xmas2:



  • Mal davon abgesehen, dass das array[strlen(array)] Element eigentlich per Definition schon eine '\0' ist kannst du dir bei fgets() nie sicher sein, dass wirklich ein '\n' hinten drankelebt (im gegensatz zur '\0', die ist sicher).



  • Ok danke euch. Sonst hät ich das noch die nächsten 10 Jahre so geschrieben 🙄



  • Jay schrieb:

    Ok danke euch. Sonst hät ich das noch die nächsten 10 Jahre so geschrieben 🙄

    einem schlauen compiler hätte das nix ausgemacht. hättest vielleicht ein warning gesehen, wie 'removed dead code' 😉



  • char *last = string + strlen(string)-1;
      if(*last == '\n')
        *last = 0;
    

Anmelden zum Antworten