ubuntuusers.de

Vergleich zweier char-Arrays

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

Data2006

Anmeldungsdatum:
7. November 2021

Beiträge: 899

Moin zusammen,

ich habe wieder was für Euch. Habe z. Zt. den VS Code im Einsatz.

Ich möchte ein Programm schreiben, wo ich zuerst einen Text eingebe, dann noch ein Wort. Anschließend will ich überprüfen ob das Wort im Text enthalten ist.

Habe hier aber schon ein Problem:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <string.h>

int main()
{
    char text[500];
    char wort[20]="Test1";
    int i;
    int gefunden=0;

   printf("Geben Sie einen Text ein: ");
   fgets(text,500,stdin);
   printf("\n");
   printf("Anzhahl Zeichen: %d\n",strlen(text));
   
   return 0;
}

Wenn ich das Programm laufen lasse und als Text "Dies ist" eingebe, erhalte ich diese Ausgabe:

1
2
3
4
5
heiko@Worf:~/test$ ./main
Geben Sie einen Text ein: Dies ist

Anzhahl Zeichen: 9
heiko@Worf:~/test$ 

Der Text hat ja nur 8 Buchstaben/Zeichen. Wird bei dieser Ausgabe das \0 mitgezählt?

Wenn ich diese Ausgabe angucke:

1
printf("%d\n",strlen("Dies ist"));

, bekomme ich 8 Buchstaben/Zeichen.

Lieben Dank Euch, Heiko

Bearbeitet von rklm:

Syntaxhighlighting. Bitte beachte Forum/Syntax und nutze die Vorschaufunktion.

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11237

Wohnort: München

Da ist noch ein Zeilenumbruch ('\n' aka 0xa) vor dem Nullbyte, das das Ende des Strings anzeigt - das sieht man z.B. so recht gut, wenn man sich den eigelesenen Text zeichenweise ausgeben lässt:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#include <stdio.h>
#include <string.h>

int main()
{
    char text[500];
    char wort[20]="Test1";
    int i;
    int gefunden=0;

   printf("Geben Sie einen Text ein: ");
   fgets(text, 500, stdin);
   printf("\n");
   printf("Anzhahl Zeichen: %d\n",strlen(text));
   for (int i = 0; i < strlen(text); ++i)
   {
       printf("'%c': 0x%x\n", text[i], text[i]);
   }

   return 0;
}

Data2006

(Themenstarter)

Anmeldungsdatum:
7. November 2021

Beiträge: 899

OK. Kann ich den Zeilenumbruch in meinem Programm entfernen oder in beiden Arrays am Ende vergleichen? text[i]==wort[i]

Ist das bei allen Eingabefunktionen so?

Wie siehts da bei C++ mit std::cin >> wort; aus?

Gute Nacht Heiko

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11237

Wohnort: München

Klar kannst du Zeilenenden entfernen - z.B.:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char *line = NULL;
    size_t len = 0;
    ssize_t nread;

    printf("Geben Sie einen Text ein: ");
    nread = getline(&line, &len, stdin);
    printf("Zeile mit der Länge %zd gelesen.\n", nread);

    line[strcspn(line, "\r\n")] = 0; // shorten string to first occurence of newline characters
    printf("Länge nach Entfernen von Zeilenumbrüchen: %zd\n", strlen(line));
    free(line);
    exit(EXIT_SUCCESS);
}

Data2006 schrieb:

Wie siehts da bei C++ mit std::cin >> wort; aus?

Wieso Wort? Ich dachte du willst eine ganze Zeile haben? std::getline verwirft den Delimiter (standardmäig \n, vgl. https://en.cppreference.com/w/cpp/string/basic_string/getline):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#include <iostream>
#include <string>

int main() {
    std::string line;
    std::cout << "Geben Sie einen Text ein: ";
    std::getline(std::cin, line);
    std::cout << "Länge der eingelesenen Zeile ist " << line.length() << std::endl;
    return 0;
}

Humbi

Anmeldungsdatum:
14. Juni 2014

Beiträge: 74

Ich glaube was du suchst ist die Funktion "strstr".

Prototype und include kannst du der manpage entnehmen:

man strstr

oder du verwendest eine selbst programmierte aus meiner Library:

 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
54
55
56
57
58
static int	ft_strlen(const char *s)
{
	int	i;

	i = 0;
	while (s[i] != '\0')
	{
		i++;
	}
	return (i);
}

static char	*find_str(char *h, char *n, size_t nl)
{
	size_t	i;
	size_t	j;

	i = 0;
	j = 0;
	while (h[i] != '\0')
	{
		if (h[i] == n[0])
		{
			while (j < nl && h[i + j] != '\0')
			{
				if (h[i + j] == n[j])
					j++;
				else
				{
					j = 0;
					break ;
				}
			}
			if (j == nl)
				return ((char *)&h[i]);
		}
		i++;
	}
	return (NULL);
}

char	*ft_strstr(const char *haystack, const char *needle)
{
	size_t	k;
	size_t	l;
	char	*hay;
	char	*nee;

	k = ft_strlen(needle);
	l = ft_strlen(haystack);
	hay = (char *)haystack;
	nee = (char *)needle;
	if (k > l)
		return (NULL);
	if (haystack == NULL || needle == NULL || l == 0 || k == 0)
		return (hay);
	return (find_str(hay, nee, k));
}
1
2
if (ft_strstr(text, word) == NULL)
   printf("%s nicht enthalten.\n", word);

Die returned NULL wenn dein String nicht enthalten ist oder einen Pointer auf den Anfang des erste Vorkommen von Needle.

rklm Team-Icon

Projektleitung

Anmeldungsdatum:
16. Oktober 2011

Beiträge: 13131

Data2006 schrieb:

Ich möchte ein Programm schreiben, wo ich zuerst einen Text eingebe, dann noch ein Wort.

Du kannst das effizienter gestalten, wenn Du erst das Suchwort eingibst und dann den (vermutlich längeren) Text.

Übrigens finde ich den Titel des Themas etwas irreführend: Du willst ja suchen und nicht zwei komplette Arrays vergleichen.

Data2006

(Themenstarter)

Anmeldungsdatum:
7. November 2021

Beiträge: 899

Moin. Danke für die zahlreichen Antworten.

Ja, ich habe den Titel etwas unglücklich ausgewählt. wort war natürlich verkehrt. text muß es heißen.

strstr ist wohl das, was ich nehmen könnte. Aber nicht so ganz, was ich mir überlegt hatte. Ich dachte es gäbe was wie in VB(A) oder Basic eine Funktion left$.

Ich wollte eigentlich das Array text Zeichen für Zeichen durchgehen ob das gerade erwählte Zeichen = dem ersten Zeichen von wort übereinstimmt. Und dann gucken ob die restlichen Zeichen mit text auch stimmen. Fällt mir gerade ein, wenn wort mitten im text ist, ist das \n Zeichen am Ende von wort. Das würde mitten im text nicht übereinstimmen. Ich müßte dann sowas probieren:

for(i=0;i<(strlen(wort)-1);i++)
{
       ...
}

@Humbi: Vielen Dank für Deine Funktionen. Ich muß zugeben, ich habe nicht verstanden wie es funktioniert.

LG Heiko

Data2006

(Themenstarter)

Anmeldungsdatum:
7. November 2021

Beiträge: 899

PS: Das \n wird aber nur bei fgets(...) mitgezählt, aber scanf(...) speichert kein \n. Habe noch ein anderes Beispiel probiert:

int main()
{
    char text[500], wort[15];

    printf("Geben Sie einen Text ein: ");
    fgets(text,500,stdin);
    printf("Und nun ein zu suchendes Wort: ");
    scanf("%s", &wort);

    printf("Der Text '%s' hat %d Zeichen.\n",text,strlen(text));
    printf("Das zu suchende Wort '%s' hat %d Zeichen.\n",wort,strlen(wort));

    return 0;
}

Data2006

(Themenstarter)

Anmeldungsdatum:
7. November 2021

Beiträge: 899

Guten Abend.

Ich habe noch was probiert:

#include <stdio.h>
#include <string.h>
int main()
{
    char text[100];
    char wort[15];
    int i, x, gefunden=0;
    int anzahl_suchwort=0;

    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++)
    {
        /*Wenn das Zeichen am 'text' an der Indexposition i == Zeichen des 'wort' an
          Indexposition 0*/
        if(text[i]==wort[0])
        {
            gefunden=1;
            anzahl_suchwort++;

            for(x=1;x<strlen(wort);x++)
            {
                /*Wenn die Zeichen an 'text[i+x]' ungleich 'wort[x]'
                  ist, gefunden wieder auf 0*/
                if(text[i+x]!=wort[x])
                {
                    gefunden=0;
                    anzahl_suchwort--;
                    break;   /*ist break hier richtig? Oder muß es heißen exit for?*/
                }
                
            }
        }

        
    }

    if(gefunden==1)
            printf("gefunden.\n");
        else
            printf("nicht gefunden.\n");

    return 0;
}

Leider läuft das Programm nicht so wie gewünscht:

heiko@Worf:~/C_und_Linux$ ./main
Geben Sie einen Text ein: Dies ist ein Test.
Geben Sie nun das zu suchende Wort ein: Dies
gefunden.
heiko@Worf:~/C_und_Linux$ 
heiko@Worf:~/C_und_Linux$ ./main
Geben Sie einen Text ein: Dies ist ein Test.
Geben Sie nun das zu suchende Wort ein: ist
nicht gefunden.
heiko@Worf:~/C_und_Linux$

Wo ist bei mir der Logikfehler?

Lieben Dank und gute Nacht, Heiko

seahawk1986

Anmeldungsdatum:
27. Oktober 2006

Beiträge: 11237

Wohnort: München

Das Problem ist, dass du gefunden wieder auf 0 setzt, wenn es nach dem Treffer noch eine Zeichenabfolge gab, die nicht passt. Außerdem schaust du nicht, ob du über das Ende des char* mit dem Text hinaussuchst - die find_str Funktion von Humbi aus 9333830 und die kapselnde ft_strstr zeigt schön, worauf man da alles achten muss, wenn man nach dem Substring sucht. In Ermangelung eines for-else Konstrukts (wie es Python bietet) könnte man das z.B. so machen:

 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", nMatches);
    free(text);
    free(search);
    exit(EXIT_SUCCESS);
}

Data2006

(Themenstarter)

Anmeldungsdatum:
7. November 2021

Beiträge: 899

Moin.

Es stimmt ich habe nicht mal das Ende von text überprüft. Das hatte ich in nem anderen Programm versucht. Ich müßte diese Abfrage erweitern:

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

Das Beispiel von Dir (seahawk1986) verstehe ich nicht. Das ist mir zu komplex. (s)size_t kenne ich nicht.

Ich versuche es noch bischen, wenn es nicht klappen sollte, höre ich damit auf und gucke weiter YouTube. Kennt jemand die C-Reihe von Franneck? Was haltet Ihr davon?

LG und schönen Samstag noch, Heiko

Data2006

(Themenstarter)

Anmeldungsdatum:
7. November 2021

Beiträge: 899

Ich müßte strlen(text)-i auf größer >= als strlen(wort) einfügen ne?

user_unknown

Avatar von user_unknown

Anmeldungsdatum:
10. August 2005

Beiträge: 17595

Wohnort: Berlin

Du bist mehr am C-Lernen interessiert, als an Wortvergleichen, stimmts?

Sonst könnte ich für die Shell contains empfehlen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
contains () 
{ 
    param=$1;
    shift;
    for elem in "$@";
    do
        [[ "$param" = "$elem" ]] && return 0;
    done;
    return 1
}

Ich bin mitten am Aufbrechen, sonst würde ich vielleicht versuchen, altes C-Wissen zu reaktivieren. Aber Wortfinden ist ein so klassisches Computerproblem - man wird bestimmt von Suchresultaten überwältigt.

Bei der Shellfunktion oben gibt man erst das Suchwort, dann den Text ein:

1
contains Baum Wald Bäume Bäume Laubbaum Nadelbaum Stammbaum Verzeichnisbaum Nussbaum

Data2006

(Themenstarter)

Anmeldungsdatum:
7. November 2021

Beiträge: 899

Danke für die Antwort. Aber ja, ich bin am C-Lernen oder -Auffrischen interessiert. Ich hatte mal in nem Kurs (so ´97/´98) u. a. C gelernt. Und später auch C++. Wollte mit YouTube meine alten Kenntnisse nur was auffrischen. Dachte wäre ganz einfach einen Text in einem anderen Text zu suchen. Ich probiere am WE noch was aus, dann breche ich ab und gehe YouTube zu Ende durch.

LG Heiko

Data2006

(Themenstarter)

Anmeldungsdatum:
7. November 2021

Beiträge: 899

Meine if-Anweisung if(text[i]==wort[0]) habe ich auf dem Papier schon mal erweitert.

if(text[i]==wort[0] && strlen(text)-1-i >= strlen(wort) //Ich ziehe von der text-Länge 1 ab für das \n
{
    ….
}

Hoffe es geht dann.

LG Heiko

Antworten |