Wczytanie macierzy z pliku do tablicy

0

Muszę wczytać z pliku macierz i wrzucić ją do tablicy. Plik ma mieć postać:

7 6 7
1 -2 1
3 1 -2
100
0
0

Wydaje mi się że:
Pierwszym krokiem miałoby być zbadanie jaka duża jest macierz.
Drugim deklaracja dwóch tablic - jednej kwadratowej dla pierwszej macierzy i później drugiej dla macierzy wyrazów wolnych
Ostatnim samo wczytanie danych do dwóch macierzy.

W jaki sposób najłatwiej sprawdzić wielkość potrzebnych tablic? Policzyć spacje w pierwszej linii +1?

No z deklaracją problemów już nie będę miał.

A jak wczytywać dane?

Program mam już napisany ale nie jest idealny...
Najpierw pytałem użytkownika jakie duża jest macierz i deklarowałem tablice. Później całą zawartość pliku wrzucałem sobie do tablicy dla wygody. Później badałem każdy kolejny znak dopóki nie uzupełniłem macierzy nxn. Gdy trafiłęm na coś innego niż znak spacji albo enter sprawdzałem czy to minus albo czy następny znak to też liczba itp... Ten fragment kodu trochę się rozrósł, ma pełno ifów i działa tylko dla liczb max3 cyfrowych... Nie ma czegoś prostszego? :P

Prosiłbym o pomoc ;)

0

tylko po co maciez ? czemu koniecznie kwadrat albo prostokat?

czy nie lepiej dla danych:

7 6 7
1 -2 1
3 1 -2
100
0
0

stworzyc strukture "prawie tablicowa" znczy pierwsza (zerowa) komorka trzyma dlugosc linii, a w reszczie znajduja sie dane:

3 7 6 7
3 1 -2 1
3 3 1 -2
1 100
1 0
1 0
#include <string.h>
#include <stdio.h>

int main(int argc,char** argv){
#define MAXLINESIZE 1024
  int** tab=0;
  int wa=0;
  char s[MAXLINESIZE];
  if(argc<2){
    printf("uruchom program z nazwa pliku jako parametrem\n");
    return -1;
  }
  FILE* f=fopen(argv[1],"r");
  if(!f){
    printf("nie mozna otworzyc pliku\n");
    return -2;
  }
  int k,w=0;  // w jak wiersz
  while(fgets(s,MAXLINESIZE,f)){       // wczytac linie max 512-1 znakow z pliku
    printf("linia=%s",s);
    char* p=s;
    if(w>=wa){
      if(wa){
        wa*=2;
      }else wa=1;
      tab=(int**)realloc(tab,wa*sizeof(int*));
      if(!tab){
        printf("brak pamieci!\n");
        return -3;
      }
    }
    tab[w]=(int*)malloc(sizeof(int));
    if(!tab[w]){
      printf("brak pamieci!\n");
      return -4;
    }
    tab[w][0]=k=0;
    while(p=strtok(p," \n\r")){
//      if(*p){             // to  nie nastapi, bo strtok zwroci wczesniej 0
        printf("%s ",p);
        char* r;
        int i=(int)strtol(p,&r,10);
        if(tab[w][0]>=k){
          if(k){
            k*=2;
          }else k=1;
          tab[w]=(int*)realloc(tab[w],(k+1)*sizeof(int));
          if(!tab[w]){
            printf("brak pamieci!\n");
            return -5;
          }
        }
        tab[w][0]++;
        if(!*r){
          printf("w=%d, tab[%d][0]=%d tab[%d][%d]=%d\n",w,w,tab[w][0],w,tab[w][0],i);
          tab[w][tab[w][0]]=i;
        }else printf("bledny znak: %c\n",*r);
//      }else printf("linia pusta!\n");
      p=0;
    }
    printf("k=%d, tab[%d][0]=%d => ",k,w,tab[w][0]);
    if(k>tab[w][0]){
      k=tab[w][0];
      tab[w]=(int*)realloc(tab[w],(k+1)*sizeof(int));
    }
    printf("k=%d, tab[%d][0]=%d\n",k,w,tab[w][0]);
    w++;
  }
  fclose(f);

  printf("wa=%d  w=%d\n",wa,w);

  if(wa>w)tab=(int**)realloc(tab,(wa=w)*sizeof(int*));

  printf("wa=%d  w=%d\n\n========================\n\n",wa,w);

  w=0;
  while(w<wa){
    k=0;
    printf("%02d  %d => ",w+1,tab[w][0]);
    while(k<tab[w][0])printf("%d ",tab[w][++k]);
    printf("\n");
    w++;
  }

  while(wa--)free(tab[wa]);
  free(tab);

  return 0;
}

i alokowac wszystko dynamicznie ? masz zmienna 'wa' w ktorej trzymasz ilosc zaalokowanych wierszy. powiedzmy wartosc poczatkowa 0, wczytujesz w-ta linijke, sprawdzasz czy jest zaalokowana przestrzen na ta linie. jesli w>=wa (wlasciwie to w nigdy nie bedzie wieksze od wa, ale taki warunek jest bezpieczniejszy) to musisz zaalokowac nowa przestrzen, teraz rozmiar przestrzeni alokowanej zalezy od wa. jesli wa==0, to ustawiasz wa=1 i alokujesz jedna linijke, w inym wypadku alokujesz 2x wiecej niz bylo poprzednio (wa*=2), w ten sposob:

  1. nigdy nie zejdziesz ponizej 50% wypelnienia tablicy.
  2. skoro doszedles do takiej a nie innej liczby linii to prawdopodobienstwo ze w pliku jest drugie tyle linii jest duzo wieksze niz ze bedzie tylko jedna.
    dlatego szkoda czasu procesora i zasobow, nie realokuje sie pamieci "o jeden wiecej" tylko "2 razy wiecej"
    po zakonczeniu czytania zwalniasz nadmiar zaalokowanej pamieci

podobnie z alokacja kolumn, z ta roznica, ze alokujesz o komorke wiecej, komorka o zerowym indeksie przetrzymuje informacje o ilosci zapamietanych liczb.

0

Kod wygląda poprawnie (mi się nie podoba), ale pierwsze pytanie powinno brzmieć: C czy C++?

0

Może od początku...

Piszę program do rozwiązywania okładu równań. Muszę wczytać macierz główną o rozmiarze nxn a później macierz wyrazów wolnych o rozmiarze 1xn. Gdy odczytam z pliku ilość elementów w pierwszej linii będę wiedział że n linii to macierz główna a reszta to macierz wyrazów wolnych.

Chciałbym uniknąć podawania w pliku innych danych niż współczynników jak np wielkości danego wiersza.

Piszę w C++

0
int n = 0; //wymiar macierzy
string linia;
ifstream plik("macierz.txt");
getline(plik, linia);
istringstream iss(linia);
int tmp;
while(iss >> tmp) n++;
plik.seekg(0, ios::beg); //wracamy na poczatek pliku

i w zmiennej n masz wymiar macierzy, dalej możesz wczytywać kolejne komórki.

0
#include<sstream>
#include<fstream>
#include<vector>

typedef std::vector<double> Wektor;
typedef std::vector<Wektor> Macierz;

Wektor& wczytajWiersz(istream& input, Wektor& wiersz)
{
     std::string linia;
     wiersz.clear();

     if(std::getline(input,linia)) {
         std::istringstream dane(linia);
         double element;
         while(dane >> element)
               wiersz.push_back(element);
     }
     // if(!input.eof()) // pojawił się coś co nie było liczbą można zignorować, lub rzucić odpowiednim wyjątkiem

     return wiersz;
}

Macierz& wczytajMacierzKwadratowa(std::istream& input, Macierz& m)
{
    m.clear();
    Wektor wiersz;
    wczytajWiersz(input, wiersz);
    const int n = wiersz.count();

    if( n > 0 ) {
        m.push_back(wiersz);

        for(int i=1;i<n;++i) {
             m.push_back(wczytajWiersz(input, wiersz));
             if(wiersz.count()!=n) {
                   // coś zrobić z tym błędem
             }
        }
    }
    return m;
}

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