Analizator tekstu w C

Analizator tekstu w C
MU
  • Rejestracja:ponad 9 lat
  • Ostatnio:około 3 lata
  • Postów:7
0

Na początek chciałbym się przywitać, bo to mój pierwszy post :)

Treść zadania:

Zaimplementuj program, który wczyta ze standardowego wejścia tekst do analizy, a następnie dla każdej litery
obliczy liczbę jej wystąpieńw tekście i wypisze wynik na standardowe wyjście.
W pierwszym wierszu program przyjmuje liczbę wierszy tekstu do analizy ( ≤150). W każdym z następujących
wierszy ciąg złożony z maksymalnie 200 znaków spośród małych i wielkich liter alfabetu łacińskiego ('a'..'z',
'A'..'Z') oraz spacji.
Przykład

Wejście:
2
ala ma kota
Ola ma psa

Wyjście:
a 7
k 1
l 2
m 2
o 1
p 1
s 1
t 1
O 1

Niestety, samo zadanie, moja niewiedza i kompilator całkowicie zniszczyły mi mózg i nie jestem w stanie wykonać tego prostego zadania.
Zadanie generalnie postanowiłem zrealizować na zasadzie utworzenia dwuwymiarowej tablicy typu char w której upchałbym te wszystkie zdania, a potem zrobić jakieś liczniki zliczające wystąpienia poszczególnych liter i to wyświetlił. Niestety, nawet nie dotarłem do planowania drugiej części zadania, bo ta pierwsza mnie przerosła.

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


int main(){
    int liczba_wierszy,i;
    char **wiersz;
    char wiersz2[200];

    printf("Podaj liczbe wierszy do analizy: ");
    scanf("%d",&liczba_wierszy);
    wiersz=(char**)malloc(liczba_wierszy*sizeof(*wiersz));
    for(i=0;i<liczba_wierszy;i++){
        wiersz[i]=(char*)malloc(200*sizeof(**wiersz));
    }

    for(i=0;i<liczba_wierszy;i++){
        fgets(wiersz2,199,stdin);
        strcpy(wiersz[i],wiersz2);
    }
    printf("%s",wiersz[1]);


getche();
return 0;
}
 

Problem przerósł mnie w pętli - kiedy jest taki warunek jaki jest, program wczytuje (liczba_wierszy-1) linijek zamiast (liczba_wierszy). Kiedy próbowałem barbarzyńsko to obejść dodając w warunku +1 do (liczba_wierszy) - cały program mi się wykrzacza. Z jakiegoś powodu nie działa mi funkcja fgets w odniesieniu do tablicy dwuwymiarowej (czyli fgets(wiersz[i],199,stdin) po prostu nie działa i wykrzacza program, przez co robiłem to za pomocą pomocniczego chara wiersz2 i "strcpy"

Kopiuj

), kompilator mi wariuje i funkcja fgets działała wcześniej tylko wtedy, kiedy wywołałem ją 2 razy pod rząd. Na dodatek, linijka testowa printf("%s",wiersz[i]);, niezależnie od "i" wypisuje mi zawsze pierwszy wczytany przez program wiersz, co oznacza, że to co jest w pętli po prostu nie działa.

Wiem, że kod zapewne wygląda strasznie i w ogóle do d**y, ale każdy kiedyś się uczył. Poprosiłbym o pomoc, sprawdzenie tego programu albo zaproponowanie jakiegoś innego rozwiązania (tylko jakieś proste, bez funkcji bibliotecznych z kosmosu)

Shalom
  • Rejestracja:ponad 21 lat
  • Ostatnio:około 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
0

W zasadzie robisz to totalnie bez sensu. Wczytaj to wszystko jako jednego wielkiego stringa skoro potem nie musisz wcale wyjścia dzielic między linijki. Wiadomo że na wejsciu będzie nie więcej niż 150*201 znaków i taka tablica zupełnie wystarczy. Wczytujesz do niej całe (!) wejście a potem liczysz znaki. Samo zliczanie też jest trywialne bo wystarczy rozumieć że znak to też jest liczba. Każdy (unsigned) char to liczba z zakresu 0-255 więc możesz po prostu używać charów do indeksowania tablicy i robić tablica[znak]++ żeby zliczyć wystąpienie danego znaku.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
_13th_Dragon
Z treści zadana wynika że mają zapoznać się z dynamicznym przydzieleniem, a nie wykonać w najprostszy sposób.
Shalom
@_13th_Dragon jasnowidz? Bo ja NIC o dynamicznej alokacji nie widzę w treści...
_13th_Dragon
Nie, jeszcze nie jasnowidz, jedynie doświadczenie w wyjaśnieniu dziwacznych zadań. Gdyby chodziło o samo zliczanie to nie byłoby: - "... wczyta ... tekst do analizy, a następnie ...". Aczkolwiek można wczytać do głupiego char Text[150][202]; i też będzie zgodnie z zadaniem.
_13th_Dragon
  • Rejestracja:prawie 20 lat
  • Ostatnio:14 dni
0
  1. Postinkrementacja: http://4programmers.net/Forum/1101404
  2. Nie używaj polskiego nazewnictwa: http://4programmers.net/Forum/1208091
  3. Nadawaj sensowne nazwy

http://ideone.com/ednRAO

Kopiuj
#include <stdio.h>
#include <string.h>
 
int main()
  {
   int liczba_wierszy,size,i;
   char **wierszy;
   char wiersz[202]; // 200 znaków plus jeden znak entera plus znak końca
 
   printf("Podaj liczbe wierszy do analizy: ");
   scanf("%d ",&liczba_wierszy);
   wierszy=(char**)malloc(liczba_wierszy*sizeof(char*));
   for(i=0;i<liczba_wierszy;++i)
     {
      fgets(wiersz,201,stdin);
      wierszy[i]=strdup(wiersz);
     }
   printf("Wczytano:\n");
   for(i=0;i<liczba_wierszy;++i) printf("%s",wierszy[i]);
   for(i=0;i<liczba_wierszy;++i) free(wierszy[i]);
   free(wierszy);
   return 0;
  }

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
MU
  • Rejestracja:ponad 9 lat
  • Ostatnio:około 3 lata
  • Postów:7
0

Ok, dzięki za odpowiedź, ale mam jedno pytanie. Co zrobiłeś z funkcją malloc ? Bo w deklaracji wskaźnika jest "" a ty owszem użyłeś "" tylko potem nie robiłeś już nic więcej. Wychodzi na to, że zadeklarowałeś pamięć na (liczba_wiersz) wierszy, ale nie deklarowałeś pamięci na znaki w każdym z tych wierszy - a potem irobisz free() na "wierszy[i]" i "wierszy". Jak to działa ?
Po drugie - po co ci zmienna "size"? Bo z tego co widzę to nie użyłeś jej w programie.
po trzecie - dlaczego w "wiersz" dajesz dodatkowy znak dla "enter"? To nie jest tak, że enter tak jakby zamyka wczytywanie i jest zamieniany na znak końca '\0'?
@Shalom ja wiem, że to zabrzmi głupio, ale w jaki sposób wczytywać wiele zdań do jednego chara, skoro każde z nich potwierdza się Enterem (tak jest w wymogach zadania) a enter przecież kończy wczytywanie?

_13th_Dragon
  • Rejestracja:prawie 20 lat
  • Ostatnio:14 dni
0

Ad 1. strdup()
Ad 2. najpierw chciałem wstawić ten strdup() w kod, rozmyśliłem się, zapomniałem wyczyścić ślady.
Ad 3. fgets wczytuję razem z enterem, chcesz bez '\n' użyj scanf("%200[^\n]",wiersz);
Ad 4. Do tego zadania nie trzeba przydzielać pamięci, ba nawet żadnej tablicy nie trzeba mieć:

Kopiuj
#include <stdio.h>
#include <string.h>
 
int main()
  {
   size_t row,count;
   int ch;
   printf("Podaj liczbe wierszy do analizy: ");
   scanf("%u ",&count);
   for(row=0;(row<count)&&((ch=getchar())!=EOF);row+=(ch=='\n'))
     {
      //putchar(ch); // tu ch kolejny znak z kolejnego wiersza
     }
   puts("koniec");
   return 0;
  }

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.
MU
  • Rejestracja:ponad 9 lat
  • Ostatnio:około 3 lata
  • Postów:7
0

Ok, wielkie dzięki za pomoc, zadanie rozwiązane. Wstawię je tutaj, może ktoś kiedyś będzie szukał to znajdzie.

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

int main()
  {
   int liczba_wierszy,i,j=0;
   char **wierszy;
   char wiersz[202];
   int znaki[123]={};

   printf("Podaj liczbe wierszy do analizy: ");
   scanf("%d ",&liczba_wierszy);
   wierszy=(char**)malloc(liczba_wierszy*sizeof(char*));
   for(i=0;i<liczba_wierszy;i++){
        wierszy[i]=(char*)malloc(200*sizeof(**wierszy));
}
   for(i=0;i<liczba_wierszy;++i)
     {
      fgets(wiersz,201,stdin);
      wierszy[i]=strdup(wiersz);
     }
   for(i=0;i<liczba_wierszy;i++){
   do{
        znaki[wierszy[i][j]]++;
        j++;
   }while(wierszy[i][j]!='\0');
   j=0;
   }
   for(i=65;i>=65&&i<=90;i++)
   {
       if(znaki[i]){
       printf("%c - %d\n",i,znaki[i]);
       }
   }
   for(i=97;i>=97&&i<=122;i++)
   {
       if(znaki[i]){
       printf("%c - %d\n",i,znaki[i]);
       }
   }
   return 0;
  }
 
_13th_Dragon
  • Rejestracja:prawie 20 lat
  • Ostatnio:14 dni
0

Kompletna beznadzieja :/ Może powtórzę jeszcze raz:

  1. Postinkrementacja: http://4programmers.net/Forum/1101404
  2. Nie używaj polskiego nazewnictwa: http://4programmers.net/Forum/1208091
  3. Nadawaj sensowne nazwy
    W gotowym kodzie zamieniasz ++i na i++? Czy zajrzałeś do linka?
    Dajesz bezsensowne do while zamiast dać zwykłego for'a?
    Używasz jakichś liczb zamiast dać pętle literami: for(i='A';i<='Z';++i)` ?
    Dajesz dodatkowe bezsensowne warunki w pętli (i>=97), po kiego przecież zacząłeś od 97 i zwiększasz ?
    Może wiesz jakiś kurs przeczytaj.

Wykonuję programy na zamówienie, pisać na Priv.
Asm/C/C++/Pascal/Delphi/Java/C#/PHP/JS oraz inne języki.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.