Stefan Sokołowski, Podstawy programowania
LABORATORIUM 13


Zadanie 0:

Funkcja może komunikować się z programem ją wywołującym przez Ale wynik może być tylko pojedynczą wartością. Co robić, jeśli skutkiem działania funkcji ma być obliczenie kilku rzeczy na raz? Do tego mogą służyć Funkcji można wskazać, gdzie ma zapisać wynik swojego działania. Na przykład:
  void divmod(int a, int b, int* q, int* r) {
    *q = a/b;  *r = a%b;
  }
Wywołanie tej funkcji powoduje zapisanie W programie głównym można użyć takiej funkcji na przykład tak:
  int  dzielna, dzielnik, iloraz, reszta;
  printf("\n  dzielna  == "); scanf("%i", &dzielna);
  printf("  dzielnik == "); scanf("%i", &dzielnik);

  divmod(dzielna, dzielnik, &iloraz, &reszta);

  printf("\n  WYNIK:  %i/%i ==  %i r %i\n\n",
         dzielna, dzielnik, iloraz, reszta
  );
Ogólnie -- operacje  *  i  &  są wzajemnie odwrotne: Proszę uruchomić program zasugerowany powyżej, stosujący funkcję  divmod .


Zadanie 1:

Proszę wykonać następujący program:
  int main() {
    int* x;  int* y;  int z=0;
    x = y = &z;
    printf("\n  *x == %i   *y == %i\n", *x, *y);
    *x = 1;
    printf("\n  *x == %i   *y == %i\n\n", *x, *y);
    return 0;
  }
i wyjaśnić (najlepiej na takich rysunkach jak powyżej) dlaczego zmiana wartości zmiennej  *x  spowodowała również zmianę wartości zmiennej  *y .


Zadanie 2:

Poniższy program
  int main() {
    double x;
    printf("\n  x == ");  scanf("%lf", x);
    printf("\n  %lf\n\n", x);
  }
generuje przy kompilacji takie ostrzeżenie:
  format '%lf' expects argument of type 'double *', but argument 2 has type 'double' [-Wformat=]
   printf("\n  x == ");  scanf("%lf", x);
                                ~~^
To jest oczywiście skutek opuszczenia znaku  &  przed  x  w instrukcji  scanf("%lf", x); .

Proszę wyjaśnić treść komunikatu tego ostrzeżenia. Czego kompilator oczekiwał i dlaczego? Czemu czepia się typów?


Zadanie 3:

Proszę zdefiniować funkcję  srednie  w taki sposób, żeby poniższy program obliczał jednocześnie średnią arytmetyczną i średnią geometryczną podanej tablicy:
  #include<stdio.h>
  #include<math.h>
...tu wpisać definicję funkcji  srednie ...
  int main() {
    int  n, i;
    printf("\nOBLICZANIE SREDNICH ARYTMETYCZNEJ I GEOMETRYCZNEJ");
    printf("\nIle elementow?  ");  scanf("%i", &n);
    double a[n], sr_a, sr_g;
    printf("Elementy tablicy:\n");
    for (i=0; i<n; i++)  scanf("%lf", &a[i]);

    srednie(n, a, &sr_a, &sr_g);

    printf("\n  srednia arytmetyczna == %lf", sr_a);
    printf("\n  srednia geometryczna == %lf\n\n", sr_g);
    return 0;
  }

Proszę niczego nie zmieniać w ciele funkcji  main .


Zadanie 4:

Proszę napisać funkcję do wczytywania liczb rzeczywistych. Powinna ona pytać, czy jest jeszcze coś do wczytania i wczytywac, następnie znowu pytać itd.; aż użytkownik odpowie, że nie, to już wszystko. Wtedy powinna programowi wywołującemu oddać informację, ile tych liczb było (można założyć, że nie więcej niż 10 000) oraz wszystkie wczytane liczby.

Co potem zrobi z nimi program główny, to już nie jest ważne i nie należy do tego zadania; np. niech je wszystkie wydrukuje. Istotne jest natomiast, jakie mają być typy parametrów funkcji wczytującej, gdzie są wskaźniki, itp.


Zadanie 5:

Ten program
  #include<stdio.h>

  int main() {
    int i;
    char  a[3], b[3], c[3];
    for (i=0; i<3; i++) {
      a[i] = 'A';  b[i] = 'B';  c[i] = 'C';
    }

    printf("\n  ");
    for (i= 0; i<3; i++)  printf("%c", a[i]);
    printf("\n  ");
    for (i=-1; i<4; i++)  printf("%c", b[i]);
    printf("\n  ");
    for (i= 0; i<3; i++)  printf("%c", c[i]);
    printf("\n\n");
  }
wypełnia a następnie drukuje zawartości tych tablic.

Oczywiście drukowanie tablicy  b  jest zorganizowane błędnie, bo sięga poza jej zadeklarowany zakres. Proszę
  1. sprawdzić, że ten błąd nie jest sygnalizowany w czasie kompilacji;
  2. wyjaśnić, dlaczego jego skutkiem jest wydrukowanie obcych liter  A  i  C .

Wskazówka:
Język C w znacznym stopniu utożsamia tablice i wskaźniki. Deklaracja postaci tablicy (T — jakiś typ, n — liczba naturalna) jest równoważna deklaracji wskaźnika na typ T i wpisania do niego ,,strzałki'' wskazującej na miejsce w pamięci, gdzie mogą być umieszczane elementy tablicy: Argumentem funkcji sizeof jest typ; a wynikiem — liczba bajtów pamięci na jedną wartość typu T. Argumentem funkcji malloc jest liczba naturalna; wynikiem — wskaźnik na wolny dotąd obszar pamięci długości (w bajtach) wskazanej przez argument; efektem ubocznym — zapamiętanie, że ten obszar jest już zajęty. Na przykład deklaracje oznaczają to samo i ich efekt w pamięci jest taki:


Wyjaśnienia można znaleźć w wielu miejscach, np.  tutaj . Ja rekomenduję stosowanie zawsze pierwszej formy, bo jest prostsza, jaśniejsza i w związku z tym mniej podatna na błędy.


Do mojej głównej witrynki

Ostatnia modyfikacja: 24 stycznia 2025