Wątek przeniesiony 2017-12-27 17:15 z C/C++ przez kq.

Tablice jednowymiarowe, wielowymiarowe oraz dynamiczna alokacja pamięci

0

Witam wszystkich, proszę o pomoc w napisaniu dwóch programów o danych poleceniach:

  1. Napisać funkcję read1D wczytującą tablicę liczb typu double i funkcję oblicz1 obliczającą dla tablicy sumę liczb dodatnich, ilość zer oraz częstość wystąpień zadanej wartości (przekazanej jako argument). W funkcji main() alokować tablicę dynamiczną o rozmiarze N=5 i wywołać dla tej tablicy obie funkcje i wydrukować wyniki.

  2. Napisać funkcję read2D wczytującą tablicę dwuwymiarową liczb typu int w stylu C99 i funkcję computeSRC obliczającą w tablicy sumę elementów wybranego wiersza i sumę elementów wybranej kolumny i zwracającą obliczone wartości przy tablicy dwuelementowej. Funkcję wywołać w funkcji main() dla tablic x[2][2] i y[3][3].

0

Zdecyduj się jaki język. Zakładam, że C, ale nie podałeś.

Pokaż co już masz.

0

Tak, chodzi o C. Pierwsze zadanie mam praktycznie gotowe, z drugiego nie mam jeszcze nic.

0

To jest moje rozwiązanie zadania nr 1.

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

int main()
{

    int wartosc;
    int i;
    int n=5;
    int *tab[n];


    for(i=0;i<n;i++)    // dynamiczna alokacja pamieci
        tab[i]=calloc(n,sizeof(int));

  //  int tab[n];

    read1D(tab,n);

    for(i=0;i<n;i++)
        printf("\n Element tablicy nr %d wynosi: %d",i,tab[i]);

    int sumaDodatnich;
    sumaDodatnich=oblicz1(tab,n);
    printf("\n Suma elementow dodatnich wynosi: %d",sumaDodatnich);

    int iloscZerowych;
    iloscZerowych=oblicz2(tab,n);
    printf("\n Ilosc elementow zerowych wynosi: %d", iloscZerowych);

    printf("\n Podaj zadana wartosc: ");
    scanf("%d", &wartosc);

    int iloscWystapien;
    iloscWystapien=oblicz3(tab,n,wartosc);
    printf("\n Ilosc liczb rownych zadanej wartosci wynosi: %d", iloscWystapien);

    return 0;
}

void read1D(int tab[], int n)
{
    int i;
    for(i=0;i<n;i++)
    {
        printf("\n Podaj element tablicy nr %d:",i);
        scanf("%d", &tab[i]);
    }
}

int oblicz1(int tab[],int n)    //funkcja liczy sumę elem. dodatnich

{
    int sumaD=0;
    int iloscParz=0;
    int i;
    for(i=0;i<n;i++)
    {
        if(tab[i]>0) sumaD=sumaD+tab[i];
    }

    return sumaD;
}
int oblicz2(int tab[],int n)    // funkcja liczy ilosc zer
{
    int iloscZer=0;
    int i;
    for(i=0;i<n;i++)
    {
        if(tab[i]==0) iloscZer=iloscZer+1;
    }
    return iloscZer;
}
int oblicz3(int tab[],int n,int x)  //funkcja liczy ilosc wystapien zadanej wartosci
{
    int i;
    int iloscWyst=0;
    for(i=0;i<n;i++)
    {
        if(tab[i]==x) iloscWyst=iloscWyst+1;
    }
    return iloscWyst;
}

Proszę o pomoc w zapisaniu tych trzech funkcji w jednej.

1

To się kompiluje? Najpierw musiałbyś mieć prototypy funkcji przed main aby je wywoływać:

void read1D(int tab[], int n);
int oblicz1(int tab[],int n);
int oblicz... // I tak dalej

int main()
{

}

// A tu definicje funkcji, tak jak teraz masz

To:

int *tab[n];

jest tablica wskaźników typu int. Tobie chodzi o tablicę int.

Jeżeli chodzi o stworzenie tablicy na podstawie zmiennej to wystarczy:

int tab[n];

To wszystko, tablica o rozmiarze n utworzona! Żadnych malloców/calloców.

Możesz również użyć operatorów przypisania takich jak +=, -=, *= itd., dzięki temu zamiast pisać:

zmienna = zmienna + inna_zmienna;

wystarczy

zmienna += inna_zmienna;

Co jest bardziej naturalne i przejrzyste.

Tak samo z inkrementacją, zamiast:

iloscZer = iloscZer + 1;

lepiej użyć

iloscZer++;

Co do nazewnictwa funkcji - piszesz komentarz co funkcja robi, ale dlaczego nie możesz nazwać funkcji tak, aby użycie komentarza było zbędne? Przecież oblicz1 może się nazywać sum, oblicz2 - count_zeroes, oblicz3 - count.

Dlaczego chcesz zapisać te 3 funkcje w jednej? W jakimś zadaniu jest to napisane czy jak? Bo nie ma zbytnio sensu tego robić.

0

Z tym calloc to chodzi mi o dynamiczną alokacje pamięci. A co do tych trzech funkcji, które chcę zapisać w jednej to dlatego, że to pierwsze polecenie tak sugeruje.

0

Tak, ale ty robiłeś coś kompletnie innego mianowicie tworzyłeś tablicę wskaźników które wskazywały na obszary n intów. To ma być tablica 2D czy 1D? Bo dla 1D, tak jak mówię, wystarczy Ci:

int tab[n];

No chyba że musisz użyć calloc, wtedy:

int *tab = calloc(n, sizeof(int));

Edit: Co do funkcji - możesz użyć struktury typu:

struct stats
{
   int sum;
   int zeroes;
   int count;
}

I zwracać ją po obliczeniu tych 3 rzeczy.

0

Czyli ta pętle zmieniam tak i jest ok?

 for(i=0;i<n;i++)    // dynamiczna alokacja pamieci
        int *tab = calloc(n, sizeof(int));
0

Ale to ma być tablica jednowymiarowa czy dwu?

0

jednowymiarowa

0

To wystarczy Ci tyle:

int* tab = calloc(n, sizeof(int));

Żadnej pętli. Z funkcji calloc zostaje zwrócony wskaźnik na 1 element tablicy jeżeli udało się przydzielić pamięć, w przeciwnym razie zwraca NULL.

0

Ok dobra dzięki. To zadanie nr 1 z głowy. Z drugiego mam tyle:

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

void wczyt2D(int x, int y, int tab[x][y]);

int main()
{
int x,y;
printf("\n Podaj ilosc wielrszy [x][] tablicy:");
scanf("%d", &x);
printf("\n Podaj ilosc kolumn [][y] tablicy:");
scanf("%d", &y);

int tab[x][y];
wczyt2D(x,y,tab);

int w,k;
printf("\n Podaj numer wiersza:");
scanf("%d", &w);
printf("\n Podaj numer wybranej kolumny:");
scanf("%d", &k);

    return 0;
}

void wczyt2D(int x, int y, int tab[x][y])
{
    int i;
    int j;
    for(i=0;i<x;i++)
    {
        for(j=0;j<y;j++)
        {
            printf("\n Podaj element tablicy nr [%d][%d]:",i,j);
            scanf("%d", &tab[i][j]);
        }
    }
}

int computeSRC(int x,int y,int tab[x][y],int w, int k)
{
    int i,j;
    for(i=0;i<x;i++)
    {
        for(j=0;j<y;j++)
        {

        }
    }
}
0

Skoro zadanie 2 mówi o stylu C99 to zamiast

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

Możesz użyć

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

Skoro masz obliczyć sumę danych z wiersza w to wystarczy 1 pętla od 0 do x, bo kolumna będzie miała indeks 0. Tak samo dla sumy z kolumny k, wtedy wiersz będzie miał indeks 0.

0

Coś nie tak...

int computeSRC(int x,int y,int tab[x][y],int w, int k)
{
    int i,j;
    int sumaElWiersza=0;
    for(i=0;i<x;i++)
    {
       if(w==x) sumaElWiersza+=tab[i][0];
    }
    return sumaElWiersza;
}
0

Bo to powinno być coś takiego:

int row_sum = 0;
for(int i = 0; i < y; i++) // Od 0 do maksymalnego indeksu kolumny
{
	row_sum += tab[w][i]; // Wybrany rząd i kolumna od 0 do y - 1.
}
0

To nie działa poprawnie. Wyrażenie w pętli jest trochę chyba bez sensu, ponieważ nie zawiera "i"

0

Dobra super, chodzi jak trzeba. Wyjaśniłbyś mi jeszcze dokładniej jak te dwie funkcje, które zastosowałem ująć w jednej, za pomocą struktury, o której była wcześniej mowa?

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

void wczyt2D(int x, int y, int tab[x][y]);

int main()
{
int x,y;
printf("\n Podaj ilosc wielrszy [x][] tablicy:");
scanf("%d", &x);
printf("\n Podaj ilosc kolumn [][y] tablicy:");
scanf("%d", &y);

int tab[x][y];
wczyt2D(x,y,tab);

int w,k;
printf("\n Podaj numer wiersza:");
scanf("%d", &w);
printf("\n Podaj numer wybranej kolumny:");
scanf("%d", &k);

int sumaW;
sumaW=computeSRC(x,y,tab,w,k);
printf("\n Suma elementow wiersza wynosi: %d", sumaW);
int sumaK;
sumaK=computeSRC2(x,y,tab,w,k);
printf("\n Suma elementow kolumny wynosi: %d", sumaK);

    return 0;
}

void wczyt2D(int x, int y, int tab[x][y])
{
    int i;
    int j;
    for(i=0;i<x;i++)
    {
        for(j=0;j<y;j++)
        {
            printf("\n Podaj element tablicy nr [%d][%d]:",i,j);
            scanf("%d", &tab[i][j]);
        }
    }
}

int computeSRC(int x,int y,int tab[x][y],int w, int k)
{
    int i;
    int row_sum = 0;
for(i=0;i<y;i++)     // Od 0 do maksymalnego indeksu kolumny
{
    row_sum += tab[w][i]; // Wybrany rząd i kolumna od 0 do y - 1.
}
return row_sum;
}

int computeSRC2(int x,int y,int tab[x][y],int w, int k)
{
    int i;
    int row_sum = 0;
for(i=0;i<x;i++)     // Od 0 do maksymalnego indeksu wiersza
{
    row_sum += tab[i][k]; // Wybrany rząd i kolumna od 0 do y - 1.
}
return row_sum;
}
1

Akurat w drugim zadaniu jest napisane aby wynik zwrócić za pomocą tablicy dwuelementowej. Połącz te funkcje w jedną:

int row_sum = 0;
for (int i = 0; i < y; i++) { ... } // Obliczanie row_sum

int column_sum = 0;
for (int i = 0; i < x; i++) { ... } // Obliczanie column_sum 

Problem z zwracaniem tablicy jest taki że gdybyś zrobił

int* foo()
{
	int some_array[10] = { 0 };
 	return some_array;
} 

to some_array przestaje istnieć po wywołaniu funkcji, w rezultacie obszar pamięci na który wskazuje wskaźnik będzie mógł przyjąć nieoczekiwane wartości.

Rozwiązania tego problemu są 2:

  1. Przydzielasz dynamicznie pamięć w funkcji (nazwijmy ją X) i zwracasz wskaźnik. Wtedy funkcja główna (lub ta, wywołująca funkcję X) musi zwolnić pamięć.
  2. Dostajesz wskaźnik do bufora i korzystasz z niego, wtedy nie musisz zwracać żadnego wskaźnika.

Zadanie jednak mówi o zwracaniu tablicy więc musimy użyć 1 rozwiązania. Więc poniżej prosty przykład:

int* foo(void) // Funkcja zwracająca wskaźnik na 1 element tablicy którą utworzy
{
	int *arr = malloc(sizeof(int) * 2); // Tworzymy wskaźnik na tablicę 2 elementową
	return arr; // Zwracamy wskaźnik
}
int main()
{
	int* numbers; // Wskaźnik na int, niezdefiniowany.
	numbers = foo(); // Wskaźnik będzie wskazywał na to, co zwróci funkcja foo() a więc tablicę.

	// Tu operujesz na tablicy numbers, np. za pomocą pętli for
	for (int i = 0; i < 2; i++)
	{
		// Zrób coś z numbers[i].
	}

	free(numbers); // Zwolnienie używanego obszaru pamięci.
}
0

No to się pokomplikowało :/ Poprawiłbyś ten program tak żeby był w całości gotowy? Będzie mi to prościej załapać...

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

void wczyt2D(int x, int y, int tab[x][y]);



int* foo(void) // Funkcja zwracająca wskaźnik na 1 element tablicy którą utworzy
{
    int *arr = malloc(sizeof(int) * 2); // Tworzymy wskaźnik na tablicę 2 elementową
    return arr; // Zwracamy wskaźnik
}


int main()
{
int x,y;
printf("\n Podaj ilosc wierszy [x][] tablicy:");
scanf("%d", &x);
printf("\n Podaj ilosc kolumn [][y] tablicy:");
scanf("%d", &y);

int tab[x][y];
wczyt2D(x,y,tab);

int w,k;
printf("\n Podaj numer wiersza:");
scanf("%d", &w);
printf("\n Podaj numer wybranej kolumny:");
scanf("%d", &k);

int sumaW;
sumaW=computeSRC(x,y,tab,w,k);
printf("\n Suma elementow wiersza wynosi: %d", sumaW);
int sumaK;
sumaK=computeSRC2(x,y,tab,w,k);
printf("\n Suma elementow kolumny wynosi: %d", sumaK);



int* numbers; // Wskaźnik na int, niezdefiniowany.
    numbers = foo(); // Wskaźnik będzie wskazywał na to, co zwróci funkcja foo() a więc tablicę.

    // Tu operujesz na tablicy numbers, np. za pomocą pętli for
    int i;
    for (i= 0; i < 2; i++)
    {
        // Zrób coś z numbers[i].
    }

    free(numbers); // Zwolnienie używanego obszaru pamięci.




    return 0;
}

void wczyt2D(int x, int y, int tab[x][y])
{
    int i;
    int j;
    for(i=0;i<x;i++)
    {
        for(j=0;j<y;j++)
        {
            printf("\n Podaj element tablicy nr [%d][%d]:",i,j);
            scanf("%d", &tab[i][j]);
        }
    }
}

int computeSRC(int x,int y,int tab[x][y],int w, int k)
{
    int i;
    int row_sum = 0;
for(i=0;i<y;i++)     // Od 0 do maksymalnego indeksu kolumny
{
    row_sum += tab[w][i]; // Wybrany rząd i kolumna od 0 do y - 1.
}
return row_sum;
}

int computeSRC2(int x,int y,int tab[x][y],int w, int k)
{
    int i;
    int row_sum = 0;
for(i=0;i<x;i++)     // Od 0 do maksymalnego indeksu wiersza
{
    row_sum += tab[i][k]; // Wybrany rząd i kolumna od 0 do y - 1.
}
return row_sum;
}
0

Ta funkcja foo() to był tylko przykład.
Powinieneś mieć funkcję computeSRC() jak poniżej:

int* computeSRC(int x, int y, int tab[x][y], int w, int k)
{
	int *sums = malloc(sizeof(int) * 2);
	sums[0] = sums[1] = 0;
	// Albo lepiej z inicjalizacją 2 elementów do 0:
	int *sums = calloc(n, sizeof(int)); 
	
	// Oblicz sumę wierszu w
	for(...)
	{
		sums[0] += tab[w][i];
	}
	
	// Oblicz sumę kolumny k
	for(...)
	{
		sums[1] += tab[i][k];
	}

	// Zwróć wskaźnik
	return sums;
}
0

Czego tu jeszcze brakuje?

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

void wczyt2D(int x, int y, int tab[x][y]);
computeSRC(int x, int y, int tab[x][y], int w, int k);





int main()
{
int x,y;
printf("\n Podaj ilosc wierszy [x][] tablicy:");
scanf("%d", &x);
printf("\n Podaj ilosc kolumn [][y] tablicy:");
scanf("%d", &y);

int tab[x][y];
wczyt2D(x,y,tab);

int w,k;
printf("\n Podaj numer wiersza:");
scanf("%d", &w);
printf("\n Podaj numer wybranej kolumny:");
scanf("%d", &k);

int sumaW;
sumaW=computeSRC(x,y,tab,w,k);
printf("\n Suma elementow wiersza wynosi: %d", sumaW);
int sumaK;
sumaK=computeSRC(x,y,tab,w,k);
printf("\n Suma elementow kolumny wynosi: %d", sumaK);




    return 0;
}

void wczyt2D(int x, int y, int tab[x][y])
{
    int i;
    int j;
    for(i=0;i<x;i++)
    {
        for(j=0;j<y;j++)
        {
            printf("\n Podaj element tablicy nr [%d][%d]:",i,j);
            scanf("%d", &tab[i][j]);
        }
    }
}
int* computeSRC(int x, int y, int tab[x][y], int w, int k)
{
    int *sums = malloc(sizeof(int) * 2);
    sums[0] = sums[1] = 0;
    // Albo lepiej z inicjalizacją 2 elementów do 0:
    int *sums = calloc(n, sizeof(int));

    // Oblicz sumę wierszu w
    for(i=0;i<y;i++)
    {
        sums[0] += tab[w][i];
    }

    // Oblicz sumę kolumny k
    for(i=0;i<x;i++)
    {
        sums[1] += tab[i][k];
    }

    // Zwróć wskaźnik
    return sums;
}
0

A IDE nie masz?

  • W prototypie funkcji computeSRC() nie jest napisane jaki jest typ zwracanych danych.
  • Niezdefiniowane n w calloc(), mój błąd, tam powinno być 2
  • Niezdefiniowane i w pętlach.
0
int* computeSRC(int x, int y, int tab[x][y], int w, int k)

conflicting types for 'computeSRC'

0

Twój kod powinien wyglądać tak (pomijam ciała funkcji):

void wczyt2D(int x, int y, int tab[x][y]);
int *computeSRC(int x, int y, int tab[x][y], int w, int k);

int main()
{
    ..
}

void wczyt2D(int x, int y, int tab[x][y])
{
    ...
}

int *computeSRC(int x, int y, int tab[x][y], int w, int k)
{
    ...
}

Poza tym to:

int sumaW;
sumaW = computeSRC(x, y, tab, w, k);

jest złe, dlatego że computeSRC zwraca wskaźnik typu int, nie int.

Zobacz ponownie mój przykład.

0

Nie przechodzi mi int *numbers w main()

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

void wczyt2D(int x, int y, int tab[x][y]);
int *computeSRC(int x, int y, int tab[x][y], int w, int k);





int main()
{
int x,y;
printf("\n Podaj ilosc wierszy [x][] tablicy:");
scanf("%d", &x);
printf("\n Podaj ilosc kolumn [][y] tablicy:");
scanf("%d", &y);

int tab[x][y];
wczyt2D(x,y,tab);

int w,k;
printf("\n Podaj numer wiersza:");
scanf("%d", &w);
printf("\n Podaj numer wybranej kolumny:");
scanf("%d", &k);

//int sumaW;
//sumaW=computeSRC(x,y,tab,w,k);
//printf("\n Suma elementow wiersza wynosi: %d", sumaW);
//int sumaK;
//sumaK=computeSRC(x,y,tab,w,k);
//printf("\n Suma elementow kolumny wynosi: %d", sumaK);


int *numbers;
numbers = computeSRC(int x, int y, int tab[x][y], int w, int k);



    return 0;
}

void wczyt2D(int x, int y, int tab[x][y])
{
    int i;
    int j;
    for(i=0;i<x;i++)
    {
        for(j=0;j<y;j++)
        {
            printf("\n Podaj element tablicy nr [%d][%d]:",i,j);
            scanf("%d", &tab[i][j]);
        }
    }
}
int *computeSRC(int x, int y, int tab[x][y], int w, int k)
{
    int *sums = malloc(sizeof(int) * 2);
    sums[0] = sums[1] = 0;
    // Albo lepiej z inicjalizacją 2 elementów do 0:
    *sums = calloc(2, sizeof(int));

    int i;
    // Oblicz sumę wierszu w
    for(i=0;i<y;i++)
    {
        sums[0] += tab[w][i];
    }

    // Oblicz sumę kolumny k
    for(i=0;i<x;i++)
    {
        sums[1] += tab[i][k];
    }

    // Zwróć wskaźnik
    return sums;
}





0

Zobacz co wpisujesz tutaj:

numbers = computeSRC(int x, int y, int tab[x][y], int w, int k);

Przecież definicja funkcji już istnieje (gdzie typy argumentów są podane), ty masz ją wywołać z odpowiednimi parametrami.

0

???

int *numbers;
numbers = computeSRC(x,y,tab[x][y],w,k);
int i;
 for (i=0;i<2;i++)
    {
       printf("\n Suma elementow ??? wynosi: %d", numbers[i]);

    }



    free(numbers); // Zwolnienie używanego obszaru pamięci.

0

tab powinno być przekazane tak:

numbers = computeSRC(x, y, tab, w, k);

Podałem Ci 2 przykłady tworzenia tablicy 2 elementowej:

int* sums = malloc(sizeof(int) * 2);
sums[0] = sums[1] = 0;

oraz

int* sums = calloc(n, sizeof(int));

Oba robią to samo więc użyj jednego z nich (najlepiej tego drugiego).

0

Tak działa ale tylko dla kolumny:


int *numbers;
numbers = computeSRC(x,y,tab,w,k);


       printf("\n Suma elementow wiersza wynosi: %d", numbers[0]);
       printf("\n Suma elementow kolumny wynosi: %d", numbers[1]);



    free(numbers); // Zwolnienie używanego obszaru pamięci.


wiem, że inaczej niż podałeś

0

U mnie działa i dla kolumny i dla rzędu. Co dokładnie jest nie tak, jaki wynik dostajesz?

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