Wczytywanie do dynamicznie alokowanej pamięci z pliku

0

Program w dużym skrócie ma kopiować zawartość pliku do dynamicznie alokowanej tablicy(9x9) tak aby na ekranie wypisała się macierz. Podany poniżej program wypisuje "0" oddzielone enterami. Byłbym wdzięczny za jakąś pomoc. ( jestem początkujący w programowaniu proszę o wyrozumiałość)

#include<stdio.h>
#include<stdlib.h>
#define N 9
int main()
{
    int i, j;
    int **tab;
    FILE* plik;
    tab=(int**)malloc(N*sizeof(int *));
    for(i=0; i<N; i++)
    {
        *(tab+i)=(int*)malloc(N*sizeof(int));
    }

    if((plik=fopen("sudoku.txt", "r"))==NULL)
        printf("Nie moge otorzyc pliku!\n");
        for(i=0;i<N;i++)
            for(j=0;j<N;j++)
        fscanf(plik, "%d", &tab[i][j]);
    if(fclose(plik))
    printf("Nie moge zamknac pliku!\n");
    for(i=0;i<N;i++)
        for(j=0;j<N;j++)
            {
                printf("%d", tab[i][j]);
                printf("\n");
            }
    for(i=0; i<N; i++)
        free(tab[i]);
    free(tab);
    return 0;
}
0
FILE plik;

fopen zwraca wskaźnik na FILE, więc musi być

FILE * plik;

https://pl.wikibooks.org/wiki/C/fopen

Jeżeli robisz 2 razy malloc, to pewnie chodziło o:

  • utworzenie tablicy wskaźników na wskaźnik
  • dla każdego z tych wskaźników utworzenie już właściwej tablicy do wpisywania wartości
Nsizeof(int)

Musi tu być znak mnożenia, a w pierwszym malloc powinien być sizeof wskaźnika (bo będziemy trzymać tam wskaźniki).

N*sizeof(int*)

Przy tym samym (pierwszym) malloc kompilator pokaże błąd, że typy się nie zgadzają - trzeba poprawić przy rzutowaniu.
Przy drugim malloc najprościej jest zapisać to tak:

tab[i]=(int*)malloc(N*sizeof(int));

Plus za nieolewanie zwalniania pamięci i zamykania plików :)

0

@ST3PA: Weź to sformatuj, to Ci nic nie będzie wycinać...

0

ogarnąłem formatowanie. Faktyczny kod wygląda tak jak powyzej.

0

Podaj jeszcze zawartość pliku który wczytujesz, bo może z nią związany jest problem...?

0

Kod po drobnej poprawie:

#include<stdio.h>
#include<stdlib.h>
#define N 9


int main()
{
    int i, j;
    int **tab;
    FILE* plik;

    tab=(int**)malloc(N*sizeof(int *));
    for(i=0; i<N; i++)
    {
        tab[i]=(int*)malloc(N*sizeof(int));
    }

    if((plik=fopen("sudoku.txt", "r"))==NULL)
        printf("Nie moge otorzyc pliku!\n");

        for(i=0;i<N;i++)
        {
            for(j=0;j<N;j++)
                fscanf(plik, "%d", &tab[i][j]);
        }

    if(fclose(plik))
    printf("Nie moge zamknac pliku!\n");
    for(i=0;i<N;i++)
    {
        for(j=0;j<N;j++)
            printf("%d", tab[i][j]);
        printf("\n");
    }

    for(i=0; i<N; i++)
        free(tab[i]);
    free(tab);
    return 0;
}

Zawartosc pliku:

001205052
658390170
293756239
723562379
905488837
762359570
762395823
872356898
237865120

Załączam jeszcze wynik uruchomienia programu

1

No to sprawa jasna -- powinno być

fscanf(plik, "%c", &tab[i][j]);
tab[i][j] -= '0';

-- zamiast

fscanf(plik, "%d", &tab[i][j]);

-- działa teraz?

0

Nadal to nie jest to, po skompilowaniu pojawia się:

1
ST3PA napisał(a):

Nadal to nie jest to, po skompilowaniu pojawia się:

Racja, powinno być:

{
    fscanf(plik, "%c", &tab[i][j]);
    tab[i][j] -= '0';
}

BTW, nie korzystaj z tego, że można opuszczać czasem nawiasy klamrowe... :)

0

Wynik kompilacji:

Dodatkowe pytanie jest takie czy to że wczytuję liczby jako znaki nie wpłynie jakoś na dalsze przekształcanie wartości w tych macierzach

0

Rozumiem że te nieścisłości wynikają z tego że sczytuje mi z pliku biały znak ( enter ). W jaki sposób moge się go pozbyc?

1

Tak, chodzi o enter. Muszisz wczytać jeszcze jeden znak (ten enter) po każdej linii -- do jakiejś zmiennej typu char i go zignorować.

0
ST3PA napisał(a):

Wynik kompilacji:

Dodatkowe pytanie jest takie czy to że wczytuję liczby jako znaki nie wpłynie jakoś na dalsze przekształcanie wartości w tych macierzach

Wydaje mi się, że może wpłynąć... :(

Lepiej chyba (w każdym razie pewniej) byłoby wczytywać do zmiennej pomocniczej typu char (może być ta sama co enter z poprzedniego postu), a potem wrzucać do tablicy. W funkcjach rodziny scanf podajesz adres, to, że działa gdy podasz adres int zamiast char to może być przypadek... Chyba, że się mylę...

0

Ok, poradziłem sobie z rozwiazaniem, wielkie dzięki za pomoc

0

Zostawiam osteteczne rozwiazanie dla potomnych

#include<stdio.h>
#include<stdlib.h>
#define N 9
 
int main()
{
    int i, j;
    int **tab;
    FILE* plik;
 
    tab=(int**)malloc(N*sizeof(int *));
    for(i=0; i<N; i++)
    {
        tab[i]=(int*)malloc(N*sizeof(int));
    }
 
    if((plik=fopen("sudoku.txt", "r"))==NULL)
        printf("Nie moge otorzyc pliku!\n");
 
        for(i=0;i<N;i++)
        {
            for(j=0;j<N+1;j++)
                {
                     fscanf(plik, "%c", &tab[i][j]);
                      tab[i][j] -= '0';
        }
        }
 
    if(fclose(plik))
    printf("Nie moge zamknac pliku!\n");
    for(i=0;i<N;i++)
    {
        for(j=0;j<N;j++)
            printf("%d", tab[i][j]);
        printf("\n");
    }
 
    for(i=0; i<N; i++)
        free(tab[i]);
    free(tab);
    return 0;
}
2

Ajajaj, ale nie powinieneś wczytywać nic do tab[i][N] (a robisz to, tak sobie radzisz z enterem), bo to jest poza formalnie zaalokowaną pamięcią -- więc UB i masz po prostu szczęście, że działa...

Ja bym radził tak (ze zmianą także tego, o czym wcześniej pisaliśmy, żeby nie pakować bezpośrednio chara do tablicy intów):

#include<stdio.h>
#include<stdlib.h>
#define N 9

int main()
{
    int i, j;
    int **tab;
    FILE* plik;
    char znak;
 
    tab=(int**)malloc(N*sizeof(int *));
    for(i=0; i<N; i++)
    {
        tab[i]=(int*)malloc(N*sizeof(int));
    }
 
    if((plik=fopen("sudoku.txt", "r"))==NULL)
        printf("Nie moge otorzyc pliku!\n");
 
        for(i=0;i<N;i++)
        {
            for(j=0;j<N;j++)
            {
                fscanf(plik, "%c", &znak);
                tab[i][j] = znak - '0';
            }
            fscanf(plik, "%c", &znak);
        }
 
    if(fclose(plik))
    printf("Nie moge zamknac pliku!\n");
    for(i=0;i<N;i++)
    {
        for(j=0;j<N;j++)
            printf("%d", tab[i][j]);
        printf("\n");
    }
 
    for(i=0; i<N; i++)
        free(tab[i]);
    free(tab);
    return 0;
}

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