Zliczanie poszczególnych elementów łańcucha- niezrozumiały wynik

0

Dzień dobry,
Podczas dzisiejszej nauki napotkałem pewien kod którego działania nie mogę sobie uzmysłowić. Mamy pewną liczbę całkowitą zadeklarowaną:

int m=4; 

Oraz pewną tablicę wskaźników typu char:

 char *ciag="S1,Z4 grupy T1-T6, %s, %s.\n"; 

A pętla taka jak poniżej, zlicza liczbę liter, cyfer i wyrazów w tym łańcuchu:

while((c=*(ciag+++m))!='\0') 
         if(c>='0'&&c<='9')cyf++; 
         else if(c>='A'&&c<='Z'||c>'a'&&c<='z')lit++; 
              else ++poz; 

Po wywołaniu wyników funkcją printf():

 printf("Liczba: cyfr=%d, liter=%d, innych znakow=%d\n",cyf,lit,poz);

Otrzymuję całkowicie niezrozumiałe wyniki:

Liczba: cyfr=7, liter=13, innych znakow=15

Dlaczego te wyniki są tak dziwne? Mnie wydawało się, że liczymy od piątego znaku łańcucha do końca co daje inne wyniki. Nawet gdybyśmy liczyli od początku to tych poszczególnych znaków w metodzie ręcznej wychodzi mniej niż w wyniku programu. Algorytm jest napisany na 100% dobrze, bo to fragment kolokwium przykładowego, gdzie zdający ma być kompilatorem i dać wynik. Proszę bardzo o wytłumaczenie, ponieważ to częsty przykład u mojego wykładowcy!

0

Zapnij sie tam debugerem i klikaj sobie krok po kroku i będziesz widział kiedy co sie inkrementuje. Nikt tego za ciebie robić nie będzie.

6

Od kogo się tego uczysz? Porzuć to natychmiast.

To:

char *ciag="S1,Z4 grupy T1-T6, %s, %s.\n"; 

W C jest dopuszczalne ale to zła praktyka, w C++ to niepoprawny kod. Literał znakowy w C jest typu char [] a w C++ const char [], ale w obu języka nie wolno ich modyfikować. Dlatego zawsze należy używać const char *.

Ta pętla to koszmar. Jest nieczytelna i nie wiadomo co robi (być w może gdzieś są klawiatury z dodatkowo płatnym klawiszem spacji). Dodatkowo ktoś błędnie zakłada, że w systemie znaków implementacji, poszczególne znaki alfabetu będą obok siebie. To nie jest gwarantowane (jedynie cyfry muszą być kolejno obok siebie). Do klasyfikacji znaków są funkcje isalpha czy isdigit. Przepisz to sobie normalnie, dokładnie rozkładając to na fragmenty odpowiedzialne za poszczególne znaki. Na "optymalizacje" czas przyjdzie później (hint: usunięcie spacji nie przyśpiesza wykonywania kodu, a nazwy zmiennych mogą być dłuższe niż 3 znaki).

Pokaż cały kod, bo te wyniki są bez sensu. Nie wiadomo jakie są początkowe wartości tych liczników znaków. (Tutaj masz "intuicyjne" wyniki: http://ideone.com/PJE4Ag)

0

Cały kod:

#include <stdio.h>
#include <stdlib.h>                       /*funkcja atof()*/
#define PR(format,val) printf("{ "#val" } = { %"#format" }\n",(val))
#define A(x,y,z) -z*n+(m*y+x)+1
#define NL printf("\n");
void funD(int *tab)
{   int i=1, j=1;  
    char ciag[]={"FunD:\'%-3d\'< %2d< %-4d\\< %02d< \"%-3d\"\n"};
    i=(j=--tab[0])-1;
    ++tab[j++];
    tab[i++-1]=--j;
    printf(ciag,i+++1,j+++2,*(tab+2),*tab+4,--tab[3]);
}
void funP(char *wsk)
{   char c, liczba[20];
    static int k, m, n;
    float arr[8];
    if(k<3) 
        { while((c=wsk[n++])!=',')liczba[m++]=c;     
          liczba[m]='\0'; m=0;  arr[k]=atof(liczba);
          printf("FunP: arr[%02d]=%.4f\n",k+n,arr[k++]); 
        }
}
int main(void)
{   int cyf=4, lit=4, poz=4, m=4, n=1, tab[]={4,3,7,4,8,1,9,6,2};
    char *ciag="S1,Z4 grupy T1-T6, %s, %s.\n", c, s=4, r=0;
    char linia[]="-8.1,28279.4,5.3568e-3,-2.51,-614.54267,-3.2465e+5,4.546e-2,-691.65";
    printf(ciag,__DATE__,__TIME__);
    funP(linia+4*m-1); funP(linia+7*m); funP(linia+7*m);
    PR(6x,A(2-1,-1+7,-4*2)+3);
    PR(06o,6+A(3-1,4+1,1+2)/3);
    PR(-6d,2*A(2-1,3-2,4-3)*3);
    printf("%s%d%s%c,\n","ciag[",4*(m||n)+m,"]=",*(ciag+4*(m||n)+m));
    while(r<5) printf("%d, ",s*=++r); NL
    funD(tab+1);
    while((c=*(ciag+++m))!='\0') 
         if(c>='0'&&c<='9')cyf++; 
         else if(c>='A'&&c<='Z'||c>'a'&&c<='z')lit++; 
              else ++poz;
    printf("Liczba: cyfr=%d, liter=%d, innych znakow=%d\n",cyf,lit,poz);
    

    system("Pause");
} 
2

:-D

Co to za syf.

Masz takie zadanie, żeby to analizować a potem podać wyniki? Głupszego zadania dawno nie widziałem. Takie coś jest całkowicie nieprzydatne i szkoda na to czasu.

"Dziwne" wyniki z pierwszego posta wynikają z początkowych wartości zmiennych cyf, lit, poz, które są różne od 0. Zobacz link, który wkleiłem i zauważ, że "intuicyjne" wyniki są właśnie mniejsze o 4.

Tutaj masz rozpisane, wszystko się zgadza, pamiętaj, że '\n' to jeden znak:

S1,Z4 grupy T1-T6, %s, %s.\n
....^^^^^^^^^^^^^^^^^^^^^^^
....cilllllilcilciiiliiilii
cyfry  = 4 +  3 =  7
litery = 4 +  9 = 13
inne   = 4 + 11 = 15
0

Z debuggera wynika że zaczyna zliczanie od "4" i kończy na "" tylko dlaczego od 4 i dlaczego od bez "n"?

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