• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Funkcja wskaźnikowa wyznaczająca liczbę słów w tablicy.

Object Storage Arubacloud
0 głosów
402 wizyt
pytanie zadane 24 kwietnia 2022 w C i C++ przez xTMx3 Obywatel (1,560 p.)

Witam,

podobnie jak w poprzednim zadanym przeze mnie pytaniu, mam znowu problem z napisaniem funkcji. Tym razem jednak, funkcja ma zwracać ilość słów w tablicy. 

Polecenie brzmi następująco: Napisz funkcję wyznaczającą liczbę słów w tablicy s. Za "słowo" proszę przyjąć ciąg liter, cyfr i znaków podkreślenia. Słowa mogą być rozdzielane jednym lub wieloma znakami spacji, tabulacji, czy podziału wiersza. 

 

Gdyby była mowa o tylko jednej spacji czy tylko jednym innym znaku podziału napisałbym coś takiego:

int str_word_count(char * s)
{
    int licznik_slow = 1;
    bool czyZnak;

    for(; *s != '\0'; ++s)
    {
        czyZnak = false;
        if(*s == 32 || *s == 9 || *s == 11)
        {
            czyZnak = true;

        }
        if(czyZnak)
        {
            licznik_slow++;
        }
    }
    return licznik_slow;
}

Jednak mój problem leży w tym, że nie mam pomysłu w jaki sposób mógłbym zliczać te słowa w przypadku, gdy jest więcej niż jedna spacja, czy którykolwiek z innych znaków, bo powyższy kod w takim przypadku zwróci po prostu błędną wartość. 

Chciałbym więc prosić o pomoc w modyfikacji, a raczej podpowiedź w jaki sposób mógłbym go poprawić, aby słowa były poprawnie zliczane i żeby większa ilość spacji, czy innych rozdzielników słów nie powodowała problemu. 

Za wszelkie odpowiedzi z góry dziękuję.  

 

1 odpowiedź

+1 głos
odpowiedź 24 kwietnia 2022 przez edutomek Dyskutant (8,380 p.)
wybrane 26 kwietnia 2022 przez xTMx3
 
Najlepsza
Na szybko pewna idea: jeśli analizujesz napis znak po znaku, szukając słów (rozdzielonych ciągami białych znaków), to powinieneś w kodzie uwzględnić dwa tryby pracy (w pętli): tryb, w którym aktualnie analizujesz słowo, oraz tryb, w którym aktualnie analizujesz ciąg białych znaków. Słowa można zliczać przy zmianie trybu na słowo. Przy pierwszym znaku napisu (argument funkcji) należy określić początkowy tryb (albo słowo, albo białe znaki). Zmiana trybu następuje, gdy odczytany znak nie będzie należał do aktualnie analizowanej grupy (słowa lub białych znaków).
komentarz 24 kwietnia 2022 przez xTMx3 Obywatel (1,560 p.)
edycja 24 kwietnia 2022 przez xTMx3
Może nie widać tego zbyt dobrze w tym co pokazałem powyżej, ale chciałem spróbować zrobić to w podobny sposób jak opisałeś, tylko właśnie tu leży cała rzecz, bo nie przychodzi mi do głowy nic poza skorzystaniem z tego bool'a, a on nie do końca działa jak należy (bo poprawny wynik mam  jedynie wtedy jak jest tylko jedna spacja itp.).

Czy mógłbyś trochę jaśniej opisać w jaki sposób to zrobić, tak żeby to co blokuje moją głowę w zauważeniu poprawnego rozwiązania zniknęło?
( i mam tu na myśli jakiś opis słowny tego, bo kod chciałbym napisać sam, a przynajmniej spróbować)

Poza tym, mam jeszcze jedną wątpliwość, o której zapomniałem wspomnieć zadając pytanie.

Polecenie mówi "Słowa mogą być rozdzielane jednym lub wieloma znakami spacji, tabulacji, czy podziału wiersza.". Szukając tych znaków w tablicy ASCII sprawdziłem, że spacja w zapisie dziesiętnym ma wartość 32, tabulator poziomy 9.

Natomiast nie wiem, czy ten "znak podziału wiersza" jest "tabulatorem pionowym" w tablicy ASCII, którego wartość dziesiętna wynosi 11, czy mylę się i chodzi o coś innego?

Wiesz może, czy dobrze myślę, że chodzi o to, czy może o coś innego?
1
komentarz 24 kwietnia 2022 przez edutomek Dyskutant (8,380 p.)
Skąd wziął się bool? To powinien być raczej int, czy może enum - bo wtedy liczba różnych trybów/stanów pracy może być większa.

Może tak: załóżmy, że mamy tylko dwa tryby pracy - "słowo" albo "nie-słowo".

Sprawdzamy pierwszy znak. Jeśli to biały znak, to zaczynamy od trybu "nie-słowo". W przeciwnym przypadku - od "słowo" (i zwiększamy licznik słów o 1).

Dalej, dla każdego znaku sprawdzamy typ znaku (biały lub nie-biały), i w zależności od (tryb, typ znaku) odpowiednio postępujemy:

typ znaku = biały, tryb = nie-słowo -> bez zmian, sprawdzać znaki dalej
typ znaku = biały, tryb = słowo -> skończyło się słowo, przechodzimy do trybu nie-słowo i sprawdzamy znaki dalej
typ znaku = nie-biały, tryb = słowo -> bez zmian, sprawdzać znaki dalej
typ znaku = nie-biały, tryb = nie-słowo -> skończyły się białe znaki, przechodzimy do trybu słowo, zwiększamy liczbę słów i sprawdzamy znaki dalej

(W tej logice mogłem coś namieszać, piszę to na szybko.)

Teraz wystarczy napisać funkcję (albo kod) do rozpoznawania typu znaku (biały / nie biały / jeszcze coś innego, wedle potrzeb) i powinno działać.

Odnośnie białych znaków, to nie wiem, jakie to mogą konkretnie być. Ale może wystarczy założyć, że spacje + '\n', '\t', '\r' i podobne? Może warto byłoby zrobić sobie tablicę z takimi znakami - wtedy poprzez modyfikację zawartości tablicy można byłoby ten zbiór ewentualnie rozszerzać?
1
komentarz 25 kwietnia 2022 przez TOWaD Mądrala (5,700 p.)
edycja 26 kwietnia 2022 przez TOWaD

Za "słowo" proszę przyjąć ciąg liter, cyfr i znaków podkreślenia.

Słowa mogą być rozdzielane jednym lub wieloma znakami spacji, tabulacji, czy podziału wiersza. 

np strumień std::cin  czy istream wyrzuca białe znaki;

edit:

//Tylko jako inspirację bo te funkcje mi 2 komputer rozwaliły

/******************************************************************************

                              Online C++ Compiler.
               Code, Compile, Run and Debug C++ program online.
Write your code in this editor and press "Run" button to compile and execute it.

*******************************************************************************/

#include <iostream>
#include <sstream>
 
 
std::size_t f1(char * words){
    std::string sword;
    std::stringstream ss(words);
    std::size_t i=0;
    for (;ss>>sword;i++);
    std::cout<<"\nLiczba slow (f1): "<<i<<std::endl;
    return i;
}
 
std::size_t f2(char * words){
    char * ptrForMoving = words;
    bool flag = false;
    std::size_t i=0;
    for (;(* ptrForMoving)!=0;ptrForMoving++){
        switch(static_cast<int>(*ptrForMoving)){
            case '\r':
            case '\n':
            case '\t':
            case ' ':
            if(flag) {i++;flag=false;}
            break;
             
            case '0' ... '9' :
            case 'A' ... 'Z' :
            case 'a' ... 'z' :
            case '_' :
                flag=true;
            break;
             
            default : std::cerr<< "\n ---nieznany znak---" <<std::flush;
        }
    }if(flag) i++;
     
    std::cout<<"\nLiczba slow (f2): "<<i<<std::endl;
    return i;
}
using namespace std;
int main()
{
   char tab[]= "Hello \n World \t \
    ff_11 spokp 111ghh_sff \t \n\
    aoajio rtpopq 22244lka \
    \n akkpo \t";
    f1(tab);
    f2(tab);

    return 0;
}

//Za to fajny jest regex

komentarz 26 kwietnia 2022 przez xTMx3 Obywatel (1,560 p.)

@TOWaD, dzięki za to rozwiązanie, na pewno sobie je przejrzę bo jest dużo dłuższe niż cokolwiek o czym myślałem do tej pory, jednak pierwsze zdanie z odpowiedzi na mój komentarz, które napisał @edutomek, nasunęło mi pewną myśl i udało mi się wymyślić coś na "własny" sposób.

Obu wam dziękuję za odpowiedzi i pomoc. 

Podobne pytania

0 głosów
2 odpowiedzi 515 wizyt
pytanie zadane 25 grudnia 2020 w C i C++ przez dark41 Użytkownik (760 p.)
0 głosów
0 odpowiedzi 360 wizyt
pytanie zadane 23 października 2017 w C i C++ przez chucksqll Stary wyjadacz (12,930 p.)
0 głosów
1 odpowiedź 512 wizyt
pytanie zadane 14 marca 2019 w C i C++ przez Curiosis Użytkownik (540 p.)

92,556 zapytań

141,404 odpowiedzi

319,563 komentarzy

61,942 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...