[C] Wyszukiwanie podciągu w ciągu znaków

0

Mam napisać program, który wczytuje zdanie rozumiane jako np. "Ala ma kota, a kot jest zielony" i zlicza ilość wystąpień danego słowa w zdaniu. Słowa rozumianego jako identyczny ciąg znaków o takiej samej długości czyli kot i kota to dwa różne słowa. Jak na razie doszedłem do programu, który wczytuje ciąg znaków i właśnie. Nie mogę tego ogarnąć. Mam wczytywać całe zdanie przez fgets()? Kompletnie nie jestem wstanie wymyślić nawet zalążka programu.

0
#include <string.h>

char *zdanie, *wyraz, *gdzie;
int ile_razy = 0;

gdzie = strstr(zdanie, wyraz);
while(gdzie != NULL)
{
	ile_razy++;
	gdzie = strstr(gdzie + 1, wyraz);
}
0

Niestety dalej niewiele mi to mówi, znaczy. Rozumiem co te funkcje robią, ale nie potrafię ogarnąć czy mam stworzyć sobie zdanie "wzorzec" przy wczytywaniu tzn. zdanie, które ma każde wystąpienie słowa tylko raz i w warunku sprawdzać czy kolejne wczytywane słowo jest we wzorcu. Jeżeli tak to do drugiej tablicy o tym samym indeksowaniu* zwiększyć wystąpienie danego słowa o jeden

  • Nie wiem tylko jak całe słowo zrobić jako jeden element tablicy. Ponieważ słowa w char zdanie[] będą podzielone na każda literka jako jeden element?

No właśnie tyle w teorii, bo w praktyce to nawet nie wiem jak to zrobić co wyżej napisałem...

0
#include <iostream>
#include <cstring>

char * znajdzWyraz(char * zrodlo, const char * szukanyWyraz);
int zliczSlowa(char * zrodlo, const char * szukanyWyraz);

int main()
{
    using namespace std;

    cout << zliczSlowa("Ala ma kota, a kot jest zielony.", "kot") << endl;
    cout << zliczSlowa("Idzie sobie stonoga i boli ja noga.", "sobi") << endl;

    return 0;
}

char * znajdzWyraz(char * zrodlo, const char * szukanyWyraz)
{
    using namespace std;

    const char * poczatekSzukanegoWyrazu = szukanyWyraz;
    char * aktualnaPozycjaZrodla = zrodlo;

    while (*zrodlo)
    {
        szukanyWyraz = poczatekSzukanegoWyrazu;
        zrodlo = aktualnaPozycjaZrodla;

        while (*zrodlo == *szukanyWyraz)
        {
            if (*zrodlo == '\0' && *szukanyWyraz == '\0')
                break;

            zrodlo++;
            szukanyWyraz++;
        }

        if (*szukanyWyraz == '\0')
            if (*zrodlo == ' ' || *zrodlo == '\0')
                return aktualnaPozycjaZrodla;

        aktualnaPozycjaZrodla++;
    }

    return NULL;
}

int zliczSlowa(char * zrodlo, const char * szukanyWyraz)
{
    using namespace std;

    char * miejsceWLancuchu = znajdzWyraz(zrodlo, szukanyWyraz);
    int licznik = 0;

    while (miejsceWLancuchu)
    {
        licznik++;
        miejsceWLancuchu = znajdzWyraz(miejsceWLancuchu + 1, szukanyWyraz);
    }

    return licznik;
}
0

No tak, to działa jak strcmp(), ale tutaj jest konkretne jedno słowo, a mam zliczać ilość każdego słowa w zdaniu (nie wiem czy wcześniej to tak precyzyjnie określiłem) co jest właśnie ta najtrudniejszą rzeczą dla mnie do ogarnięcia, bo samo sprawdzanie czy dane słowo wystąpiło w zdaniu i zliczanie tego nie jest trudne. Problem mam jak w jakiejś "tablicy" char buffor[] to mam "rozbić" zdanie na pojedyncze, unikalne słowa i przechowywać słowo w tej tablicy, sprawdzić ilość wystąpień i przejść do następnego słowa.

0

Tzn. chcesz policzyć ilość wszystkich słów w łańcuchu, czy ilość określonych słów? Bo jak to drugie, to masz już napisane.

0

Ilość wszystkich słów np.
"Kot kot kot ziemniak kotlet kot kot kota ziemniaki" to będę miał wypisane
5 - kot
1 - ziemniak
1 - kotlet
1 - kota
1 - ziemniaki

0
#include <iostream>
#include <cstring>
#include <cctype>

char * wszystkieSlowaWLancuchu[10000];

char * znajdzWyraz(char * zrodlo, const char * szukanyWyraz);
int zliczSlowa(char * zrodlo, const char * szukanyWyraz);
int osobneSlowa(char * zrodlo, char ** slowa);

int main()
{
    using namespace std;

    cout << "Podaj zdanie: ";
    char zdanie[100000];
    cin.getline(zdanie, 100000);

    int iloscSlow = osobneSlowa(zdanie, wszystkieSlowaWLancuchu);

    for (int i = 0; i < iloscSlow; i++)
        cout << wszystkieSlowaWLancuchu[i] << " - " << zliczSlowa(zdanie, wszystkieSlowaWLancuchu[i]) << endl;

    return 0;
}

char * znajdzWyraz(char * zrodlo, const char * szukanyWyraz)
{
    using namespace std;

    const char * poczatekSzukanegoWyrazu = szukanyWyraz;
    char * aktualnaPozycjaZrodla = zrodlo;

    while (*zrodlo)
    {
        szukanyWyraz = poczatekSzukanegoWyrazu;
        zrodlo = aktualnaPozycjaZrodla;

        while (tolower(*zrodlo) == tolower(*szukanyWyraz))
        {
            if (*zrodlo == '\0' && *szukanyWyraz == '\0')
                break;

            zrodlo++;
            szukanyWyraz++;
        }

        if (*szukanyWyraz == '\0')
            if (*zrodlo == ' ' || *zrodlo == '\0')
                return aktualnaPozycjaZrodla;

        aktualnaPozycjaZrodla++;
    }

    return NULL;
}

int zliczSlowa(char * zrodlo, const char * szukanyWyraz)
{
    using namespace std;

    char * miejsceWLancuchu = znajdzWyraz(zrodlo, szukanyWyraz);
    int licznik = 0;

    while (miejsceWLancuchu)
    {
        licznik++;
        miejsceWLancuchu = znajdzWyraz(miejsceWLancuchu + 1, szukanyWyraz);
    }

    return licznik;
}

int osobneSlowa(char * zrodlo, char ** slowa)
{
    using namespace std;
    char slowo[80];
    int i = 0;
    int j = 0;
    bool czyJuzJestTakieSlowo;

    while (*zrodlo)
    {
        czyJuzJestTakieSlowo = false;
        while (*zrodlo != ' ' && *zrodlo != '\0')
        {
            slowo[i] = tolower(*zrodlo);
            i++;
			zrodlo++;
        }

		zrodlo++;

        slowo[i] = '\0';
        i = 0;

        for (int a = 0; a < j; a++)
            if (strcmp(slowo, slowa[a]) == 0)
            {
                czyJuzJestTakieSlowo = true;
                break;
            }

        if (!czyJuzJestTakieSlowo)
        {
            slowa[j] = new char [strlen(slowo) + 1];
            strcpy(slowa[j], slowo);
            j++;
        }
    }

    return j;
}
 
0

ps. Zapomniałem o zwolnieniu pamięci na końcu. Trzeba dopisać pod koniec main:

for (int i = 0; i < iloscSlow; i++)
delete [] wszystkieSlowaWLancuchu[i];

0

Były błędy. Teraz działa dobrze:

 #include <iostream>
#include <cstring>
#include <cctype>

char * wszystkieSlowaWLancuchu[10000];
char * znajdzWyraz(char * zrodlo, const char * szukanyWyraz);
int zliczSlowa(char * zrodlo, const char * szukanyWyraz);
int osobneSlowa(char * zrodlo, char ** slowa);

int main()
{
    using namespace std;

    cout << "Podaj zdanie: ";
    char zdanie[100000];
    cin.getline(zdanie, 100000);

    int iloscSlow = osobneSlowa(zdanie, wszystkieSlowaWLancuchu);

    for (int i = 0; i < iloscSlow; i++)
        cout << wszystkieSlowaWLancuchu[i] << " - " << zliczSlowa(zdanie, wszystkieSlowaWLancuchu[i]) << endl;

    for (int i = 0; i < iloscSlow; i++)
        delete [] wszystkieSlowaWLancuchu[i];

    return 0;
}

char * znajdzWyraz(char * zrodlo, const char * szukanyWyraz)
{
    using namespace std;

    const char * poczatekSzukanegoWyrazu = szukanyWyraz;
    char * aktualnaPozycjaZrodla = zrodlo;
    char * poczatekZrodla = zrodlo;

    while (*zrodlo)
    {
        szukanyWyraz = poczatekSzukanegoWyrazu;
        zrodlo = aktualnaPozycjaZrodla;

        while (tolower(*zrodlo) == tolower(*szukanyWyraz))
        {
            if (aktualnaPozycjaZrodla != poczatekZrodla)
                if (aktualnaPozycjaZrodla[-1] != ' ')
                    break;

            if (*zrodlo == '\0' && *szukanyWyraz == '\0')
                break;

            zrodlo++;
            szukanyWyraz++;
        }

        if (*szukanyWyraz == '\0')
            if (*zrodlo == ' ' || *zrodlo == '\0')
                return aktualnaPozycjaZrodla;

        aktualnaPozycjaZrodla++;
    }

    return NULL;
}

int zliczSlowa(char * zrodlo, const char * szukanyWyraz)
{
    using namespace std;

    char * miejsceWLancuchu = znajdzWyraz(zrodlo, szukanyWyraz);
    int licznik = 0;

    while (miejsceWLancuchu)
    {
        licznik++;
        miejsceWLancuchu = znajdzWyraz(miejsceWLancuchu + 1, szukanyWyraz);
    }

    return licznik;
}

int osobneSlowa(char * zrodlo, char ** slowa)
{
    using namespace std;
    char slowo[80];
    int i = 0;
    int j = 0;
    bool czyJuzJestTakieSlowo;

    while (*zrodlo)
    {
        czyJuzJestTakieSlowo = false;
        while (*zrodlo != ' ' && *zrodlo != '\0')
        {
            slowo[i] = tolower(*zrodlo);
            i++;
			zrodlo++;
        }

		if (*zrodlo != '\0')
			zrodlo++;

        slowo[i] = '\0';
        i = 0;

        for (int a = 0; a < j; a++)
            if (strcmp(slowo, slowa[a]) == 0)
            {
                czyJuzJestTakieSlowo = true;
                break;
            }

        if (!czyJuzJestTakieSlowo)
        {
            slowa[j] = new char [strlen(slowo) + 1];
            strcpy(slowa[j], slowo);
            j++;
        }
    }

    return j;
}
0

Jeszcze jedna poprawka:

#include <iostream>
#include <cstring>
#include <cctype>

char * wszystkieSlowaWLancuchu[10000];
char * znajdzWyraz(char * zrodlo, const char * szukanyWyraz);
int zliczSlowa(char * zrodlo, const char * szukanyWyraz);
int osobneSlowa(char * zrodlo, char ** slowa);

int main()
{
    using namespace std;

    cout << "Podaj zdanie: ";
    char zdanie[100000];
    cin.getline(zdanie, 100000);

    int iloscSlow = osobneSlowa(zdanie, wszystkieSlowaWLancuchu);

    for (int i = 0; i < iloscSlow; i++)
        cout << wszystkieSlowaWLancuchu[i] << " - " << zliczSlowa(zdanie, wszystkieSlowaWLancuchu[i]) << endl;

    for (int i = 0; i < iloscSlow; i++)
        delete [] wszystkieSlowaWLancuchu[i];

    return 0;
}

char * znajdzWyraz(char * zrodlo, const char * szukanyWyraz)
{
    using namespace std;

    const char * poczatekSzukanegoWyrazu = szukanyWyraz;
    char * aktualnaPozycjaZrodla = zrodlo;
    char * poczatekZrodla = zrodlo;

    while (*zrodlo)
    {
        szukanyWyraz = poczatekSzukanegoWyrazu;
        zrodlo = aktualnaPozycjaZrodla;

        if (aktualnaPozycjaZrodla != poczatekZrodla)
            if (aktualnaPozycjaZrodla[-1] != ' ')
            {
                aktualnaPozycjaZrodla++;
                continue;
            }

        while (tolower(*zrodlo) == tolower(*szukanyWyraz))
        {

            if (*zrodlo == '\0' && *szukanyWyraz == '\0')
                break;

            zrodlo++;
            szukanyWyraz++;
        }

        if (*szukanyWyraz == '\0')
            if (*zrodlo == ' ' || *zrodlo == '\0')
                return aktualnaPozycjaZrodla;

        aktualnaPozycjaZrodla++;
    }

    return NULL;
}

int zliczSlowa(char * zrodlo, const char * szukanyWyraz)
{
    using namespace std;

    char * miejsceWLancuchu = znajdzWyraz(zrodlo, szukanyWyraz);
    int licznik = 0;

    while (miejsceWLancuchu)
    {
        licznik++;
        miejsceWLancuchu = znajdzWyraz(miejsceWLancuchu + 1, szukanyWyraz);
    }

    return licznik;
}

int osobneSlowa(char * zrodlo, char ** slowa)
{
    using namespace std;
    char slowo[80];
    int i = 0;
    int j = 0;
    bool czyJuzJestTakieSlowo;

    while (*zrodlo)
    {
        czyJuzJestTakieSlowo = false;
        while (*zrodlo != ' ' && *zrodlo != '\0')
        {
            slowo[i] = tolower(*zrodlo);
            i++;
			zrodlo++;
        }

		if (*zrodlo != '\0')
			zrodlo++;

        slowo[i] = '\0';
        i = 0;

        for (int a = 0; a < j; a++)
            if (strcmp(slowo, slowa[a]) == 0)
            {
                czyJuzJestTakieSlowo = true;
                break;
            }

        if (!czyJuzJestTakieSlowo)
        {
            slowa[j] = new char [strlen(slowo) + 1];
            strcpy(slowa[j], slowo);
            j++;
        }
    }

    return j;
}
 

1 użytkowników online, w tym zalogowanych: 0, gości: 1