Zlicz wystąpienia każdej cyfry - dlaczego 12 linijka działa?

0

Witam,
z pomocą książki Język C Briana Kernighan'a oraz Dennisa Ritchie napisałem poniższy program:

#include<stdio.h>
void main(void){
	int c, numWhite, numOther;
	int tab[10];

	for(int i = 0; i < 10; i++){
		tab[i] = 0;
	}

	while( (c = getchar()) != EOF){
		if( c >= '0' && c <='9'){
			tab[c-'0'] += 1;
		}
		else if ( c == ' ' || c == '\n' || c == '\t'){
			numWhite++;
		}
		else{
			numOther++;
		}
	}

	printf("cyfry = { ");
	for(int i = 0; i < 10; i++){
		printf("%d, ", tab[i]);
	}
	printf("}, białe znaki = %d, inne = %d\n", numWhite, numOther);
}

Problem pierwszy polega na tym, iż nie rozumiem dlaczego program działa tylko, gdy w 12. linijce jest tab[ c - '0' ]. Początkowo wydawało mi się, że wystarczy tab[c], jednak w książce jest tab[ c - '0' ] i faktycznie, tylko ta wersja działa. Nie mam pojęcia dlaczego. Czy ktoś mógłby przystępnie wytłumaczyć co robi ów - '0'?

Problem drugi znajduje się w linijce 11. - if( c >= '0' && c <='9'){ - dlaczego liczby muszą być ujęte w apostrofy, przecież zmienna c jest typu int?
Z góry dziękuję
title

1

Dobre pytanie.
Znak '0' to wartość int 0x30 (48) w kodzie ASCII.
Masz 10 miejsc na wartość w tablicy.
Gdy stosujesz tab[c] to wychodzisz poza tablicę.

Różne wersje zera:
0 = 0
'\0' = 0
"\0" = łańcuch zaczynający się od 0.
'0' = 48

0
vpiotr napisał(a):

Gdy stosujesz tab[c] to wychodzisz poza tablicę.

Czyli wychodzę poza tablicę ponieważ getchar() zwraca znak w systemie szesnastkowym? W takim razie czy apostrofy oznaczają użycie systemu szesnastkowego?

0
nv506 napisał(a):
vpiotr napisał(a):

Gdy stosujesz tab[c] to wychodzisz poza tablicę.

Czyli wychodzę poza tablicę ponieważ getchar() zwraca znak w systemie szesnastkowym? W takim razie czy apostrofy oznaczają użycie systemu szesnastkowego?

Apostrofy domyślnie oznaczają użycie kodu ASCII.
I getchar zwraca znak, nie cyfrę.

0
vpiotr napisał(a):
nv506 napisał(a):
vpiotr napisał(a):

Gdy stosujesz tab[c] to wychodzisz poza tablicę.

Czyli wychodzę poza tablicę ponieważ getchar() zwraca znak w systemie szesnastkowym? W takim razie czy apostrofy oznaczają użycie systemu szesnastkowego?

Apostrofy domyślnie oznaczają użycie kodu ASCII.
I getchar zwraca znak, nie cyfrę.

Czyli w tab[ c - 0 ], - 0 służy odjęciu znaku końca tekstu \0?

0

Odejmowanie tutaj służy głównie zaoszczędzeniu miejsca w tablicy.
Poprawna wersja bez odejmowania:

#include<stdio.h>
int main(void){
    int c;
    int numWhite = 0;
    int numOther = 0;
    int tab['9'+1];
 
    for(int i = '0'; i <= '9'; i++){
        tab[i] = 0;
    }
 
    while( (c = getchar()) != EOF){
        if( c >= '0' && c <='9'){
            tab[c] += 1;
        }
        else if ( c == ' ' || c == '\n' || c == '\t'){
            numWhite++;
        }
        else{
            numOther++;
        }
    }
 
    printf("cyfry = { ");
    for(int i = '0'; i <= '9'; i++){
        printf("%d, ", tab[i]);
    }
    printf("}, białe znaki = %d, inne = %d\n", numWhite, numOther);
    return 0;
}

https://ideone.com/PCDEJN

0

Szczerze dziękuję za chęć pomocy, jednak również szczerze pisząc... teraz już nie rozumiem dlaczego zera i dziewiątki są w apostrofach... i dlaczego int tab['9'+1];

0

int tab['9'+1] to deklaracja tablicy o rozmiarze który zapewni że wszystkie zliczane wartości się zmieszczą.
Zliczasz znaki od '0' do '9', indeks tablicy zaczyna się od 0, dlatego musisz mieć o 1 element więcej niż maksymalna zliczana wartość.

Czyli w tym wypadku przetwarzane są elementy tablicy:
tab['0'] = tab[48]
do
tab['9'] = tab[48+9] = tab[57]

'9' + 1 = 57 + 1 = 58

Zawsze gdy deklarujesz tablicę, musisz podać jej rozmiar jako "wartość maksymalna indeksu + 1".
Ale tylko w C i pokrewnych językach.
W Julii np. indeks tablicy zaczyna się od 1.

0

Ok, przeczytałem jeszcze raz, że getchar() zwraca znak, nie liczbę, więc wnioskuje że stąd te apostrofy, ale skoro nie operuję już na liczbach, tylko na znakach to dlaczego wciąż w użyciu jest typ int?

0
nv506 napisał(a):

Ok, przeczytałem jeszcze raz, że getchar() zwraca znak, nie liczbę, więc wnioskuje że stąd te apostrofy, ale skoro nie operuję już na liczbach, tylko na znakach to dlaczego wciąż w użyciu jest typ int?

Jak sprawdzisz EOF to możesz wyeliminować int.
EOF jest typu int, inne znaki ZTCW mieszczą się w typie char.
Trochę więcej:
http://www.tenouk.com/cpluscodesnippet/chardecimalhexoctal.html

0

Ok, dziękuję! :)

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