ubuntuusers.de

Vergleich zweier char-Arrays

Status: Gelöst | Ubuntu-Version: Ubuntu 20.04 (Focal Fossa)
Antworten |

Data2006

(Themenstarter)

Anmeldungsdatum:
7. November 2021

Beiträge: 899

rklm schrieb:

Nur mal so als Hinweis: es gibt reichlich Algorithmen zur Textsuche, wo man sich bedienen kann. ☺

Danke Dir, aber ich wollte ja mal selber probieren. strlen(...) ist eigentlich schon zuviel.

LG Heiko

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11261

Wohnort: München

Data2006 schrieb:

Nun ja, ich bräuchte doch im text die letzte Möglichkeit wo ich das wort noch finden kann. Gebe ich z. B. "Dies ist ein Te" ein, dann brauche ich gar nicht erst nach dem wort "Test" zu suchen. Nur bei "Dies ist ein Test" kann ich nach dem wort "Test" suchen.

Der Computer weiß nur, dass er einen char-Array mit einem String von bestimmter Länge darin hat - und er muss sich bei einem 4 Zeichen langen Suchbegriff mindestens bis zum viertletzten Zeichen vorarbeiten, um ausschließen zu können, dass dieser String im Text enthalten ist.

Wenn der 1. Buchstabe übreinstimmt, setze ich gefunden = 1, aber wenn dann die restlichen Buchstaben nicht mehr übereinstimmen, gefunden zurück auf 0.

Wie in meinem Code-Beispiel zu sehen kann man auch auf die Zählvariable der inneren for-Schleife schauen und sich eine extra Variable sparen - steigen wir mal an der Stelle nach Zeile 34 ein, wo der Vergleich mit dem ersten Zeichen des Suchbegriffs gerade erfolgreich war und jetzt die Innere for-Schleife zum Einsatz kommt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
            for (j = 1; j < searchLen; j++) {
                if (text[i + j] == search[j]) {
                    printf("Matching character '%c'\n", search[j]);
                } else break;
            }
            if (j != searchLen) {
               printf("Incomplete match - '%c' != '%c' \n", text[i + j], search[j]);
               continue;
            }
            nMatches++;

Die for-Schleife inkrementiert für jeden Durchlauf die Variable j und prüft, ob deren Wert kleiner als die String-Länge des Suchbegriffs ist und führt in dem Fall die nachfolgenden Anweisungen aus. Wenn alle Zeichenvergleiche in der for-Schleife erfolgreich sind, beendet sich die for-Schleife, nachdem sie j auf den einen Wert inkrementiert hat, der der String-Länge des Suchbegriffs entspricht. Wenn ein Vergleich nicht erfolgreich war, greift die break-Anweisung, wodurch die Schleife unmittelbar verlassen wird und j bleibt dadurch kleiner als die Zeichenlänge des Suchbegriffs. Diese Bedingung frage ich in dem nachfolgenden if-Statement ab - wenn die for-Schleife vorzeitig abgebrochen wurde, springe ich mit continue zum nächsten Schleifendurchlauf der äußeren for-Schleife, ansonsten inkrementiere ich den Zähler nMatches für die gefundenen Suchbegriffe.

Data2006

(Themenstarter)

Anmeldungsdatum:
7. November 2021

Beiträge: 899

OK. Danke.

LG Heiko

Data2006

(Themenstarter)

Anmeldungsdatum:
7. November 2021

Beiträge: 899

PS: Dein letzter Code ist etwas anders als in Deinem Codebeispiel. Absichtlich? Könntest Du bitte noch mal das gesamte Programm zeigen? Lieben Dank.

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17621

Wohnort: Berlin

1
  for(i=0;i<strlen(text)-1-strlen(wort);i++)

Wenn der Text ab ist und das Wort b, ist strlen(text) 2, strlen(wort) 1, d.h.

1
for (i=0; i < (2-1-1); i++)

Längere Texte und Wörter ändern nichts daran - wenn das Wort nur ganz am Ende steht, kann es nicht gefunden werden.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13209

Data2006 schrieb:

Danke Dir, aber ich wollte ja mal selber probieren. strlen(...) ist eigentlich schon zuviel.

Oh. Dann posten die Kollegen vielleicht auch schon zu viel Code... 😉

Data2006

(Themenstarter)

Anmeldungsdatum:
7. November 2021

Beiträge: 899

Moin. Hier noch mal das gesamte und geänderte (von seahawk1986) Programm:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main()
{
    char text[100];
    char wort[15];
    int i, x,j, gefunden;
    int anzahl_suchwort=0;
    size_t textLen = 0;
    size_t searchLen = 0;
    size_t nread;

    searchLen = strlen(wort);

    printf("Geben Sie einen Text ein: ");
    fgets(text,100,stdin);
    printf("Geben Sie nun das zu suchende Wort ein: ");
    scanf("%s", wort);
    
    /*äußere Schleife für die Indexe von 'text'*/
    for(i=0;i<strlen(text)-1;i++)
    {
        int nMatches = 0;
        gefunden=0;

        /*Wenn das Zeichen am 'text' an der Indexposition i == Zeichen des 'wort' an
          Indexposition 0*/
        if(text[i]==wort[0] && (strlen(text)-1-i) >= strlen(wort))
        {
            gefunden=1;

            for (j = 1; j < searchLen; j++) {
                if (text[i + j] == wort[j]) {
                    printf("Matching character '%c'\n", wort[j]);
                } else break;
            }
            if (j != searchLen) {
               printf("Incomplete match - '%c' != '%c' \n", text[i + j], wort[j]);
               continue;
            }
            nMatches++;
        }
    }


    return 0;
}

Programm läuft nur nicht:

heiko@Worf:~/C_und_Linux$ ./main
Geben Sie einen Text ein: Dies ist ein Test.
Geben Sie nun das zu suchende Wort ein: ein
Incomplete match - 's' != 'i' 
Incomplete match - 'i' != 'i' 
Incomplete match - 's' != 'i' 
heiko@Worf:~/C_und_Linux$

Lieben Dank, Heiko

Data2006

(Themenstarter)

Anmeldungsdatum:
7. November 2021

Beiträge: 899

Data2006 schrieb:

Ok. Ich setze gefunden auf 1 wenn ein Buchstabe aus text mit dem 1. Buchstaben von Wort übereinstimmt. Und dann in der inneren for-Schleife die restlichen Buchstaben. Findet die Schleife einen Buchstaben, der nicht paßt, setze ich gefunden wieder auf 0 und verlasse die Schleife wieder mit break.

Ich drucke mir mein Programm mal aus, da läßt es sich besser lesen.

Stimmt denn in meinem Programm die if-Bedingung (s. o.)? Oder ist die auch schon falsch?

Lieben Dank, Heiko

@seahawk1986: Konntest Du meiner Ausführung folgen? Oder Logikfehler und das ich falsch an die Sache rangehe?

LG Heiko

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17621

Wohnort: Berlin

Du solltest Dir den Index mit ausgeben, um zu sehen, wo es schief läuft.

Als Messgerät kannst Du diesen Code verwenden:

1
2
3
4
for i in {0..9}; do echo -n {0..9} | sed 's/ //g; '; done | sed 's/0/ /g' ; echo 
 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789 123456789
Dies ist ein Test.
ein

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11261

Wohnort: München

Data2006 schrieb:

PS: Dein letzter Code ist etwas anders als in Deinem Codebeispiel. Absichtlich?

Ich habe da nur eine unnötige Klammerung weggelassen.

Könntest Du bitte noch mal das gesamte Programm zeigen?

Das sieht so aus:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char *text = NULL;
    char *search = NULL;
    size_t textLen = 0;
    size_t searchLen = 0;

    ssize_t nread;

    printf("Geben Sie einen Text ein: ");
    nread = getline(&text, &textLen, stdin);
    // remove newline characters
    text[strcspn(text, "\r\n")] = 0;
    textLen = strlen(text);
    printf("got text of length %zd, stripped %zd\n", nread, strlen(text));

    printf("Geben Sie einen Suchbegriff ein: ");
    nread = getline(&search, &searchLen, stdin);
    // remove newline characters
    search[strcspn(search, "\r\n")] = 0;
    searchLen = strlen(search);
    printf("got search of length %zd, stripped %zd\n", nread, strlen(search));

    int nMatches = 0;
    if (textLen == 0 || searchLen == 0 || searchLen > textLen) goto RESULT;
    size_t i;
    size_t j;
    for (i = 0; i < textLen; i++) {
        printf("Checking '%c'\n", text[i]);
        if (text[i] == search[0] && searchLen <= (textLen - i)) {
            printf("Matching character %c\n", search[0]);
            for (j = 1; j < searchLen; j++) {
                if (text[i + j] == search[j]) {
                    printf("Matching character '%c'\n", search[j]);
                } else break;
            }
            if (j != searchLen) {
               printf("Incomplete match - '%c' != '%c' \n", text[i + j], search[j]);
               continue;
            }
            nMatches++;
        }
    }
RESULT:
    printf("%zd matches found\n", nMatches);
    free(text);
    free(search);
    exit(EXIT_SUCCESS);
}

Das sollte dann für dein Beispiel sowas liefern:

$ ./a.out
Geben Sie einen Text ein: Dies ist ein Test
got text of length 18, stripped 17
Geben Sie einen Suchbegriff ein: ein
got search of length 4, stripped 3
Checking 'D'
Checking 'i'
Checking 'e'
Matching character e
Incomplete match - 's' != 'i'
Checking 's'
Checking ' '
Checking 'i'
Checking 's'
Checking 't'
Checking ' '
Checking 'e'
Matching character e
Matching character 'i'
Matching character 'n'
Checking 'i'
Checking 'n'
Checking ' '
Checking 'T'
Checking 'e'
Matching character e
Incomplete match - 's' != 'i'
Checking 's'
Checking 't'
1 matches found 
Antworten |