[WikiDyd] [TitleIndex] [WordIndex

Języki i metodyka programowania 1

Komentarze studentów

Tutaj każdy może napisać cokolwiek pod warunkiem, że jest związane z przedmiotem

Propozycje:

1. Podpowiedzi

2. Pytania

WPISY

Kiedy i gdzie można się do Pana zgłaszać po wpisy?

Wpisy tylko i wyłącznie w pokoju 226 w Gmachu Elektrotechniki.

MO1

Mówił Pan, by w funkcjach pisanych przez nas były obsługiwane błędy tzw. "niemożliwe". Mam pytanie odnośnie wielkości tablicy, którą dostaje funkcja. Łatwo jest zrobić obsługę błędu takiego, że funkcja dostała wielkość ujemną. Ale jak zrobić, by funkcja obsługiwała błąd w drugą stronę? Znaczy: jak można zgadnąć, czy funkcja nie dostała za dużej wielkości tablicy? Przykład błędnego wywołania funkcji dostającej tablicę (wektor):

{


  int tablica[10];


  /*tu tablica dostaje wartości*/


  wypisz(tablica, 20); // tu funkcja dostaje tablicę (tzn. wskaźnik na tablicę) i jej błędną wielkość.


}

Odpowiedź:

Mówiłem o zabezpieczeniu się przed sytuacją, w której program wykonuje operację, której nigdy wykonać nie powinien. Na przykład:

void costam( double v[], int n ) {


   int i;


   for( i= 0; i < n; i++ )


       v[i] = v[i] == 0 ? 0.0001 : v[i];


    /* ... */


    for( i= 0; i < n; i++ )


         costam /= v[i];   /* tutaj v[i] teoretycznie NIE MOZE BYC == 0,


                              ale ostrożny programista sprawdzi, czy na pewno nie jest */


    /* ... */


}

"jak można zgadnąć, czy funkcja nie dostała za dużej wielkości tablicy?"

Nie można zgadnąć. Nie zabezpieczy Pan funkcji przed takim błędem.

MO2

Czyli można uznać, że możliwość odnalezienia końca tablicy funkcja ma jedynie dla jednowymiarowej tablicy znaków (program rozpoznaje słowo/zdanie, ponieważ jest zakończone znakiem '\0'). Można z tego wywnioskować, że programiści, co zaprojektowali język C, nie wzięli pod uwagę takiego rozwiązania (jak dla typu char) dla innych typów zmiennych... Takie rozwiązanie zmniejszyłoby jedynie zakres wartości zmiennych (dla unsigned int od 0 do 65534 zamiast do 65535) i zwiększyło deklarowaną pamięć o jedną zmienną (będącą zakończeniem tablicy).

Odpowiedź:

Sądzę, że wzięli pod uwagę, ale uznali, że:

  1. nie ma wartości całkowitej, której można by użyć tak, jak '\0'
  2. gdy czyta Pan dane z pliku to tablicy, to i tak musi te dane policzyć, bo przecież używa Pan indeksu ostatniego elementu
  3. i tak, i tak musi Pan przeznaczyć dodatkową pamięć na informację o liczbie elementów. To, czy będzie to dodatkowa liczba n, czy specjalny znak na końcu tablicy, to żadna różnica, a osobne n jest: czytelniejsze, wygodniejsze i łatwiejsze do realizacji ze względu podanego w p. a.

UWAGA: proszę zapomnieć, że zakres unsigned to 0-65535, bo to nieprawda. Polecam http://en.wikipedia.org/wiki/Limits.h

MO3

" ...definiować zmienną przed wywołaniem funkcji for(;;){}. Dlaczego?..."

Odpowiedź:

Dlatego: t1.c:2: error: 'for' loop initial declaration used outside C99 mode

MO4

" Wydaje mi się, że napisanie

for (int i=0 ; i<jakastamwartosc ; i++){}

Odpowiedź:

W zasadzie tak, choć czasem przydałaby się Panu zmienna i po zakończeniu pętli. Ja pisząc w C++, Javie, C# deklaruję zazwyczaj i w części kontrolnej for, natomiast w C trzymam się standardu C90, bo nie mam wtedy problemów z kompatybilnością programów ze starymi kompilatorami, itp.

Podstawowa sprawa, to świadomie używać określonego języka.

MO5

Ja mam pytanie odnośnie wskaźnika do funkcji.

typedef double (*wfdd_t)(double);



struct para {


  wfdd_t f; /* double (*f) ( double ); */


  char * n;


};

To rozumiem, że mówi nam o tym, że funkcja f zwraca double i przyjmuje argumenty typu double.

Natomiast później widać

wfdd_t


wybierz_fun( char * fun_name )

Czy funkcja wybierz_fun zwraca double i przyjmuje argumenty typu char ? (Czy to zmienia typ argumentu wprowadzanego z double na char?)

MO6

Ja mam pytanie dlaczego w tym kodzie

typedef struct {


        int prog;


        char* nazwa;


        } roslina_t;



FILE *we = fopen( "dane2.txt" , "r");


    int l_elementow;


    int i,prog;


    char buf[100];



    if (fscanf ( we , "%d" , &l_elementow ) != 1 )


       return -1;



    roslina_t baza[l_elementow];



fscanf ( we , "%d %s" , &prog , &buf );


   baza[0].prog = prog;


   baza[0].nazwa = buf;


fscanf ( we , "%d %s" , &prog , &buf );

po wykonaniu drugiego fscanfa za baza[0].nazwa podstawia mi buf z drugiego fscanfa

odp:bo najpierw do baza[0].nazwa przypisujesz adres buf, a potem pod tym adresem funkcja fscanf coś zapisuje -- noril

3. Uwagi do prowadzących

Zawsze łatwiej mi analizować program i problemy, gdy widzę na bieżąco jego kod. Mógłby pan w czasie prezentacji pracować w dwóch oknach terminala, w jednym byśmy widzieli kod programu, a w drugim kompilować, i widzieć wyniki programu? Ewentualnie wywoływać nasz program w vi(:!./a.out). Pozdrawiam

- Czy materiały z wykładów są umieszczone pod svn? Jaki jest adres repozytorium?


2015-09-23 06:43