Analizator tekstu w C

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.

#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"


), 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)

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.

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

#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;
  }
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?

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ć:

#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;
  }
0

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

#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;
  }
 
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.

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