Czytanie z pliku macierzy i wsadzenie jej do tablicy wielowymiarowej oraz odczytywanie z konkretnej linijki w C

0

Mam trudne zadanie i trochę utknąłem tak wygląda moja funkcja (takie musi przyjąć argumenty), którą muszę zrobić int readArray(FILE *wp, char *name, int n, double M[n][n]). Muszę przeczytać macierz z pliku i wsadzić nazwę macierzy do tablicy wskaźnikowej, która przechowuję nazwę oraz wsadzić macierz do tablicy dwuwymiarowej o wielkości n. Próbowałem uruchomić program, ale dostaje segmentation fault.

To jeszcze nic, jest jeszcze coś gorszego. W pliku mam drugą macierz, którą też muszę odczytać, ale jak zacząć czytać tekst od konkretnej linijki? Myślałem o jakimś scanf, w którym zapytam użytkownika od której linijki chce czytać i wtedy, mam zmienną przechowującą tą informację, ale co potem, czy są jakieś funkcje w c, które pozwolą mi na czytanie od pewnego miejsca?

Oto mój program:

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


int readArray(FILE *wp, char *name, int n, double M[n][n])
{
    int i = 0, j;
    fscanf(wp, "%s", &name[0]);
    printf("Print name: %s", name);
    return 0;
    for (i = 0; i < n; ++i)
        for (j = 0; j < n; ++j)
            fscanf(wp, "%lf", &M[i][j]);
    printf("Print array: %s", name);

}

int main (int argc, char *argv[])
{
    FILE *wz;                         
    int n = 3;
    char *name[1];
    char *name2[1]; 
    double arr[n][n];
    double arr2[n][n];


    if (argc != 2) {                                
    printf("Wrong arguments number\n");
    printf("I should run this way:\n");
    printf("%s source\n",argv[0]);
    exit(1);
    }

    if( (wz= fopen(argv[1],"r")) == NULL) {
        printf("Open error %s\n", argv[1]);
        exit(1);
    }

    readArray(wz, *name, n, arr);
    readArray(wz, *name2, n, arr2);    

    int fclose(FILE *wz);
    int fclose(FILE *wc);

    return 0;
}

Oraz plik z moimi danymi

arr1
9 8 7
6 5 4
3 2 1
arr2
1 2 3
4 5 6
7 8 9
1

Zaalokowałeś pamięć dla stringów wskazywanych przez name i name2?

1

nie wiem jak to jest w języku C, ale ja bym zaczął wczytywać po prostu jak leci do jakiejś tablicy, listy, wektora czy czegokolwiek co ci wygodne - czyli byłby to taki ciąg cyferek

1, 2, 3, 4, 5 ... N

z tego co widzę, ty masz macierz rozdzieloną spacjami, ja to bym wyszedł z założenia, że lepiej by było gdybyś uwzględnił dopuszczalne seperatory np

; : spacja ,

(ale już nie kropka, z tego względu, że kropka w macierzy może być liczbą zmiennoprzecinkową -> 25.5)

następnie, na podstawie wyliczonych seperatorów obliczyłbym ile jest kolumn w macierzy - oczywiście powiększając to o jeden, gdyż seperatorów jest o jeden za mało w stosunku do ilości kolumn

w drugim kroku zliczyłbym niewidoczne znaki typu "\n" (znak nowej linii) w sumie są trzy takie znaki LF, CR, CRLF - w zależności jaki system operacyjny używasz - to posłużyłoby do zliczenia ilości wierszy w macierzy - takie cuda możesz sobie podejrzeć w dowolnym hexedytorze

następnie zrobiłbym parsowanie i oddzieliłbym liczby od seperatorów i ogólnie rzecz biorąc umieściłbym te wszystkie cyferki w modelu macierzy

1

Nie trzeba tak, scanf() w tym przypadku sam wykryje spacje jako separator i je pominie.

1

Co do skakania po pliku, to chyba nie o to chodziło autorowi zadania.
Ja to rozumiem tak, że masz czytać po kolei linie pliku: nazwa, elementy macierzy (wiesz ile masz do przeczytania wierszy np. po liczbie elementów pierwszego wiersza z elementami), potem kolejna nazwa, elementy, itd. aż do EOF.

1

chociaż czekaj, myślę, że nie będzie problemu z wykryciem nazwy macierzy w pliku, wystarczy, że podczas wczytywania będzie porównywał odpowiednie znaki z kodem ASCII (małe i duże litery) - najgorzej, jak w nazwie będzie jakiś numer...

0

Co do nazwy i alokowania pamięci do stringów, to nie trzeba

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


int readArray(FILE *wp, char *name)
{
    int i = 0, j;
    fscanf(wp, "%s", &name[0]);
    printf("Print name: %s", name);

    return 0;
}

int main (int argc, char *argv[])
{
    FILE *wz;                         
    int n = 3;
    char *name[1];


    
    if (argc != 2) {                                
    printf("Wrong arguments number\n");
    printf("I should run this way:\n");
    printf("%s source\n",argv[0]);
    exit(1);
    }
    
    if( (wz= fopen(argv[1],"r")) == NULL) {
        printf("Open error %s\n", argv[1]);
        exit(1);
    }

    readArray(wz, *name);
    
    int fclose(FILE *wz);
    int fclose(FILE *wc);
    
    return 0;
}

Ten kod działa bez zarzutu.

Niestety , chyba przy kolejnym wywołaniu fscanf, program nie pamięta, że już raz fscanf użył i odczytał tą linijkę napisu i jak potem chce wczytać macierz do tablicy wielowymiarowej to znów wczytuje stringa z pierwszej linijki, a nie wartości z drugiej
Ten kod dalej daje naruszenie ochrony pamięci

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


int readArray(FILE *wp, char *name, int n, double M[n][n])
{
    char buffer[100];
    int i, j;
    fscanf(wp, "%s", &name[0]);
    for (i = 0; i < n; ++i)
        for (j = 0; j < n; ++j)
            fscanf(wp, "%lf", &M[i][j]);

    return 0;
}

int main (int argc, char *argv[])
{
    FILE *wz;                         
    int n = 3;
    char *name[1];
    char *name2[1]; 
    double arr[n][n];
    double arr2[n][n];

    
    if (argc != 2) {                                
    printf("Wrong arguments number\n");
    printf("I should run this way:\n");
    printf("%s source\n",argv[0]);
    exit(1);
    }
    
    if( (wz= fopen(argv[1],"r")) == NULL) {
        printf("Open error %s\n", argv[1]);
        exit(1);
    }

    readArray(wz, *name, n, arr);
    
    int fclose(FILE *wz);
    int fclose(FILE *wc);
    
    return 0;
}

Wczytuje macierz prawdopodobnie dobrze, bo zrobiłem plik tekstowy

1 2 3
4 5 6
7 8 9

I użyłem tego kodu i czyta elegancki

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


int readArray(FILE *wp, int n, double M[n][n])
{
    int i, j;
    for (i = 0; i < n; ++i)
        for (j = 0; j < n; ++j)
            fscanf(wp, "%lf", &M[i][j]);
    printf("Two Dimensional array elements:\n");
    for(i=0; i<3; i++) 
    {
        for(j=0;j<3;j++) 
        {
            printf("%f ", M[i][j]);
        }
    }
    return 0;
}

int main (int argc, char *argv[])
{
    FILE *wz;                         
    int n = 3;
    double arr[n][n];

    
    if (argc != 2) {                                
    printf("Wrong arguments number\n");
    printf("I should run this way:\n");
    printf("%s source\n",argv[0]);
    exit(1);
    }
    
    if( (wz= fopen(argv[1],"r")) == NULL) {
        printf("Open error %s\n", argv[1]);
        exit(1);
    }

    readArray(wz, n, arr);
    
    int fclose(FILE *wz);
    int fclose(FILE *wc);
    
    return 0;
}

1

powiem tak. Kod działa dobrze. Kod jest poprawny ale nie wiem jak się zachowa dalej, bo nie miałem kiedy tego dokończyć, bo teraz uczę się Qt.

Klasa macierz ma dwa konstruktory.

  1. Utworzy macierz kwadratową
macierz(int); //kwadratowa
  1. Utworzy macierz prostokątną
macierz(int, int); //prostokatna

jak tego użyć ?

w pliku main tworzysz obiekt macierz odpowiednim konstruktorem

macierz m(7,2);

w pętli wywołujesz funkcję która wpisze odpowiednie liczby do macierzy.

pierwszy parametr typu int, to wiersz, drugi to kolumna, trzeci to wartość do wstawienia

m.wypelnij_macierz(0,0,5);

następnie wyświetlasz macierz funkcją

m.wyswietl_macierz();

oto cały kod

  1. Klasa
class macierz
{
public:
    macierz(int); //kwadratowa
    macierz(int, int); //prostokatna
    ~macierz();

    int *wypelnij_macierz(int, int, int);
    void wyswietl_macierz(void);

    int FunWiersz(int);
    int FunKolumna(int);

private:
    int wiersze;
    int kolumny;
    int wymiarKwadr;

    int wyp_wiersz;
    int wyp_kolumne;

    int **_macierz;
};
  1. definicja klasy
#include <iostream>
#include "macierz.h"

macierz::macierz(int _wymiar) : wymiarKwadr(_wymiar)
{
    _macierz = new int *[wymiarKwadr];

    wiersze = kolumny = wymiarKwadr;

    for(int i=0; i<wymiarKwadr; i++)
    {
        _macierz[i] = new int [wymiarKwadr];
    }

    for(int i=0; i<wymiarKwadr; i++)
    {
        for(int j=0; j<wymiarKwadr; j++)
        {
            _macierz[i][j] = 0;
        }
    }
}

macierz::macierz(int _wiersze, int _kolumny) : wiersze(_wiersze), kolumny(_kolumny)
{
    _macierz = new int *[wiersze];

    for(int i=0; i<wiersze; i++)
    {
        _macierz[i] = new int [kolumny];
    }

    for(int i=0; i<wiersze; i++)
    {
        for(int j=0; j<kolumny; j++)
        {
            _macierz[i][j] = 0;
        }
    }
}

int *macierz::wypelnij_macierz(int _wiersz, int _kolumna, int _wartosc)
{
    wyp_wiersz = _wiersz;
    wyp_kolumne = _kolumna;

    _macierz[wyp_wiersz][wyp_kolumne] = _wartosc;

    return &_macierz[0][0];
}

/*void macierz::wyswietl_macierz(void)
{
    for(int i=0; i<wymiarKwadr; i++)
    {
        std::cout << "|";

        for(int j=0; j<wymiarKwadr; j++)
        {
            if(j % wymiarKwadr != 0)
            {
                std::cout << "\t";
            }

            if(_macierz[i][j] < 10)
            {
                std::cout << " ";
            }

            std::cout << _macierz[i][j];
        }

        std::cout << "|";
        std::cout << std::endl;
     }
}*/

void macierz::wyswietl_macierz(void)
{
    for(int i=0; i<wiersze; i++)
    {
        std::cout << "|";

        for(int j=0; j<kolumny; j++)
        {
            if(j % kolumny != 0)
            {
                std::cout << "\t";
            }

            if(_macierz[i][j] < 10)
            {
                std::cout << " ";
            }

            std::cout << _macierz[i][j];
        }

        std::cout << "|";
        std::cout << std::endl;
     }
}

int macierz::FunWiersz(int _wiersz)
{
    wiersze = _wiersz;

    return wiersze;
}

int macierz::FunKolumna(int _kolumna)
{
    kolumny = _kolumna;

    return kolumny;
}

macierz::~macierz()
{
    std::cout << "Usuwam macierz" << std::endl;

    for(int i=0; i<wymiarKwadr; i++)
    {
        //delete [] _macierz[i];
    }

    delete [] _macierz;
}
  1. plik main
int main(void)
{
    macierz m(7);

    m.wypelnij_macierz(0,0,5);
    m.wypelnij_macierz(0,1,7);

    m.wyswietl_macierz();

    return 0;
}

daj mi znać czy to co zrobiłem się sprawdziło. Poniżej zrzut z działania programu

screenshot-20200426142834.png

0

W ogóle proponuję przemyśleć swój kod na spokojnie i zająć się problemami po kolei, a nie prosić kogoś o gotową klasę - na dodatek w innym (gorszym, szkodliwym dla Ciebie) języku i jeszcze w dodatku źle napisaną...
Masz dużo innych błędów w swoim kodzie, o których na razie nie wspomniałem, żeby na razie Tobie nie mieszać... np. co to ma być?

 int fclose(FILE *wz);
 int fclose(FILE *wc);

Ogólnie Twoja okrojona wersja kodu czytająca 1 macierz działa tylko przez przypadek. Warto zrozumieć dlaczego.

0

Co do pytania.
Tak to zapomniałem usunąć. Powinno być tylko

 int fclose(FILE *wz);

Zamykam plik ręcznie, tak nam mówili.

Co do tego segmentation fault, to pewnie dlatego on występuje. Chodzi o ten fragment kodu:

    fscanf(wp, "%s", &name[0]);
    for (i = 0; i < n; ++i)
        for (j = 0; j < n; ++j)
            fscanf(wp, "%lf", &M[i][j]);

co do pliku danych to tak jak wyżej

arr1
9 8 7
6 5 4
3 2 1
arr2
1 2 3
4 5 6
7 8 9

Najpierw do tablicy wskaźnikowej wczytuje napis arr1, ale potem chyba przy ponownym użyciu fscanf czyta znowu od samego początku, czyli dla elementu [0][0] - będzie wartość arr1, dla [0][1] będzie dziewięc, a powinno być M[0][0] = 9 M[0][1] = 8. Więc dla tablicy typu double wsadza mi łańcuch znaków do pierwszego elementu, zamiast liczby

Dlaczego tak wywnioskowałem?

Ponieważ nie mam błędu segmentacji w tej funkcji, w której wczytuje sam napiś, więc problem nie leży we wczytywaniu napisu

int readArray(FILE *wp, char *name)
{
    int i = 0, j;
    fscanf(wp, "%s", &name[0]);
    printf("Print name: %s", name);

    return 0;
}

Także gdy mam samą macierz w pliku tekstowym, tak jak napisałem wyżej

1 2 3
4 5 6
7 8 9

i stosuje funkcję do jej wczytania i wyświetlenia to czyta elegancko


int readArray(FILE *wp, int n, double M[n][n])
{
    int i, j;
    for (i = 0; i < n; ++i)
        for (j = 0; j < n; ++j)
            fscanf(wp, "%lf", &M[i][j]);
    printf("Two Dimensional array elements:\n");
    for(i=0; i<3; i++) 
    {
        for(j=0;j<3;j++) 
        {
            printf("%f ", M[i][j]);
        }
    }
    return 0;
}
0
Morgotheron napisał(a):

Co do pytania.
Tak to zapomniałem usunąć. Powinno być tylko

 int fclose(FILE *wz);

Zamykam plik ręcznie, tak nam mówili.

Ty tu niczego nie zamykasz. Ty tu jedynie deklarujesz lokalną funkcję wewnątrz funkcji main. Powinno być wywołanie:

fclose(wz);

Co do tego segmentation fault, to pewnie dlatego on występuje. Chodzi o ten fragment kodu:

    fscanf(wp, "%s", &name[0]);
    for (i = 0; i < n; ++i)
        for (j = 0; j < n; ++j)
            fscanf(wp, "%lf", &M[i][j]);

A sprawdziłeś to?

co do pliku danych to tak jak wyżej

arr1
9 8 7
6 5 4
3 2 1
arr2
1 2 3
4 5 6
7 8 9

Najpierw do tablicy wskaźnikowej wczytuje napis arr1, ale potem chyba przy ponownym użyciu fscanf czyta znowu od samego początku, czyli dla elementu [0][0] - będzie wartość arr1, dla [0][1] będzie dziewięc, a powinno być M[0][0] = 9 M[0][1] = 8. Więc dla tablicy typu double wsadza mi łańcuch znaków do pierwszego elementu, zamiast liczby

Dlaczego tak wywnioskowałem?

Ponieważ nie mam błędu segmentacji w tej funkcji, w której wczytuje sam napiś, więc problem nie leży we wczytywaniu napisu

int readArray(FILE *wp, char *name)
{
    int i = 0, j;
    fscanf(wp, "%s", &name[0]);
    printf("Print name: %s", name);

    return 0;
}

Także gdy mam samą macierz w pliku tekstowym, tak jak napisałem wyżej

1 2 3
4 5 6
7 8 9

i stosuje funkcję do jej wczytania i wyświetlenia to czyta elegancko


int readArray(FILE *wp, int n, double M[n][n])
{
    int i, j;
    for (i = 0; i < n; ++i)
        for (j = 0; j < n; ++j)
            fscanf(wp, "%lf", &M[i][j]);
    printf("Two Dimensional array elements:\n");
    for(i=0; i<3; i++) 
    {
        for(j=0;j<3;j++) 
        {
            printf("%f ", M[i][j]);
        }
    }
    return 0;
}

A z tym stringiem (char *) widzę jednak ciągle problem. Zastanów się gdzie on tą wartość ciągu znaków zapisuje. U mnie fscanf z %lf działa zgodnie z oczekiwaniami jeżeli poprawnie zaalokuję pamięć dla stringa.

1
zkubinski napisał(a):

powiem tak. Kod działa dobrze. Kod jest poprawny ale nie wiem jak się zachowa dalej, bo nie miałem kiedy tego dokończyć, bo teraz uczę się Qt.

Kod jest daleki od ideału (delikatnie mówiąc). Ujął mnie pozytywnie w zasadzie tylko dwoma konstruktorami, tylko przez to znalazłem energię do korekt.

class macierz  // byłaby kandydatką na fajną macierz, gdyby była typowana temmplate<T>
{
public:
    macierz(int); //kwadratowa  // @any: OK
    macierz(int, int); //prostokatna  // @ny: OK
    virtual ~macierz();   // gdyby przyszło do głowy komuś odziedziczyć
    void wypelnij_macierz(int, int, T); // na cholerę ten straszny return ???
    void wyswietl_macierz(ostream & str);  // unikamy hardkodowania cout
//     int FunWiersz(int);  // największa patologia tej klasy, mutator, który wysadza w powietrze, z dziwny returnem. Skąd taki archaiczny pomysł ???
//     int FunKolumna(int);
     int get_kolumny() const { return kolumny; }
     int get_wiersze() const { return wiersze; }
private:
    int wiersze;  /// a nawet ośmielił bym się const
    int kolumny;
//     int wymiarKwadr;   zbędne i wprowadzjace błędy
//      int wyp_wiersz;  // sieczka, do czego to jest?
//     int wyp_kolumne;   // sieczka, do czego to jest?
    T **_macierz;
};
#include <iostream>
#include "macierz.h"
 macierz::macierz(int _wymiar) : macierz(_wymiar,_wymiar)
{
}
macierz::macierz(int _wiersze, int _kolumny) : wiersze(_wiersze), kolumny(_kolumny)
{
    _macierz = new int *[wiersze];
    for(int i=0; i<wiersze; i++)
    {
        _macierz[i] = new int [kolumny] () ;  // new zerujący
    }
//     _macierz = new int *[wiersze];
// 
//     for(int i=0; i<wiersze; i++)
//     {
//         _macierz[i] = new int [kolumny];
//     }
// 
//     for(int i=0; i<wiersze; i++)
//     {
//         for(int j=0; j<kolumny; j++)
//         {
//             _macierz[i][j] = 0;
//         }
//     }
}
void macierz::wypelnij_macierz(int _wiersz, int _kolumna, T _wartosc)    //na Hugona ten return ???
{
//    wyp_wiersz = _wiersz;
//     wyp_kolumne = _kolumna;

    _macierz[wyp_wiersz][wyp_kolumne] = _wartosc;  // najstrasi górale nie rozumieją dlaczego jedna komórka, jak obiecuje całą macierz !?!??!?

//    return &_macierz[0][0]; // niczemu nie służy
}
/*void macierz::wyswietl_macierz(ostream & str)
{
    for(int i=0; i<wymiarKwadr; i++)     // <-- tu się sam potykasz na swojej źle zaprojektowanej zmiennej
     { 
        str << "|";
     }
} */
void macierz::wyswietl_macierz(ostream & str)
{
    for(int i=0; i<wiersze; i++)
    {
         str << "|";

        for(int j=0; j<kolumny; j++)
        {
            if(j % kolumny != 0)   // WTF
           {
               str << "\t";
           }
            if(_macierz[i][j] < 10)  // a ja lubię 9, albo 12 ....
            {
                str << " ";
            }
             str  << _macierz[i][j];
        }
        str << "|";
        str << std::endl;
     }
}
macierz::~macierz()
{
//      std::cout << "Usuwam macierz" << std::endl;  od tego są debuggery
    for(int i=0; i<wymiarKwadr; i++)  // znów wdepnąłeś w g.... 
    {
         delete [] _macierz[i];  // ma być, zdjąłem komentarz
    }
    delete [] _macierz;
}

Podsumowanie @zkubinski Gdybyś dał taki kod w rubryce "mam problem", może bym go tak nie rozjechał, ale że go zalecasz innym, to Ci się należy

PS. jest taki styl, że returnuje się "coś", i to "coś" pozwala zbudować wyrażenie z kropkami,

t.ala().ma().kota()

ale to "coś" się robi ZUPEŁNIE inaczej

1

@AnyKtokolwiek

oo, fajnie, dzięki za rozjechanie :D mam nadzieję, że wyciągnę z tego jakieś wnioski, ten kod powstał po to by zrozumieć jak robić macierze, klasy i obiekty - od czegoś trzeba wyjść by to coś potem poprawić, jeszcze nie spotkałem kogoś kto zrobiłby cokolwiek na 100% idealnie, a tak poza tym, wiem, że to nadaje się na szablon ale problem w tym, że jeszcze szablonów nie przerobiłem, nie mówiąc już o zasadzie 3/5/0 w której i tak nie wiem o co chodzi i jeszcze wspominacie o tajemniczym SRP - ja jestem samoukiem, nie kończyłem "cudownych" studiów informatycznych które człowiekowi nic nie dają oprócz zmarnowania czasu na zaliczenie setek niepotrzebnych w życiu zawodowym bzdur - ale skończyłem inne pokrewne...

Ale dzięki za uwagi. Co do przykładu t.ala().ma().kota() zawsze chciałem rozumieć skąd taki zapis się bierze, conieco doszedłem dlaczego ale i tak dużo mi brakuje, po prostu ja uczę się samodzielnie, a nie mam się od kogo uczyć, bo dużo ludzi nie dzieli się wiedzą, nie chcą jej pchać dalej, tylko wiecznie są prowadzone debaty o wszystkim i o niczym byle tylko nie rozjaśnić tego o co się pyta. Zamiast rzucić konkretny przykład który wyjaśniłby zupełnie wszystko (ewentualnie byłyby pytania gdyby czegoś się nie rozumiało) - ale brak jest konstruktywnej wymiany zdań i doświadczenia. Tylko odbywa się to na zasadzie polskiej patrz jak ci dowalę

0

pytanie do @AnyKtokolwiek

jak już w tym wątku pojawiła się mowa o poniższym wyrażeniu, to czy dasz jakiś przykład na to z którego można zbudować takie wyrażenie ?

t.ala().ma().kota()
0

@thock
Próbowałem zaalokować tak jak pisałeś w komentarzu pamięć

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


int readArray(FILE *wp, char *name, int n, double M[n][n])
{
    int i, j;
    fscanf(wp, "%s", &name[0]);
    for (i = 0; i < n; ++i)
        for (j = 0; j < n; ++j)
            fscanf(wp, "%lf", &M[i][j]);

    return 0;
}

int main (int argc, char *argv[])
{
    FILE *wz;                         
    int n = 3;
    char name[10];
    char name2[10];
    char *name[1];
    double arr[n][n];

    
    if (argc != 2) {                                
    printf("Wrong arguments number\n");
    printf("I should run this way:\n");
    printf("%s source\n",argv[0]);
    exit(1);
    }
    
    if( (wz= fopen(argv[1],"r")) == NULL) {
        printf("Open error %s\n", argv[1]);
        exit(1);
    }

    readArray(wz, *name, n, arr);
    
    int fclose(FILE *wz);
    int fclose(FILE *wc);
    
    return 0;
}

Wychodzi taki błąd

ang1.c: In function ‘main’:
ang1.c:21:11: error: conflicting types for ‘name’
     char *name[1];
           ^~~~
ang1.c:20:10: note: previous declaration of ‘name’ was here
     char name[10];
          ^~~~

0

Pierwszy lepszy sposób:

char name[10][10]; // właściwa tablica 10 stringów po max 10 znaków
char *name_ptr; // pointer do przekazania w wywołaniu funkcji

potem wywoływać kolejne czytania macierzy w jakiejś pętli gdzie indeksem będzie i:

name_ptr = &name[0][i];

czyli najpierw możesz bez pętli przetestować 1 wywołanie:

name_ptr = &name[0][0];
readArray(..., name_ptr, ...);

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