C, Pomoc przy zadaniu

Witam
Mam treść zadania która nakazuje pobrać n elementów od użytkownika i dodawać ją do tablicy dopóki użytkownik nie poda wartości ujemnej n. Mam problem ponieważ program działa na małych tablicach ale wysypuje się kiedy pojawiają się większe, dokładnie większe od 6.
Z góry dziękuje za pomoc.

#include <stdio.h>
#include <stdlib.h>
int *tab,*tab2,n,licznik=0;
void tworz_tab(n){
   tab = (int *) calloc(n,sizeof(int)); //daklaruje tablice
   tab2 = (int *) calloc(n,sizeof(int));
   while(n>=0){
       printf("Podaj liczbe calkowita  "); //dodaje elementy do tablicy do momentu dodania elementu ujemnego
       scanf("%d",&n);
       tab[licznik]=n;
       licznik++;
   }
   for (int i=0;i<licznik-1;i++){
       tab2[i]=tab[i]; //tworze tablice bez ostatniego elementu ujemnego tabliccy pierwszej
   }
}
void wypisz(){
   for (int i=0;i<licznik-1;i++){
       printf("%d ",tab2[i]);
   }
}
int main()
{
   tworz_tab(n);
   wypisz();
}

A gdzie ustalasz N? Po co Ci 2 tablice? Do czego używasz w końcu N? Do określenia długości tablicy, czy do wczytywania liczb? Co ma na celu przepisanie tablicy bez ostatniego elementu? Nie używaj zmiennych globalnych - to bardzo zła praktyka.

N pobiera liczby od użytkownika i dodaje je do tablicy, kopiowanie tablicy bez ostatniego elementu jest mi potrzebne bo np generuje mi tablice 3 4 5 8 -2 i nie może być tej -2 na końcu bo potem będę liczył z tego średnią

Jak na razie nigdzie nie pobierasz N czyli w ogóle nie rezerwujesz pamięci, jeśli coś zapamiętujesz to nadpisujesz pamięć która nie jest zarezerwowana do tego celu.

Nie musisz mieć 2 tablic, wystarczy że sprawdzisz czy podana wartość jest dodatnia, jeśli jest to ją dodajesz do tablicy, jeśli nie to przerywasz całą operację pobierania liczb. Wystarczy if w pętli pobierającej wartości oraz break do przerwania pętli.

Szczerze z tym N nie za bardzo ciebie rozumiem, mógłbyś to poprawić jeśli masz czas ?? :slight_smile:

Dobrze to inaczej, wskaż miejsce w którym użytkownik podaje długość tablicy czyli nasze N. Ja go nie widzę, czyli N wynosi 0 - czyli tworzysz tablicę 0 elementową czyli zajmujesz 0 bajtów pamięci. Wskaźnik wskazuje pewnie na 0 adres w pamięci i od niego zapisujesz dane naruszając pamięć - błąd naruszenia pamięci, segmentation fault czyli piszesz sobie po fragmencie pamięci który może być wykorzystywany do czegoś innego czyli możesz zmieniać sobie wartości zupełnie innych zmiennych niż chcesz.
W starszych systemach sytuacja mogłaby być jeszcze gorsza i mógłbyś pisać po obszarze pamięci z którego korzysta inny program, a nawet system tym sposobem możesz doprowadzić do uszkodzenia systemu.

Widzę, że problem podstawowy leży w zrozumieniu treści zadania. Tutaj (ogólnie w matematyce) “n” zazwyczaj symbolizuje bliżej nieokreśloną wartość całkowitą, a z dalszej treści zadania wynika, że właśnie tego “n” na początku działania programu nie znamy. To “n” poznamy dopiero podczas wprowadzania wartości przez użytkownika (wartość ujemna kończy wprowadzanie). Nigdy tego “n” bezpośrednio nie wczytujemy w programie!
A że potrzebujemy te wprowadzane wartości gdzieś trzymać, najprościej zadeklarować tablicę o odpowiednio dużym rozmiarze (nie jest to za eleganckie, ale patrząc na poziom pytającego, w zupełności wystarczy) i do niej wczytywać wartości.

PS. Kod programu zawiera przerost formy nad treścią (i jest mocno błędny) - sam algorytm dałoby się zapisać w kilku linijkach (poniżej początek - wczytywanie wartości):

const maxN = 1024;
tab = (int *) calloc(maxN,sizeof(int)); 
licznik=0;
do {
  scanf("%d",&n);
  tab[licznik++]=n;
} while (n>=0);

Racja chyba tak należy wykonać to zadanie. Zapomniałeś określić typ zmiennych jedynie.

Sami nieżyczliwi ludzie tutaj, łap gotowca:

#include <stdio.h>
int __[0xFFFF];main(_){scanf("%d",__+_)&&__[_]>-1?printf("%d ",__[_]),main(++_):0;}

Tu masz działający przykład: http://ideone.com/jA5Dy3

PS Wszystkie dodatnie liczby masz przechowywane w jedynej globalnej tablicy.

1 polubienie

Fajnie zaciemniłeś kod :D. Spoko pomysł.

1 polubienie

Dzięki za docenienie odrobiny sarkazmu. Bałem się już, że zadziała tu prawo Poego.

@bossunio
Tak na poważnie. Chyba porywasz się na za trudne zadanie dla siebie. Zacznij może od tego krótkiego kursu: https://pl.wikibooks.org/wiki/C bo ewidentnie nie masz pojęcia co robisz, oceniasz poprawność pisanego kodu “bo działa na 6 liczbach” (co w ogóle jeżeli mogę sobie pozwolić na dygresję jest czystym przypadkiem implementacji kompilatora którego używasz, większość zamiast poprawnego wskaźnika w taki sposób jak to robisz zwróciła by null i segmentation fault, a nie pozwoliła cokolwiek wprowadzić).

Naprawdę w internecie masz pełno kursów, a alokacja dynamiczna to nie jest chyba najlepszy starter.

Tutaj jest prostrza wersja, w Brainfucku:

,>+++++[<--------->-]<[>+++++[<+++++++++>-]<.,>+++++[<--------->-]<]

Jaki widać, kod jest znacząco którszy (prawie 2 razy), niż Twoja wersja w C, ponadto zaimplementowałem w kodzie obsługę liczb całkowitych dowolnej długości, czyli n.p. zadziała dla liczb większych niż 2^64.

1 polubienie