Odczyt zawartosci pliku tekstowego do struktury i zapis do pliku binarnego

0

Witam,
Mam problem z poprawnym zapisem tekstu z pliku tekstowego do binarnego.

struct ksiazka{
         char tytul[256];
};

struct lista{
        struct lista *next;
        struct ksiazka ks;
};

void zapisz(int n){
      FILE *plik, *plik1;
      struct ksiazka ks; 
      int i=0;
      plik = fopen("spis_ksiazek.bin","wb");
      plik1 = fopen("spis_kiazek.txt", "r");
        system("CLS");
      
      while(i<n){
      
      fread(&ks, sizeof(ks), 1, plik1);
      fwrite(&ks,sizeof(ks),1,plik);
      
      i++;
      }
      fclose(plik);
      fclose(plik1);
      printf("\n Zapisano do pliku... \n");
      getch();

      
}

Co robię źle?

0

A czym u ciebie różni się zapis tekstowy od binarnego ?

0

Rodzajem otwierania pliku. Do zapisu binarnego jest "wb", do zapisu tekstowego było by samo "w". Różnią się czymś jeszcze?

0

Co robię źle?

Nie wiemy. Nie opisałeś w ogóle na czym polega problem: czy jest to błąd kompilacji, czy plik się nie zapisuje, czy się zapisuje ale źle, czy… czy… czy…
Zmuszasz wszystkich do wczytania się dokładnie w program, odpalania kompilatora, zastanawiania się CO w ogóle chciałeś osiągnąć, i CO tu w ogóle może pójść źle.

Napisz z czym masz problem.

0
Azarien napisał(a)

Co robię źle?

Nie wiemy. Nie opisałeś w ogóle na czym polega problem: czy jest to błąd kompilacji, czy plik się nie zapisuje, czy się zapisuje ale źle, czy… czy… czy…
Zmuszasz wszystkich do wczytania się dokładnie w program, odpalania kompilatora, zastanawiania się CO w ogóle chciałeś osiągnąć, i CO tu w ogóle może pójść źle.

Napisz z czym masz problem.

Wszystko się kompiluje, tylko źle zapisuje do pliku binarnego. Jak później odczytuje ten plik binarny do listy jednokierunkowej to wczytują się puste elementy (tj. bez nazwy).

0

Nie wiemy jak wygląda plik spis_kiazek.txt

0
Azarien napisał(a)

Nie wiemy jak wygląda plik spis_kiazek.txt

Dodałem spis_ksiazek.txt w załączniku

@Edit

Omg już wiem co źle miałem. Źle wpisałem nazwe pliku do odczytu(miałem spis_kiazek.txt, a nie spis_ksiazek.txt)... teraz już działa, ale dalej nie tak jak powinno. Do jednego rekordu wczytuje parę linijek z pliku tekstowego zamiast jednej(dokładnie 5 albo 6). Pobawię się trochę z tym, może uda mi się to naprawić.

@edit1

Chyba mam coś źle z zapisem do pliku binarnego, bo jak otwieram stworzony plik binarny notatnikiem to widać w nim normalny tekst;/ Ma ktoś jakiś pomysł jak rozwiązać ten problem?

0

Podpowiedź już masz w postaci pytania: - "Czym się różni zapis binarny od tekstowego?".
Pytanie nie dotyczy tego jak to otwierasz (wszak binarnie można zapisać/odczytać prawie w każdym języku) a dotyczy tego jak to wygląda w pliku.
Dopóki nie znajdziesz odpowiedzi na to pytanie, to nie napiszesz tego poprawnie.

0

Moge się wbić tu z problemem drobnym?
chodzi mi o zmiane flag formatowania jak ktos nie wpisze liczby...

//uzycie w programie:
...
if(p_tab = pob_tab(licz_g, SIZ) ==false){ 									//sprawdz poprawnosc danych				                
 cout << "Twoje nowe liczby, postaraj sie nie robic wiecej bledow\n";
 getch();
 wyp_tab(licz_k, SIZ);
 pob_tab(licz_g, SIZ);}
else if(p_tab==true){
...
//kod funkcji
bool pob_tab(int tab[], int max){
      cout << "Wpisuj po 2 cyfry i oddzielaj spacja od kolejnych: \n" << endl;
	  for(int i=0;i< max; i++)
	 {
	  cin >> tab[i];		  
	  if(cin.fail())
	  { cout << "Odczytuje tylko liczby, sprobuj jeszcze raz! \n" << endl;
	  cin.clear();
	  return false;
	  }}
return true;
	   }
0

Do if(cin.fail()) program nigdy nie wejdzie, ponieważ jeżeli wczytanie się nie uda to pętla się skończy ponieważ cin>>tab... masz w warunku.
do czyszczenia wszystkich flag wystarczy cin.clear();

0

Daj może lepiej warunek
if(!cin) ...

0

poprawny snip czytania z cin, z założeniem że coś może nie wyjść wygląda tak:

cin >> cośtam
if(cin.fail())
{
zrob cos zeby naprawic sytuacje
cin.clear();
jakos zdobadź poprawną wartość na "costam"
}

w kontekście czytania danych od uzytkownika, może np. wyglądać to tak:

int liczba;
while(true)
{
    cin >> liczba;
    if(cin.fail())
    {
        cout << "Hejze. Miala to byc liczba. Podaj jeszcze raz:" << endl;
        cin.clear();  // czystka flag, aby operacje na strumieniu zaczely znowu funkcjonowac
        cin.ignore(numeric_limits<streamsize>::max(), '\n'); // pominiecie z wejscia wszystkiego, az do napotkania nowej linii
    }
    break;
}

zamiast przydlugiej linijki z ignore, mozesz (jesli zalozysz buforowane wejscie) probowac uzyc cin.flush, ale tylko ignore-do-konca-linii da Ci absolutna pewnosc, ze PO jego zakonczeniu, faktycznie "bedziesz" w linii nastepnej. flush nie daje takiej gwarancji, tylko "dużą pewność".

edit: ach, napisalem literalem, zeby bylo "dobitniej", a zapomniałem o MAC'ach.. oczywiscie, '\n' to tylko na linux i windows, a na MAC'ach, '\r'. ew. odbiedy, zamiast ignore mozesz machnac getline, ale po co to "buforowac" skoro tylko chcesz "przewinac"

0

13th: if ( !cin )
jest tożsame z if(cin.good())
i nie jest tym samym co if (cin.fail())
zajrzyj na CPP-FAQ, tam to bylo ładnie wyjasnione, o ile dobrze pamietam.
różnica tkwi w traktowaniu INNYCH flag bledów niz tylko prostego 'błędu konwersji', chocby, EOF.

0

sorry, widac zdążyłeś znow okomentować, zanim ja zdazylem przepisac komentarz na normalny post..

quetzalcoatl napisał(a)

nie bredzi, tylko pisząc szybko zapomnialem !'a. A to na co wskazuje w poście, to fakt, że !good != fail

Iostreamy sa pisane tak, aby program mógł abstrahowac od tego z czego czyta. Nawet w praktyce, każdy błąd może powstać wszędzie. Nawet user interaktywny może wysłać Ci EOFa. Jeżeli nie chcesz "uczyc" się trzydziestu sposobow czytania danych ze strumienia, na trzydziesci okazji użyć, prawidlowy jest tylko jeden, poniewaz przy jesli testowanie cin.good z powodu INNEJ flagi niż fail, to bardzo szybko moze sie okazac, ze ignore zawiesi Ci program, albo że pętla ciagle nawracajaca po clear' nigdy sie nie zakonczy..

Żeby było śmieszniej, ten jedyny-dobry, to też nie całkiem ten który podalem. przyklad który podalem zaklada, że dobre dane kiedys w koncu przyjdą, co w przypadku EOF'a skonczy się zerwaniem petli i osobliwością w "liczba". Jednak w kontekscie samego czytania wartosci z czyszczeniem strumienia, wnętrzne while'a jest poprawne, while stanowi tylko ułomny sposob na "zdobycie innej wartosci dla zmiennej"

0

Ok, wygrałeś - zmusiłeś mnie do wyszukania, czemu w mojej dziurawej pamięci kołacze się, że "lepiej używać FAIL niż GOOD".

http://www.horstmann.com/cpp/pitfalls.html
sekcja "Stream pitfalls"

Btw. to przy okazji wskazuje, że w moim:

13th: if ( !cin )
jest tożsame z if(cin.good())
i nie jest tym samym co if (cin.fail())

nie "zapomniałem ! przy good", ale że pokreciłem znaczenie opvoid* na stream: ono jest równe " ! fail() " a nie " good() ", co tym bardziej pokazuje, ze good nie jest zbyt dobrym wyborem.

0
void zapisz(int n){
      FILE *plik, *plik1; 
      int i=0, j=0;
      plik = fopen("spis_ksiazek.bin","wb");
      plik1 = fopen("spis_ksiazek.txt", "r");
        system("CLS");
        char tytul[100];
      
      while(i<n){
      
          while(feof(plik1)==0){
              fscanf(plik1, "%s", &tytul[j]);
              j++;
          }
                            
      fwrite(&tytul,100 ,1,plik);
 
      i++;
      }
      fclose(plik);
      fclose(plik1);
      printf("\n Zapisano do pliku... \n");
      getch();
 
 
}

Próbuje zczytywać literka po literce tytuły z pliku wierszami tj. zczytywanie jednego tytułu kończy się jak skończy się dany wiersz w pliku tekstowym i następnie zapisuje ten tytuł w pliku binarnym. To co zrobiłem nie działa, jak to powinienem poprawić??

0

Dobra trochę zmodyfikowałem moją funkcję i tearz mam następujący problem: do pliku binarnego zapisuje mi tylko pierwszy wiersz z pliku tekstowego (tzn. tyle ile elementów na się zapisać to się zapisuje, ale zapisuje się tylko pierwszy wiersz z pliku tekstowego. Co tu jest nie tak??

struct ksiazka{
         char tytul[256];
};

struct lista{
        struct lista *next;
        struct ksiazka ks;
};
void zapisz(int n){
      FILE *plik, *plik1;
      int i=0, j=0;
      plik = fopen("spis_ksiazek.bin","wb");
      plik1 = fopen("spis_ksiazek1.txt", "r");
      struct ksiazka ks;
      char *tytul=malloc(sizeof(char)*n*256);
      int k;
      ///wczytwanie z pliku tekstowego do tablicy
     while(i<n && (feof(plik1)==0)){
     fscanf(plik1, "%[^\n]\n", &tytul[i*256]);
    
     i++;
     }
     //wypisanie elemetnow zapisywanych do pliku
     for (j=0;j<n;j++){
          for (k=0;k<256;k++)  printf("%c",tytul[j*256+k]);
          printf("\n");
          }
          
         //zapis do struktury, a nastepnie do pliku binarnego 
         for (j=0;j<n;j++){
          for (k=0;k<256;k++){
                         ks.tytul[k]=tytul[i*256+k];;
                          strcpy(ks.tytul,tytul);
                          fwrite(&ks,sizeof(ks),1,plik);
           }
          }
          printf("\n");
              
          
      fclose(plik);
      fclose(plik1);
      printf("\n Zapisano do pliku... \n");
      getch();
 
 
}   
1
Aras napisał(a)
        //zapis do struktury, a nastepnie do pliku binarnego 
         for (j=0;j<n;j++){                                // A
          for (k=0;k<256;k++){                         // B
                         ks.tytul[k]=tytul[i*256+k];       // C
                          strcpy(ks.tytul,tytul);               // D
                          fwrite(&ks,sizeof(ks),1,plik);      // E
           }
          }

B+C tworzy mniej-wiecej prawidłowe kopiowanie tytułu z ''tytuł" do struktury
A+B+C tworzy mniej-wiecej prawidłowe kopiowanie wszystkich tytułów do struktury
A+D tworzy bardzo NIEprawidłowe kopiowanie losowego (od pierwszy do dowolny dalszy) ciągu tytułów do kolejnych struktur
A+E tworzy mniej-wiecej prawidłowe zapisywanye wszystkich struktur do pliku
C+D tworzy dziwaczną duplikację
A+B+D tworzy idiotyczne kopiowanie kazdego tytuły 256 razy w to samo miejsce
A+B+E tworzy idiotyczne zapisywanie kazdej struktury 256 razy pod rząd

a A+B+C+D+E wskazuje nieład, "strzelanie a nuż się uda", pomieszanie kodu z kilku prób, i/lub złe postawienie } zamykającego pętlę

przemyśl układ pętli i to co się w nich dzieje. zdecyduj się czy chcesz kopiowac recznie (B+C) czy poprzez strcpy (D). Jesli to drugie, to je napraw - "tytuł" to jest wiele tytułów, skad strcpy ma wiedziec ktory kopiowac?

0

Teraz to mi kopiuje jakieś chińskie znaczki do pliku binarnego;/ Wywaliłem to strcpy i ręcznie kopiuję do struktury

for (j=0;j<n;j++){
              
          for (k=0;k<256;k++){
                         ks.tytul[k]=tytul[i*256+k];;
                          //strcpy(ks.tytul,tytul);
                                  
           }
                         fwrite(&ks,sizeof(ks),1,plik);   
          }
0

Bo zapisujesz całą strukturę do której poprzednie kopiujesz nie wiadomo co nie wiadomo skąd.

0

ehh jak zwykle diabeł tkwi w szczegółach: w drugiej petli for zamiast j mialem i. Wszystko już ładnie śmiga, dzięki za pomoc

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