Operacje na tablicach

0

Cześć. Dzisiaj pisałem kolokwium, niestety nie zdałem bo program nie działa :) Większość funkcji działa tak jak powinna ale jednak coś jest nie tak. Polecenie:
Napisz program, który uzupełni tablicę liczbami całkowitymi z zakresu od -15 do 10. Rozmiar tablicy ma być wprowadzony przez użytkownika i nie może być mniejszy niż 15 i nie większy niż 25. Elementy tablicy mają być w ten sposób wyświetlone, że pierwsza połowa będzie zawierać liczby pseudolosowe zwiększone o wartość 5 i posortowane malejąco, zaś druga będzie zawierać elementy ciągu arytmetycznego. Pierwszy element ciągu arytmetycznego ma być losowany z zakresu od -15 do 10, a jego różnica ma być podawana przez użytkownika.

Funkcji sprawdzającej czy rozmiar jest dobry jeszcze nie napisałem bo chciałem sprawdzić czy wszystkie główne funkcje działają. Wszystkie działają oprócz sortowania pierwszej połowy tablicy (czasami działa, czasami nie) ale kiedy wprowadzam rozmiar tablicy większy niż 12 to wyświetla mi mniej elementów albo w ogóle ich nie wyświetla (Nie mam pojęcia dlaczego). Podpowiecie co robię źle? Dzięki :)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <math.h>
void uzupelnij_tablice (char *tab, int *rozmiar)
{
    srand(time(NULL));
    for(int i=0; i < *rozmiar; i++)
        tab[i]=-15 + rand()%26;
}
void wyswietl_tablice (char *tab, int *rozmiar)
{
    int i;
    for(i=0; i < *rozmiar; i++)
        printf("A[%d] = %d\n",i,tab[i]);
}
void swap (int *first, int *second)
{
    int schowek = *first;
    *first = *second;
    *second = schowek;
    return;
}
void pierwsza_polowa_plus_5 (char *tab, int *rozmiar)
{
    int srodek = *rozmiar/2;
    for(int i=0; i <= srodek-1; i++)
        tab[i]=tab[i]+5;
}
void sortuj_pierwsza_polowa (char *tab, int *rozmiar)
{
    for(int i=1;i<*rozmiar/2;i++)
    {
        int max=i-1;
        for(int j=i; j<*rozmiar/2 ; j++)
            if(tab[max]<tab[j])
                max=j;
        swap(&tab[i-1], &tab[max]);
    }
}
void arytmatyczny_druga_polowa(char *tab, int *rozmiar)
{
    srand(time(NULL));
    int i,r,a;
    a = -15+rand()%26;
    printf("Podaj roznice ciagu arytmetycznego = ");
    scanf("%d",&r);
    for(i=*rozmiar/2; i<=*rozmiar; i++)
    {
        a=a+r;
        tab[i]=a;
    }
}
int main()
{
    int size;
    char tablica[size];
    printf("Podaj rozmiar tablicy = ");
    scanf("%d",&size);
    uzupelnij_tablice(tablica,&size);
    printf("Wylosowana tablica :\n");
    wyswietl_tablice(tablica,&size);
    pierwsza_polowa_plus_5(tablica,&size);
    sortuj_pierwsza_polowa(tablica,&size);
    arytmatyczny_druga_polowa(tablica,&size);
    printf("tablica po zmianach :\n");
    wyswietl_tablice(tablica,&size);

    return 0;
}
2

nie mam czasu teraz(może później) ale:
to jest przy kompilacji

main.c: In function ‘sortuj_pierwsza_polowa’:
main.c14: warning: passing argument 1 of ‘swap’ from incompatible pointer type [-Wincompatible-pointer-types]
39 | swap(&tab[i-1], &tab[max]);
| ^~~~~~~~~
| |
| char *
main.c17: note: expected ‘int *’ but argument is of type ‘char *’
18 | void swap (int *first, int *second)
| ~~~~~^~~~~
main.c25: warning: passing argument 2 of ‘swap’ from incompatible pointer type [-Wincompatible-pointer-types]
39 | swap(&tab[i-1], &tab[max]);
| ^~~~~~~~~
| |
| char *
main.c29: note: expected ‘int *’ but argument is of type ‘char *’
18 | void swap (int *first, int *second)
| ~~~~~^~~~~~

    int size;
    char tablica[size];

zakładam że chciałeś mieć rozmiar tablicy w runtime, coś mnie przekonuje mnie to. No i te wysyłanie size za pomocą wskaźnika.

3

debuger w ręce i tyle, nikt tego nie zrobi za ciebie

Z pomniejszych: dlaczego argumenty rozmiar przez int *, jeśli to proste przekazanie liczby, bez jej zmiany?
Ja bym sortowanie zrobił jedno, i tylko "zasilał" funkcję sotrujacą wybranymi odcinkami tablicy. Akurat ta wada (błędogenny ficzer jezyka) C tu ma szansę być zastosowana pozytywnie.

czyli

void sortu_drugą_polowe(tab ... )
{
    sortuj_generyczne( tab + n/2, n/2 (plus minus jeden) )
}

W sortowaniu tablicę traktujesz od jedynki, w innym od zera. Nie wiem, słusznie czy nie - ja w tym nie umiem wyczytać, jaki wzorzec sortowania ma to robić.
Mając jedno SORTOWANIE, masz (w razie błędu) ten błąd wyrazistszy, wiesz co poprawiasz itd...

6
int main()
{
    int size;
    char tablica[size];

To jest UB jak nic! W końcu wartośći size nie jest zdefiniowana w momencie deklaracji tablicy VLA.

Na dodatek to warning wykrywa poważny błą ze wskaźnikami https://godbolt.org/z/7TPTG4Mnb :

<source>: In function 'sortuj_pierwsza_polowa':
<source>:42:14: error: passing argument 1 of 'swap' from incompatible pointer type [-Werror=incompatible-pointer-types]
   42 |         swap(&tab[i-1], &tab[max]);
      |              ^~~~~~~~~
      |              |
      |              char *
<source>:19:17: note: expected 'int *' but argument is of type 'char *'
   19 | void swap (int *first, int *second)
      |            ~~~~~^~~~~
<source>:42:25: error: passing argument 2 of 'swap' from incompatible pointer type [-Werror=incompatible-pointer-types]
   42 |         swap(&tab[i-1], &tab[max]);
      |                         ^~~~~~~~~
      |                         |
      |                         char *
<source>:19:29: note: expected 'int *' but argument is of type 'char *'
   19 | void swap (int *first, int *second)
1
    int size;
    char tablica[size];

To jest niepoprawne, wartość zmiennej size nie jest znana w momencie deklaracji tablicy.
Skoro size zgodnie z założeniami nie przekroczy 25, to po prostu stwórz tablicę 25-elementową i wykorzystuj tylko jej fragment.

Dlaczego zadeklarowałeś tablicę jako char skoro planujesz przechowywać w niej liczby ? Przy 25 elementach oszczędność pamięci jest pomijalnie mała, a niepotrzebnie zaciemniasz kod.

srand(time(NULL));

Tej konstrukcji używasz tylko raz na początku działania programu. Zanotuj sobie - raz, na początku funkcji main() i nigdy więcej. Jak zdobędziez troszkę doświadczenia to dowiesz się kiedy możesz chcieć użyć srand wielokrotnie.

A tak na koniec...

Jeśli tablica ma 15 elementów, to ile elementów ma jej pierwsza połowa ?

2

Po poprawkach z budowaniem jest buffer overflow: https://godbolt.org/z/nh9enbYEb
Bo warunek pętli jest zły.naprawionde na głupa.

2

Wszyscy już dużo popisali ale powiem Ci, jasne masz niby przedział mały ale jednak jak bym miał liczby całkowite do umieszczenia w tablicy, nawet małe
To bym zrobił
int tab[ xxx ];

W porywach int8_t

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