Zliczanie liter słowa – jak to powinno wyglądać?

0

Witam, chcę napisać program zliczający ilość wystąpień kazdej litery słowa wczytanego wcześniej do tablicy. program powinien się opierać na funkcjach getchar i putchar. Czy coś takiego ma sens, czy inaczej to powinno być?

#include <stdio.h>
#define R 20
int main()
{
    int white = 0, other = 0;
    char nazwa[R] = { 'a' };
    int ilosc_znakow[R];
    int i = 0;
    printf("Maksymalna dlugosc nazwy to: %d\n ", R);
    while (i < R && nazwa[i] != EOF) {
        nazwa[i] = getchar();
        i++;
    }
    i = 0;
    while (i < R && nazwa[i] != EOF) {
        putchar(nazwa[i]);
        i++;
    }
    //for(int i=0;i<strlen(nazwa);i++)
    i = 0;
    while ((nazwa[i] = getchar()) != EOF) {
        if (nazwa[i] >= 'a' && nazwa[i] <= 'z') {
            ilosc_znakow[nazwa[i] - 'a']++;
        }
        else if (nazwa[i] == ' ' || nazwa[i] == '\n' || nazwa[i] == '\t') {
            white++;
        }
        else {
            other++;
        }
        i++;
    }
    for (char i = 'a'; i < 'z'; i++) {
        printf("%c : %d\n", i, ilosc_znakow[i]);
    }
    printf("Znaki biales: %d, znaki inne: %d", white, other);
    return 0;
}
1

Dwa błędy na dzień dobry w pętli while:

  • masz getchar zamiast getchar()
  • z poprzedniej lekcji zapomniałaś, że są problemy z przesłaniem EOF do stdin z konsoli, i lepiej nie używać takiego warunku przerwania pętli.
0

Bardzo dobry kod, ale potrzeba kilka poprawek:

  1. 'R' proponuję zamienić na coś bardziej znaczącego, np. WORD_MAX_LEN

  2. kod

int ilosc_znakow[R];

zamień na:

int ilosc_znakow['z' - 'a' + 1];
  1. kod:
printf("%c : %d\n",i,ilosc_znakow[i]);

zamień na:

printf("%c : %d\n",i,ilosc_znakow[i - 'a']);
  1. przetestuj na kilku słowach
1

Kolejny drobny błąd - nie inicjujesz tablicy int iloscZnakow[R] zerami, przez co fałszuje Ci wyniki.

1

Bardzo prosto Kamilka, definiujesz ją tak:

int iloscZnakow[R] = { 0 };
0

Poprawione. Jednak program dalej zatrzymuje się na wczytaniu i wypisaniu wyrazu.

0

Zamień:

while((nazwa[i]=getchar())!=EOF)

na:

while(nazwa[i])
0
#include <stdio.h>
#define R 20
int main()
{
    int white = 0, other = 0;
    char nazwa[R] = { 'a', '\0' };
    int ilosc_znakow['z' - 'a' + 1] = { 0 };
    int i = 0;
    int c = 0;
    printf("Maksymalna dlugosc nazwy to: %d\n ", R);
    while (i < R) {
        c = getchar();
        if (c == EOF)
            break;
        nazwa[i] = c;
        i++;
    }
    i = 0;
    while (nazwa[i]) {
        putchar(nazwa[i]);
        i++;
    }
    //for(int i=0;i<strlen(nazwa);i++)
    i = 0;
    while (nazwa[i]) {
        if (nazwa[i] >= 'a' && nazwa[i] <= 'z') {
            ilosc_znakow[nazwa[i] - 'a']++;
        }
        else if (nazwa[i] == ' ' || nazwa[i] == '\n' || nazwa[i] == '\t') {
            white++;
        }
        else {
            other++;
        }
        i++;
    }
    for (char i = 'a'; i < 'z'; i++) {
        printf("%c : %d\n", i, ilosc_znakow[i - 'a']);
    }
    printf("Znaki biales: %d, znaki inne: %d", white, other);
    return 0;
}

Poprawiłem na tyle żeby działało bez krzaków na ekranie.

2
Kamila Nowak napisał(a):

Witam, chcę napisać program zliczający ilość wystąpień kazdej litery słowa wczytanego wcześniej do tablicy. program powinien się opierać na funkcjach getchar i putchar. Czy coś takiego ma sens, czy inaczej to powinno być?

Cześć. Kiedyś napisałem podobny program, tylko że zlicza same, konkretne litery, bez spacji czy innych znaków, ale łatwo to zmodyfikować korzystając z gotowych funkcji obsługi znaków z pliku cctype, takich jak np. isspace() itd. Możesz sobie porównać.

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

int main()
{
   int f = 0; int i=0; int i2=0;
   char ch;


   char const alf[] = "abcdefghijklmnopqrstuvwxyz";
   int wynik[26] = {[25] = 0}; //jeżeli do jednego elementu przypiszemy zero, to reszta elementow automatycznie otrzymuje zera

   printf("Wpisz jakies slowo, a ja wypisze, ile razy wystepuje dana litera\n");
   printf("Wpisz slowo: \n");

   while( (ch = getchar()) != '\n')
   {
       while(f<1)
       {
        if(i==26)
          break;

        if(ch == alf[i])
        {
           i2++;
           wynik[i]++;
           f=1;
        } i++;

       } f=0; i=0;
   } i=0;

   printf("\nPodane slowo ma %d liter\n", i2);
   printf("\nZawiera nastepujace litery:\n");

   while(i<26)
   {
       if(wynik[i] == 0)
       {
           i++;
           continue;
       }

       printf("Litera %c wystepuje %d razy\n", alf[i], wynik[i]);
       i++;
   }
   getchar();

    return 0;
}

1

W programowaniu na taką zmienną mówi się zmienna flagowa lub flaga. Można powiedzieć, że flaga to zmienna, która po otrzymaniu konkretnej wartości, pozwoli komputerowi przejść do konkretnej części programu (najczęściej są to wartości true lub false czyli 1 lub 0). Nie wiem, czy dobrze zdefiniowałem co to jest flaga, jeżeli masz jakieś wątpliwości, co to jest w ogóle flaga w programowaniu, to poczytaj o tym na necie, a teraz wytłumaczę, co konkretnie robi ta zmienna w tym programie:
W tym przypadku zmienna f jest potrzebna do pętli while(f<1), czyli pętla ma się wykonywać tak długo, dopóki prawdą jest, że zmienna f jest mniejsza od 1. Domyślnie ta zmienna jest ustawiona na 0, czyli program przechodzi do tej pętli i wykonuje tam wszystkie czynności. W tej pętli chodzi o to, żeby sprawdzać po kolei zawartość tablicy alf z pobranym znakiem w zmiennej ch - jeżeli litera w zmiennej ch równa się którejś wartości z tablicy alf[], to wartość zmiennej wynik[] jest zwiększana o 1 (myślę, że rozumiesz algorytm tego programu? zresztą widać to po działaniu programu i po tym, co wypisuje ostatnia pętla), a następnie flaga otrzymuje wartość 1. Wtedy program ponownie przechodzi do warunku pętli i tym razem warunek pętli jest już fałszywy, gdyż zmienna f=1, a powinna być <1, żeby pętla się dalej wykonywała. Ponieważ warunek pętli jest fałszywy, program wychodzi z niej, z powrotem ustawia flage na 0 i wraca do pętli głównej while( (ch = getchar()) != '\n'), żeby pobrać kolejny znak i powtórzyć wszystkie czynności, aż dojdzie do znaku nowej linii.

1

Można takie coś xD:

while( (ch = getchar()) != '\n')
   {
       while(1)
       {
        if(i==26)
          break;

        if(ch == alf[i])
        {
           i2++;
           wynik[i]++;
           i++;
           break;
        }

       } f=0; i=0;
   } i=0;

Wiesz na jakiej zasadzie teraz to działa? ;)
A co, nie podoba Ci się sama idea stosowania flagi jako warunku w pętli/instrukcji if? Moim zdaniem jest to bardzo przydatne, czasami lepiej podać pojedynczą zmienną, niż jakieś dłuższe wyrażenie logiczne.

0

Raczej na odwrót, jak jest jedynka, to true, 0 - false. Generalnie zasada działania pętli mówi, że ma się ona wykonywać tak długo, dopóki jest prawdziwa, albo (mówiąc dokładniej) jest wartością NIE ZEROWĄ. W powyższym przykładzie w warunku pętli jest po prostu 1, więc te pętla będzie trwać w nieskończoność, a jedyna rzecz, która może zakończyć jej działanie, to instrukcja break, którą masz w dwóch ifach. Jak w warunku pętli wpiszesz 0 (albo w wcześniejszej flagę domyślnie ustawisz na wartość większa lub równą 1), to pętla nie wykona się ani razu.

0

O to mi chodziło. Dzięki!

0
MasterBLB napisał(a):
  • z poprzedniej lekcji zapomniałaś, że są problemy z przesłaniem EOF do stdin z konsoli, i lepiej nie używać takiego warunku przerwania pętli.

control+d na linuxie, na windowsie control+z albo +c nie pamietam

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