Przekazywanie tablicy dynamicznej pomiędzy funkcjami

Przekazywanie tablicy dynamicznej pomiędzy funkcjami
M1
  • Rejestracja:ponad 7 lat
  • Ostatnio:około 7 lat
  • Postów:3
0

Siemka,
mam do napisania program, który będzie sobie radził z obrazami PGM/PPM.
Funkcja "czytaj" wczytuje sobie informacje o pliku(P2/P3, szerokosc, wysokosc max kolor) a następnie wczytuje wartosci pikseli obrazu do tablicy dynamicznej.
Kiedy operacja się powiedzie, przekazuje wszytskie wartosci do funkcji main.
Problem pojawia się przy próbie zapisania wartości z tablicy "obraz" do pliku.
Przypuszczam, że źle przekazuje tablice z czytaj do main, ale nie znam innego sposobu.
Proszę o pomioc, jak to zrobic poprawnie, zeby działało.

czytaj.c

Kopiuj
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include"czytaj.h"

#define DL_LINII 1024      /* Dlugosc buforow pomocniczych */


int czytaj(FILE *plik_we,int **tablica,int *wymx,int *wymy, int *szarosci,char numerMagiczny[2]) {
    char buf[DL_LINII];      /* bufor pomocniczy do czytania naglowka i komentarzy */
    int znak;                /* zmienna pomocnicza do czytania komentarzy */
    int koniec=0;            /* czy napotkano koniec danych w pliku */
    int i,j;
    
    
    
    /*Sprawdzenie czy podano prawid≥owy uchwyt pliku */
    if (plik_we==NULL) {
        fprintf(stderr,"Blad: Nie podano uchwytu do pliku\n");
        return(0);
    }
    
    /* Sprawdzenie "numeru magicznego" - powinien byÊ P2 */
    if (fgets(buf,DL_LINII,plik_we)==NULL)   /* Wczytanie pierwszej linii pliku do bufora */
        koniec=1;                              /* Nie udalo sie? Koniec danych! */
    
    if ( (buf[0]='P') && ((buf[1]='2') | (buf[1]='3')) ) { /* Czy jest magiczne "P2/P3"? */
        numerMagiczny[0]=buf[0];
        numerMagiczny[1]=buf[1];}
        else{
        fprintf(stderr,"Blad: To nie jest plik PGM/PPM\n");
        return(0);
        }
    
    /* Pominiecie komentarzy */
    do {
        if ((znak=fgetc(plik_we))=='#') {         /* Czy linia rozpoczyna sie od znaku '#'? */
            if (fgets(buf,DL_LINII,plik_we)==NULL)  /* Przeczytaj ja do bufora                */
                koniec=1;                   /* Zapamietaj ewentualny koniec danych */
        }  else {
            ungetc(znak,plik_we);                   /* Gdy przeczytany znak z poczatku linii */
        }                                         /* nie jest '#' zwroc go                 */
    } while (znak=='#' && !koniec);   /* Powtarzaj dopoki sa linie komentarza */
    /* i nie nastapil koniec danych         */
    
    /* Pobranie wymiarow obrazu i liczby odcieni szarosci */
    if (fscanf(plik_we,"%d %d %d",wymx,wymy,szarosci)!=3) {
        fprintf(stderr,"Blad: Brak wymiarow obrazu lub liczby stopni szarosci\n");
        return(0);
    }
    
    
    tablica = (int **)malloc(*wymx * sizeof(int *)); //Zdefiniowanie tablicy dynamicznej
                                                    //Przystosowanej dla rozmiarow obrazu
    for (i = 0; i < *wymy; ++i)
        tablica[i] = (int *)malloc(*wymy * sizeof(int));
    
    
    /* Pobranie obrazu i zapisanie w tablicy obraz_pgm*/
    for (i=0;i<*wymx;i++) {
        for (j=0;j<*wymy;j++) {
            if (fscanf(plik_we,"%d", &tablica[i][j])!=1) {
                fprintf(stderr,"Blad: Niewlasciwe wymiary obrazu\n");
                return(0);
            }
        }
    }
    return *wymx**wymy;   /* Czytanie zakonczone sukcesem    */
}                       /* Zwroc liczbe wczytanych pikseli */

main.c

Kopiuj
#include"display.h"
#include"czytaj.h"

int main() {
    FILE *plik;
    int *obraz ; //tablica z obrazem
    int wymx,wymy,odcieni; //dane obrazu
    char nazwa[100];
    char numerMagiczny[2];
    int i, j;
    int odczytano = 0;

    int menu; //menu
    
    do { //Menu uzytkownika
        
        printf("Menu: \n");
        printf("\t1 - Wczytanie obrazu \n");
        printf("\t2 - Wyświetlenie obrazu \n");
        printf("\t3 - Zapis obrazu \n");
        printf("\t4 - Zakończenie \n\n");
        printf("Twoj wybor: ");
        scanf("%d", &menu); //Dokonanie wyboru
        
        switch(menu){
            case 1: printf("Wybrano wczytanie obrazu \n");
                
                printf("Podaj nazwe pliku:\n"); /* Wczytanie zawartosci wskazanego pliku do pamieci */
                scanf("%s",nazwa);
                plik=fopen(nazwa,"r");
                
                if (plik != NULL) {       /* co spowoduje zakomentowanie tego warunku */
                    odczytano = czytaj(plik,&obraz,&wymx,&wymy,&odcieni,numerMagiczny);
                    fclose(plik);
                    printf("Pomyślnie wczytano obraz\n");
                }
                break;
                
            case 2: printf("Wybrano wyswietlenie obrazu \n");
                if (plik != NULL) {       /* co spowoduje zakomentowanie tego warunku */
                    odczytano = czytaj(plik,&obraz,&wymx,&wymy,&odcieni,numerMagiczny);
                    fclose(plik);
                }
                /* Wyswietlenie poprawnie wczytanego obraza zewnetrznym programem */
                if (odczytano != 0)
                    wyswietl(nazwa);
                break;
                
            case 3: printf("Wybrano zapis obrazu \n"); //Sprawdzenie czy wczytano plik
                plik=fopen(nazwa, "w");
                
                if ((plik=fopen(nazwa, "w")) == NULL){
                    fprintf(stderr,"Blad: Nie wczytano pliku\n");
                    break;
                }
                else{
                    fprintf(plik, "%c%c\n", numerMagiczny[0], numerMagiczny[1]); /*Zapisanie magicznego numeru*/
                    fprintf(plik, "# Plik edytowany \n");
                    fprintf(plik, "%d %d\n%d\n", wymx, wymy, odcieni); /*Zapisanie szerokosci, wysykosci i max wartosci szarosci*/
                    for (i = 0; i < wymy; i++) {
                        for (j = 0; j < wymx; j++)
                            fprintf(plik, "%d ", obraz[i][j]);
                        fprintf(plik, "\n");}
                    fclose(plik);
                    printf("Obraz zapisano pomyślnie \n");
                }
                break;
                
        }
    }while(menu!=4);
    
    printf("Program zakończył działanie. \n"); //Koniec programu
    
    return odczytano;
}
edytowany 1x, ostatnio: mike14
PanRiK
  • Rejestracja:ponad 7 lat
  • Ostatnio:ponad rok
  • Lokalizacja:Szczecin
  • Postów:104
0
Kopiuj
if ( (buf[0]='P') && ((buf[1]='2') | (buf[1]='3')) )  ...

Nie powinny być dwa znaki || ?

Masz tablice dynamiczną , a nigdzie jej na zwalniasz "free()"

Edit.
Według mnie taka danymaczna tablica nie jest potrzebna, bo ogólnie wymiary zczytujesz i wychodzi X na Y, i zawsze wymiar bedzie X na Y , nigdy nie bedzie w obrazie tak, żeby np. nie było potrzeba ostatniej wartości z kolumny, więc jej nie będzie.

Ogólnie to co tutaj stworzyłeś to nie jest do końca tablica dynamiczna dwuwymiarowa, jest "jednowymiarowa tablica zawierająca wskaźniki do tablic jednowymiarowych". Znalazłem na internecie coś takiego:

Kopiuj
int main()
{
  int m=4,n=3;
  int** arr;
  allocate_mem(&arr,n,m);
}

int* allocate_mem(int*** arr, int n, int m)
{
  *arr = (int**)malloc(n * sizeof(int*));
  int *arr_data = malloc( n * m * sizeof(int));
  for(int i=0; i<n; i++)
     (*arr)[i] = arr_data + i * m ;
  return arr_data; //free point
} 

do delokowanie tablicy:

Kopiuj
void deallocate_mem(int*** arr, int* arr_data){
    free(arr_data);
    free(*arr);
}

Takie rozwiązanie wydaje mi się troszeczkę sensowniejsze.


Jeśli widzisz mój błąd to mnie popraw.
Pisanie błędnych wypowiedzi utrwala złe praktyki.
Kiedyś możesz dostać do ręki mój kod.
edytowany 6x, ostatnio: PanRiK
M1
Fakt powinny powinno być " || " i powinienem zwolić tablice, ale to chyba nadal nie rozwiązuje głównego problemu.
PanRiK
Dobra, dlaczego potrzebujesz , akurat takiej tablicy dynamicznej?
M1
Takie wymogi zadania, że obraz ma być zapisany w dynamicznej tablicy, przystosowanej rozmiarowo do obrazu
Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)