Program z Kolokwium

1

Cześć,
Mam kłopot ze zrozumieniem działania programu z przykładowego kolokwium jakie otrzymałem od prowadzącego przedmiot. Moje pytania brzmią następująco:

Dlaczego przy wywoływaniu fun1 wypisuje właśnie takie dane? Nie mogę zrozumieć co jest przypisywane poszczególnym zmiennym m oraz n i dlaczego przy pierwszym wywołaniu wyrażenie jest równe 0,05.

Dlaczego przy ostatnie iteracji while(r<7) printf("%d, ",s=(s+1)*r++); NL jest wypisane 116? Ogólnie wiem, że liczba wykracza poza zakres 255, ale nie jak policzyć ile akurat wyniesie.

Później przy wywoływaniu PR również nie bardzo wiem, dlaczego zostaje wypisywana 1 jako wynik z "%#format"

Nie bardzo też rozumiem co się dzieje po wywołaniu fun2. Gdy funkcji main jest napisane fun2(tab+3), no to do zmiennej globalnej zostaje przypisany 4 element tab, czyli 6. I jak rozpatruje co się dzieje w funkcji globalnej to "zapominam", na chwilę o mainie i patrzę na 6? Chodzi mi o to, czy jeśli w fun2 jest napisane np --tab[0] To jest to odniesienie do tego 1wszego elementu z tab(funkcji main), czyli liczbę 2?
Dopiero zaczynam przygodę z programowaniem, stąd też proszę o wyrozumiałość i przepraszam jesli coś jest nie zrozumałe. Dodam tylko, że ogólne zadanie polega na napisaniu, co wypisze poniższy program :)

 #include <stdio.h>
#include <stdlib.h>                       /*funkcja atof()*/
#define A(x,y,z) y*(n+1-m*z)+x
#define PR(format,val) printf("{ "#val" } = { %"#format" }\n",(val))
#define NL printf("\n");
//#define PRINT1(f,x1) PR(f,x1), printf("\n")
//#define PRINT2(f,x1,x2) PR(f,x1), PRINT1(f,x2)
//#define POB(i) lanc[i++]
void fun1(char *wsk)
{   unsigned 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("Fun%i: arr[%02d]=%.2f\n",k,k+n,arr[k-1]);
        }
}
void fun2(int *tab)
{   int i=2, j;
    unsigned char ciag[]={"Fun4:||%-3d> \"%-4d\"> %2d> \'%02d\'> %-3d>%%2d\n"};
    i=(j=--tab[0])-1;
    ++tab[--j];
    tab[i+++1]=++j;
    printf(ciag,*(tab+2),--tab[1],i+++1,*tab,j++-1);
}

int main(void)
{   int cyf=1, lit=1, poz=1, m=1, n=-1, tab[]={2,4,5,6,8,9,7,4,2};
    unsigned char *lanc="%s, %s=> PRM - 1st Check:-)\n", c, s=1, r=1;
    char linia[]="4.545e-2;614.54267;-691.65;2879.4;-8.1;-2.51;-3.2465e+4;5.35678e-3";
    printf(lanc,__DATE__,__TIME__);
    printf("%s%d%s%c;\n","lanc[",6*m+(m&&n),"]=",*(lanc+6*m+(m&&n)));
    fun1(linia+4*(m||n)); fun1(linia+4*(m||n)); fun1(linia+4*(m||n));
    while(r<7) printf("%d, ",s=(s+1)*r++); NL
	PR(-4x,A(5-2,-6+1,-3*2)*2);
    PR(04o,7+A(2-1,4+1,1+2)/4);
    PR(4d,2*A(3-1,3-1,4-2)+4);
    fun2(tab+3);
    while((c=*(lanc++-n))!='\0')
         if(c>='0'&&c<='9')cyf++;
         else if(c>='A'&&c<='Q'||c>='R'&&c<='Z')lit++;
              else ++poz;
    printf("Liczba: cyfr=%d, liter=%d, innych znakow=%d\n",cyf,lit,poz);
}
0

Zacznij tak, analizuj po kolej każdą z funkcji i refaktoryzuj kod, zmieniaj nazwy funkcji, zmiennych na zrozumiałe dla człowieka.

Nie ma innego wyjścia musisz podzielić na mniejsze elementy i jakoś określić ich zastosowanie.

Ewentualnie możesz skompilować i w disassemblerze to analizować ewnentualnie tam zdekompilować do C prawdopodobnie będzie czytelniejsze, bo kompilator zoptymalizuje trochę.
Lub w debbugerze patrz co się dzieje.

1

masz przykładowo 1 bajt = 0xff = 1111 1111 i jak dodasz +1 to otrzymasz 1 0000 0000, ale zmienna może mieć tylko 8 bitów, to zostanie 0000 0000 czyli 0x00 czyli 0.

3

W C musisz zapamiętać, że a[b] = *(a+b) = b[a].

Zmienne statyczne (static) inicjalizowane są wartością 0, stąd początkowa wartość m i n.

Podając do fun2 adres tab+3 (czyli &tab[3]), w tej funkcji masz wskaźnik na czwarty element tej tablicy, czyli 6. Wewnątrz funkcji fun2, tab odnosi się właśnie do tego adresu, więc tab[0] to 6 (przynajmniej na początku).

Ogółem postaraj się ten kod zrefaktoryzować aby otrzymać coś w miarę czytelnego.

A prowadzącemu możesz przekazać, że pisząc taki kod to nie utrzymałby (o ile by w ogóle otrzymał) pozycji juniorskiej w żadnej normalnej firmie, nie wspominając o takiej, gdzie dzieliłby się wiedzą z innymi.

1

Nie mogę zrozumieć co jest przypisywane poszczególnym zmiennym m oraz n i dlaczego przy pierwszym wywołaniu wyrażenie jest równe 0,05.

m i n mają przypisane wartości na początku funkcji main odpowiednio 1 i -1

Dlaczego przy wywoływaniu fun1 wypisuje właśnie takie dane?

Zauważ, że pierwsze wywołanie przekazuje fun1 przekazuje przesunięty wskaźnik na tabelę linia. Przesunięty o 4, czyli wskazuje na cyfrę 5 z tabli linia. Funkcja fun1 czyta po kolei znaki z tej tabeli aż napotka znak ";". Następnie wyświetla to co odczytał, a odczytał dokładnie to "5e-2" czyli 5 * 10^-2 czyli 0.05

Dlaczego przy ostatnie iteracji while(r<7) printf("%d, ",s=(s+1)r++); NL* jest wypisane 116? Ogólnie wiem, że liczba wykracza poza zakres 255, ale nie jak policzyć ile akurat wyniesie.

Masz tam przecież wyraźnie napisane, że pętla w kolejnych przejściach wykonuje operację s=(s+1)*r++. W poprzednim kroku s wynosiło 189. Czyli teraz masz```
(189+1)*6 = 1140


Ogólnie kod brzydko napisany, upierdliwy. Ale taki chyba był zamysł prowadzącego, żeby pobudzić Wasze szare komórki do myślenia i sprawdzić czy rozumiecie język c oraz czy potraficie po nitce do kłębka dojść do rozwiązania. W robocie programista nie przez jedno takie gówno będzie się przekopywał, więc możecie podziękować prowadzącemu, że po takim treningu nic nie będzie wam straszne.
0

Po wpisie @jarekr000000 przypomniało mi się, że fajne tricki w C kiedyś napisał @Gynvael Coldwind

Kruczki i sztuczki C cz. 1

Przyda ci się do łamania tego kodu.

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