Przekazywanie tablicy dynamicznej w funkcjach w C.

0

Wkleje kod i wytłumacze w czym rzecz, bedzie latwiej.

#include <stdio.h>
#include <stdlib.h>

void menu(void);
void wypelnij(int *wektor,int n);
void wyswietl(int *wektor,int n);

int main(int argc, char *argv[]) 
{
	int wybor,wybor2,n;
	int *wektor;
	
	menu();
	do {
		printf("\n\nWybor: ");
		scanf("%d",&wybor);
		switch(wybor)
		{
			case 1:
				{
					wypelnij(wektor,n);
                                        wyswietl(wektor,n); /* W TYM WIERSZU PROGRAM SIE SYPIE, przy wywoływaniu tej funkcji*/
				};break;
		}
	} while (wybor!=0);
	getche();		
	return 0;
}

void menu(void)
{	
	system("cls");
	printf("1. Zaalokuj pamiec na wektor.\n");
}

void wypelnij(int *wektor,int n)
{
	int i;
	
	system("cls");
	printf("Wprowadz rozmiar wektora: ");
	scanf("%d",&n);
	wektor=(int*)malloc(n*sizeof(int));
	if(wektor==NULL) 
		printf("Pamieci nie zaalokowano.\n");
	else 
		printf("\nWypelniam wektor elementami.\n");
	for(i=0;i<n;i++)
	{
		wektor[i]=rand()%10+1;
	}
        wyswietl(wektor,n); /* NATOMIAST JESLI UMIESZCZE WYWOLANIE FUNKCJI W TYM MIEJSCU, DZIALA POPRAWNIE.*/
	printf("\nENTER - dalej ...");
	getche();
	menu(); 
}

void wyswietl(int *wektor,int n)
{
	int i;
	
	system("cls");
	for(i=0;i<n;i++)
		printf("Element nr %d: %d\n",i+1,wektor[i]);
	getche();
} 

Umieściłem komentarze gdzie co jest nie tak.
Napisze jeszcze, ze przy wywolywaniu funkcji w programie głownym, program sie sypie. Nie wiem dlaczego, a jesli wywołam w funkcji, w ktorej ALOKUJE tablice, to wszystko pieknie działa.
Nie mam pojecia dlaczego tak, jakis przeciek pamieci?
Probowalem przekazywac przez zmienna/refrencje i nic z tego.
Prosze o wskazowke, uzasadnienie dlaczego tak sie dzieje.
Dziekuje, pozdrawiam.

0

Błąd klasyk. Funkcja wypelnij alokuje pamięć a po wyjściu z niej wskaźnik na ten obszar znika. Dlaczego? Bo przekazałeś int *wektor czyli wskaźnik na int. Jeżeli chcesz zmodyfikować wskaźnik (malloc zwraca nowy wskaźnik) a nie to, na co wskazuje, musisz użyć int **wektor czyli wskaźnik na wskaźnik na int. typedef Twoim przyjacielem. Poczytaj miliard podobnych tematów na tym forum.

0

Komentarze dalem co jest zle

#include <stdio.h>
#include <stdlib.h>
 
void menu(void);
void wypelnij(int *wektor,int n);
void wyswietl(int *wektor,int n);
 
int main(int argc, char *argv[]) 
{
        int wybor,wybor2,n; // n == ?
        int *wektor;
 
        menu();
        do {
                printf("\n\nWybor: ");
                scanf("%d",&wybor);
                switch(wybor)
                {
                        case 1:
                                {
                                        wypelnij(wektor,n);
                                        wyswietl(wektor,n); //w tym miejscu n == ??
                                };break;
                }
        } while (wybor!=0);
        getche();                
        return 0;
}
 
void menu(void)
{        
        system("cls");
        printf("1. Zaalokuj pamiec na wektor.\n");
}
 
void wypelnij(int *wektor,int n)
{
        int i;
 
        system("cls");
        printf("Wprowadz rozmiar wektora: ");
        scanf("%d",&n);
        wektor=(int*)malloc(n*sizeof(int)); // przy wyjsciu z funkcji tracisz dane
        if(wektor==NULL) 
                printf("Pamieci nie zaalokowano.\n");
        else 
                printf("\nWypelniam wektor elementami.\n");
        for(i=0;i<n;i++)
        {
                wektor[i]=rand()%10+1;
        }
        wyswietl(wektor,n);  // w tym miejscu n ma nadana wartosc
        printf("\nENTER - dalej ...");
        getche();
        menu(); 
}
 
void wyswietl(int *wektor,int n)
{
        int i;
 
        system("cls");
        for(i=0;i<n;i++)
                printf("Element nr %d: %d\n",i+1,wektor[i]);
        getche();
} 

Zamiast wskaznikow na wskazniki mozna zrobic cos takiego

int* wypelnij(int *wektor,int n)
{
        int i;
 
        system("cls");
        printf("Wprowadz rozmiar wektora: ");
        scanf("%d",&n);
        wektor=(int*)malloc(n*sizeof(int)); // przy wyjsciu z funkcji tracisz dane
        if(wektor==NULL) 
                printf("Pamieci nie zaalokowano.\n");
        else 
                printf("\nWypelniam wektor elementami.\n");
        for(i=0;i<n;i++)
        {
                wektor[i]=rand()%10+1;
        }
        wyswietl(wektor,n);  // w tym miejscu n ma nadana wartosc
        printf("\nENTER - dalej ...");
        getche();
        menu(); 
        return wektor;
}

w mainie zmienic wywolanie na cos takiego

wektor = wypelnij(wektor,n);

Natomiast zeby dzialala funkcja wyswietl trzeba w deklaracji funkcji dopisac int &n

Ps. No i wypadaloby zwolnic ta pamiec zaalokowana na stercie przez malloc

0

Déjà vu? Chyba Matrix się resetuje...

0

Należy w każdej deklaracji funkcji stworzyć dodatkowo wskaźnik na wektor i wywoływać funkcje wypelnij i wyswietl w sposob taki ?

wypelnij(&wektor,n);
wyswietl(&wektor,n);

Tylko pytanie jak sobie poradzić z tym :

wektor=(int*)malloc(n*sizeof(int));
....
	for(i=0;i<n;i++)
	{
		wektor[i]=rand()%10+1;
	}

Probowalem: wektor=(int)malloc(n*sizeof(int)); wektor[i]=rand()%10+1;
Oraz : (wektor)=(int)malloc(n
sizeof(int)); *(wektor[i])=rand()%10+1;

Program nie hula ;\

0

wystarczy zrobic tak

#include <stdio.h>
#include <stdlib.h>
 
void menu(void);
int* wypelnij(int *wektor,int &n);
void wyswietl(int *wektor,int n);
 
int main(int argc, char *argv[]) 
{
        int wybor,wybor2,n;
        int *wektor;
 
        menu();
        do {
                printf("\n\nWybor: ");
                scanf("%d",&wybor);
                switch(wybor)
                {
                        case 1:
                                {
                                        wektor = wypelnij(wektor,n);
                                        wyswietl(wektor,n); /* W TYM WIERSZU PROGRAM SIE SYPIE, przy wywoływaniu tej funkcji*/
                                };break;
                }
        } while (wybor!=0);
        getche();                
        return 0;
}
 
void menu(void)
{        
        system("cls");
        printf("1. Zaalokuj pamiec na wektor.\n");
}
 
int* wypelnij(int *wektor,int &n)
{
        int i;
 
        system("cls");
        printf("Wprowadz rozmiar wektora: ");
        scanf("%d",&n);
        wektor=(int*)malloc(n*sizeof(int));
        if(wektor==NULL) 
                printf("Pamieci nie zaalokowano.\n");
        else 
                printf("\nWypelniam wektor elementami.\n");
        for(i=0;i<n;i++)
        {
                wektor[i]=rand()%10+1;
        }
        wyswietl(wektor,n); /* NATOMIAST JESLI UMIESZCZE WYWOLANIE FUNKCJI W TYM MIEJSCU, DZIALA POPRAWNIE.*/
        printf("\nENTER - dalej ...");
        getche();
        menu(); 
        return wektor;
}
 
void wyswietl(int *wektor,int n)
{
        int i;
 
        system("cls");
        for(i=0;i<n;i++)
                printf("Element nr %d: %d\n",i+1,wektor[i]);
        getche();
} 
0

Wolalbym sie trzymac normalnego przekazywania parametrow. I zrobilem tak, tyle ze nie moge cos przekazac parametru N (ilosc).
Mam tak :

void wypelnij(int **wektor,int *n);
void wyswietl(int **wektor,int n);

/*WYWOŁANIA*/
wypelnij(&wektor,&n);
wyswietl(&wektor,n);

void wypelnij(int **wektor,int *n)
{
	int i;
	
	system("cls");
	printf("Wprowadz rozmiar wektora: ");
	scanf("%d",n);
	*wektor=(int*)malloc(*(n)*sizeof(int));
	if(wektor==NULL) 
		printf("Pamieci nie zaalokowano.\n");
	else 
		printf("\nWypelnij wektor elementami: \n");
	for(i=0;i<*n;i++)
	{
		scanf("%d",&wektor[i]);
	}
	printf("\nENTER - dalej ...");
	getche();
	menu(); 
}

void wyswietl(int **wektor,int n)
{
	int i;
	
	system("cls");
	for(i=0;i<n;i++)
		printf("Element nr %d: %d\n",i+1,wektor[i]);
	getche();
}
 

Nie przekazuje mi tego N, program dziala, ale zamiast N-elementow, moge wprwowadzic tylko np. 2. Albo 1.

0
Arn napisał(a):

Wolalbym sie trzymac normalnego przekazywania parametrow. I zrobilem tak, tyle ze nie moge cos przekazac parametru N (ilosc).

My za to wolelibyśmy żebyś trzymał się języka C (lub C++) oraz logiki.

Arn napisał(a):
void wypelnij(int **wektor,int *n);
void wyswietl(int **wektor,int n);

Po co do funkcji wyswietl() przekazujesz wskaźnik na wskaźnik? Uzasadnij.

Arn napisał(a):
/*WYWOŁANIA*/
wypelnij(&wektor,&n);
wyswietl(&wektor,n);

Co to jest? Co to ma robić?
Zmienne wektor oraz n w tym miejscu nie istnieją.

Arn napisał(a):
void wypelnij(int **wektor,int *n)
{
	int i;
	
	system("cls");
	printf("Wprowadz rozmiar wektora: ");
	scanf("%d",n);
	*wektor=(int*)malloc(*(n)*sizeof(int));

Co według Ciebie robi *(n)? Uzasadnij użycie.

Arn napisał(a):
	if(wektor==NULL) 
		printf("Pamieci nie zaalokowano.\n");
	else 
		printf("\nWypelnij wektor elementami: \n");
	for(i=0;i<*n;i++)
	{
		scanf("%d",&wektor[i]);
	}
	printf("\nENTER - dalej ...");

To miło, że sprawdzasz czy malloc() się udał, ale ten test nic Ci nie daje, gdyż niezależnie od tego czy się powiedzie, czy nie i tak próbujesz wypełniać zaalokowaną pamięć. To jest bez sensu i jeśli zaalokować pamięci się nie da, będziesz miał błąd.

Arn napisał(a):
void wyswietl(int **wektor,int n)
{
	int i;
	
	system("cls");
	for(i=0;i<n;i++)
		printf("Element nr %d: %d\n",i+1,wektor[i]);
	getche();
}
 

Do funkcji przekazujesz wskaźnik na wskaźnik. W funkcji odczytujesz ze wskaźnika. Widzisz problem?

Arn napisał(a):

Nie przekazuje mi tego N, program dziala, ale zamiast N-elementow, moge wprwowadzic tylko np. 2. Albo 1.

Popraw fundamentalne błędy.

0

Poprawiłem, ale co z tego jeśli mi to nie działa. 100 wskazówek już było, każda inna, a i tak nic z tego. Już się połapać ciężko. Brakowało mi tylko dobrego przekazania parametru n. No ale dobra, zastosowałem się do Twoich rad i przy wywoływaniu **wyświetl ** program się sypie.

 #include <stdio.h>
#include <stdlib.h>
/*----------------------------------------------------------------------------*/
void menu(void);
void wypelnij(int **wektor,int *n);
void wyswietl(int *wektor,int n);
/*----------------------------------------------------------------------------*/
int main(int argc, char *argv[]) 
{
	int wybor,wybor2,n;
	int *wektor;
	
	menu();
	do {
		printf("\n\nWybor: ");
		scanf("%d",&wybor);
		switch(wybor)
		{
			case 1:
				{
					wypelnij(&wektor,&n);
					wyswietl(wektor,n);	
				};break;
			case 2:
				{
				
				};break;
		}
	} while (wybor!=0);
	printf("\nZapraszam ponownie.");
	getche();		
	return 0;
}
/*----------------------------------------------------------------------------*/
void menu(void)
{	
	system("cls");
	printf("1. Zaalokuj pamiec na wektor.\n");
}
/*----------------------------------------------------------------------------*/
void wypelnij(int **wektor,int *n)
{
	int i;
	
	system("cls");
	printf("Wprowadz rozmiar wektora: ");
	scanf("%d",n);
	*wektor=(int*)malloc(*n*sizeof(int)); /* *n jest wskaznikiem na n, inaczej program sie nie kompiluje.*/
	if(wektor==NULL) 
		printf("Pamieci nie zaalokowano.\n");
	else
	{
		printf("\nWypelnij wektor elementami: \n");
		for(i=0;i<*n;i++) /*tu tak samo*/
		{
			scanf("%d",&wektor[i]);
		}
	}
	printf("\nENTER - dalej ...");
	getche();
	menu(); 
}
/*----------------------------------------------------------------------------*/
void wyswietl(int *wektor,int n)
{
	int i;
	
	system("cls");
	for(i=0;i<n;i++)
		printf("Element nr %d: %d\n",i+1,wektor[i]);
	printf("\nENTER - dalej ...");
	getche();
	menu();
}
/*----------------------------------------------------------------------------*/
0

masz działającą wersje.
Funkcja wypełnij musi przyjąć wskaźnik na wskaźnik do inta. Innymi słowy musi przyjąć wskaźnik na tablice intów, żeby pod ten wskaźnik móc wpisać to co zwróci malloc.
Jedną z niefajnych rzeczy w C jest brak referencji, który przekłada się potem na gwiazgkologie.

twój problem nie jest w funkcji wyświetl tylko w:

 
 printf("\nWypelnij wektor elementami: \n");
                for(i=0;i<*n;i++) /*tu tak samo*/
                {
                        scanf("%d",&wektor[i]);
                }

&wektor[i] oznacza że wyciągasz wskaźnik z tego co zwrócił ci malloc, czyli adres wskaźnika który wysłałeś do funkcji, a potem po nim iterujesz w góre, czyli iterujesz w górę po stosie, a nie po tej tablicy na stercie.

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
/*----------------------------------------------------------------------------*/
void menu(void);
void wypelnij(int **wektor,int *n);
void wyswietl(int *wektor,int n);
/*----------------------------------------------------------------------------*/
int main(int argc, char *argv[]) 
{
        int wybor,wybor2,n;
        int* wektor;
 
        menu();
        do {
                printf("\nWybor: ");
                scanf("%d",&wybor);
                switch(wybor)
                {
                        case 1:
                                {
                                        wypelnij(&wektor,&n);
                                        wyswietl(wektor,n);        
                                };break;
                        case 2:
                                {
 
                                };break;
                }
        } while (wybor!=0);
        printf("\nZapraszam ponownie.");
        getch();                
        return 0;
}
/*----------------------------------------------------------------------------*/
void menu(void)
{        
        system("cls");
        printf("1. Zaalokuj pamiec na wektor.\n");
        printf("0. koniec programu.\n");
}
/*----------------------------------------------------------------------------*/
void wypelnij(int **wektor,int *n)
{
        int i;
 
        system("cls");
        printf("Wprowadz rozmiar wektora: ");
        scanf("%d",n);
        *wektor = (int*) malloc ((*n)*sizeof(int));
        if(wektor == NULL) 
        {
                printf("Pamieci nie zaalokowano.\n");
                exit(1);
        }                
        else
        {
                printf("\nWypelnij wektor elementami: \n");
                for(i=0;i <(*n); i++)
                {
                      scanf("%d", &((*wektor)[i]));
                }

        }
        printf("\nENTER - dalej ...");
        getche();
        menu(); 
}
/*----------------------------------------------------------------------------*/
void wyswietl(int* wektor,int n)
{
        int i;
 
        system("cls");
        for(i=0; i<n; i++)
                printf("Element nr %d: %d\n",i+1,wektor[i]);
        printf("\nENTER - dalej ...");
        getche();
        menu();
}
/*----------------------------------------------------------------------------*/

 
0

Dzięki Ci wielkie, ciężkie te gwiazdki, oj ciężkie.

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