[C++] Zapis i odczyt txt

Woniak
Użytkownik
Użytkownik
Posty: 45
Rejestracja: 4 lis 2008, o 15:37
Płeć: Mężczyzna
Podziękował: 22 razy
Pomógł: 1 raz

[C++] Zapis i odczyt txt

Post autor: Woniak »

Witam, chcialbym dowiedziec sie, gdzie jest blad i czy to w ogóle jest dobrze?
Zapis do pliku dziala prawidlowo, natomiast odczytac go i zapisac do bazy nie jestem w stanie

Kod: Zaznacz cały

void ZAPIS(T_baza *baza, int rozmiar)
{
        FILE *baza_samochodow;
        baza_samochodow = fopen ("C:\baza_samochodow.txt", "wt");
 
        for (int i=0; i<rozmiar; i++) 
                fprintf(baza_samochodow, "%d %s %s %s %s %s %d 
", 
                baza[i].pozycja, 
                baza[i].nazwisko, 
                baza[i].imie, 
                baza[i].nr_rejestracyjny, 
                baza[i].marka, 
                baza[i].model, 
                baza[i].rok_produkcji);
        fclose(baza_samochodow);
 
        cout<<"Zapisano do C:\baza_samochodow.txt.
";
 
}
 
void ODCZYT(T_baza *baza, int rozm_bazy)
{
        FILE *baza_samochodow;
        baza[rozm_bazy];
        baza_samochodow = fopen ("C:\baza_samochodow.txt", "rt");
        for (int i=0; (!feof(baza_samochodow)) && i<rozm_bazy; i++) 
                fscanf(baza_samochodow, "%d %s %s %s %s %s %d", 
                &baza[i].pozycja, 
                &baza[i].nazwisko, 
                &baza[i].imie, 
                &baza[i].nr_rejestracyjny, 
                &baza[i].marka, 
                &baza[i].model, 
                &baza[i].rok_produkcji);
        fclose(baza_samochodow);
 
        cout<<"Odczytano.
";
} 
Ostatnio zmieniony 13 sty 2012, o 10:31 przez Afish, łącznie zmieniany 1 raz.
Powód: Poprawa wiadomości.
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++] Zapis i odczyt txt

Post autor: Afish »

Co miała robić ta linijka:

Kod: Zaznacz cały

baza[rozm_bazy];
Bo jeżeli zamysłem było utworzenie tablicy, to niestety jest to źle.
Woniak
Użytkownik
Użytkownik
Posty: 45
Rejestracja: 4 lis 2008, o 15:37
Płeć: Mężczyzna
Podziękował: 22 razy
Pomógł: 1 raz

[C++] Zapis i odczyt txt

Post autor: Woniak »

Tak, tak już wiem. Ale przed i po usunięciu różnicy w działaniu nie ma.

Jeszcze podam wywołanie:

Kod: Zaznacz cały

case 5: ZAPIS(baza, wpis);        break;
case 6: ODCZYT(baza, rozm_bazy);        break;
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++] Zapis i odczyt txt

Post autor: Afish »

Bo i być różnicy nie powinno. Pokaż cały program wraz z wywoływaniem, bo po fragmencie kodu nie jestem w stanie powiedzieć nic więcej.
Woniak
Użytkownik
Użytkownik
Posty: 45
Rejestracja: 4 lis 2008, o 15:37
Płeć: Mężczyzna
Podziękował: 22 razy
Pomógł: 1 raz

[C++] Zapis i odczyt txt

Post autor: Woniak »

Kod: Zaznacz cały

#include <stdafx.h>
#include <iostream>
#include <stdio.h>
using namespace std;

struct T_baza 
{
	int pozycja;
	char nazwisko[30];
	char imie[30];
	char nr_rejestracyjny[10];
	char marka[30];
	char model[30];
	int rok_produkcji;
};

void TWORZENIE(T_baza &baza, int pozycja)
{
	baza.pozycja=pozycja;
	cout<<"\npozycja nr:\t\t"<<baza.pozycja;
	cout<<"\nnazwisko:\t\t";			cin>>baza.nazwisko;
	cout<<"imie:\t\t\t";				cin>>baza.imie;
	cout<<"numer rejestracyjny:\t";		cin>>baza.nr_rejestracyjny;
	cout<<"marka:\t\t\t";				cin>>baza.marka;
	cout<<"model:\t\t\t";				cin>>baza.model;
	cout<<"rok produkcji:\t\t";			cin>>baza.rok_produkcji;
}

void WYSWIETLANIE(T_baza &baza)
{
	cout<<"\npozycja nr:\t\t"<<baza.pozycja;
	cout<<"\nnazwisko:\t\t"<<baza.nazwisko;
	cout<<"\nimie:\t\t\t"<<baza.imie;
	cout<<"\nnumer rejestracyjny:\t"<<baza.nr_rejestracyjny;
	cout<<"\nmarka:\t\t\t"<<baza.marka;
	cout<<"\nmodel:\t\t\t"<<baza.model;
	cout<<"\nrok produkcji:\t\t"<<baza.rok_produkcji;
	cout<<endl;
}

void USUWANIE(void)
{
}

void SORTOWANIE(T_baza *baza, int rozm_bazy, int wpis)
{
	(...)
}

void ZAPIS(T_baza *baza, int rozmiar)
{
	FILE *baza_samochodow;
	baza_samochodow = fopen ("C:\\baza_samochodow.txt", "wt");
	
	for (int i=0; i<rozmiar; i++) 
		fprintf(baza_samochodow, "%d %s %s %s %s %s %d \n", 
		baza[i].pozycja, 
		baza[i].nazwisko, 
		baza[i].imie, 
		baza[i].nr_rejestracyjny, 
		baza[i].marka, 
		baza[i].model, 
		baza[i].rok_produkcji);
	fclose(baza_samochodow);

	cout<<"Zapisano do C:\\baza_samochodow.txt.\n";

}

void ODCZYT(T_baza *baza, int rozm_bazy)
{
	FILE *baza_samochodow;
	baza_samochodow = fopen ("C:\\baza_samochodow.txt", "rt");
	for (int i=0; (!feof(baza_samochodow)) && i<rozm_bazy; i++) 
		fscanf(baza_samochodow, "%d %s %s %s %s %s %d", 
		&baza[i].pozycja, 
		&baza[i].nazwisko, 
		&baza[i].imie, 
		&baza[i].nr_rejestracyjny, 
		&baza[i].marka, 
		&baza[i].model, 
		&baza[i].rok_produkcji);
	fclose(baza_samochodow);

	cout<<"Odczytano.\n";
}

int main(int argc, char* argv[])
{
	int menu, rozm_bazy, wpis=0, usun;
	char koniec='n';

	cout<<"Podaj rozmiar bazy danych: ";
	cin>>rozm_bazy;
	cout<<endl;
		
	T_baza *baza=NULL;
	baza = new T_baza[rozm_bazy];

	do
	{
		system("cls");
		cout<<"BAZA SAMOCHODOW\n\n";
		cout<<"1.\tNowy wpis.\n";
		cout<<"2.\tWyswietlenie bazy.\n";
		cout<<"3.\tUsuniecie wpisu.\n";
		cout<<"4.\tSortowanie.\n";
		cout<<"5.\tZapis do *.txt.\n";
		cout<<"6.\tOdczyt z *.txt.\n";

		cout<<"WYBOR: ";
		cin>>menu;
		cout<<endl<<endl;

		switch (menu)
		{
			case 1:
				if (wpis<rozm_bazy)
				{
					cout<<"Nowy wpis: ("<<wpis+1<<"/"<<rozm_bazy<<")"<<endl;;
					TWORZENIE(baza[wpis], wpis+1);
					wpis++;
				}
				else cout<<"Baza przepelniona!";
			break;

			case 2:
				cout<<"Wyswietlenie bazy:\n";
				if (wpis==0) cout<<"Brak danych!";
				for (int i=0; i<wpis; i++)
				{
					WYSWIETLANIE(baza[i]);
				}
			break;

			case 3:
				cout<<"Usuniecie wpisu:\n";
				cout<<"Ktora pozycje chcesz usunac?\n";
				cin>>usun;
			break;

			case 4: SORTOWANIE(baza, rozm_bazy, wpis);		break;
			case 5: ZAPIS(baza, wpis);	break;
			case 6: ODCZYT(baza, rozm_bazy);	break;
			default: cout<<"Brak takiej opcji w menu.\n";	break;
		}
		cout<<"\n\nZakonczyc (t\\n)? ";
		cin>>koniec;
		cout<<endl<<endl;
	}
	while (koniec!='t');

	delete[]baza;

	system("PAUSE");
	return 0;
}
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++] Zapis i odczyt txt

Post autor: Afish »

Po wczytaniu nie zmieniasz wartości zmiennej wpis. Poza tym program będzie wczytywał o jeden raz za dużo i przez to otrzymasz trochę śmieci.
Woniak
Użytkownik
Użytkownik
Posty: 45
Rejestracja: 4 lis 2008, o 15:37
Płeć: Mężczyzna
Podziękował: 22 razy
Pomógł: 1 raz

[C++] Zapis i odczyt txt

Post autor: Woniak »

Dzięki wielkie! Wszystko przez to, że zapomniałem zwiększać rozmiaru zapisanej bazy :)

Kod: Zaznacz cały

int ODCZYT(T_baza *baza, int rozm_bazy)
{
	int wpis=0;

	FILE *baza_samochodow;
	baza_samochodow = fopen ("C:\\baza_samochodow.txt", "rt");
	for (int i=0; (!feof(baza_samochodow)) && i<rozm_bazy; i++)
	{
		fscanf(baza_samochodow, "%d %s %s %s %s %s %d", 
		&baza[i].pozycja, 
		&baza[i].nazwisko, 
		&baza[i].imie, 
		&baza[i].nr_rejestracyjny, 
		&baza[i].marka, 
		&baza[i].model, 
		&baza[i].rok_produkcji);

		wpis++;
	}
	fclose(baza_samochodow);

	cout<<"Odczytano.\n";
	return wpis;
}

Kod: Zaznacz cały

case 6: wpis=ODCZYT(baza, rozm_bazy); break;
Faktycznie, pojawiają się śmieci, ale nie widzę przyczyny. Gdzie jest fragment powodujący, że 'wpis' jest za duży?
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++] Zapis i odczyt txt

Post autor: Afish »

Problem jest tu:

Kod: Zaznacz cały

fprintf(baza_samochodow, "%d %s %s %s %s %s %d 
",
i tu:

Kod: Zaznacz cały

 for (int i=0; (!feof(baza_samochodow)) && i<rozm_bazy; i++)
Zapisujesz jeden wpis i dajesz na końcu znak nowej linii. Wobec tego po każdym odczytaniu wpisu w pliku coś jeszcze jest (jakaś spacja i znak nowej linii), więc funkcja feof zwróci false, nastąpi kolejna iteracja pętli i będziesz próbował odczytać za dużo danych. Jak to rozwiązać? fscanf zwraca liczbę wczytanych danych, możesz to wykorzystać.
Kolejna kwestia, o której nie napisałem wcześniej: jeżeli to jest C++, to załączaj cstdio, a nie stdio.h (chyba że masz tak stary kompilator, który nie ma nowego nagłówka). Ponadto nie za bardzo rozumiem dlaczego mieszasz cout z fprintf. Jeżeli już korzystasz ze strumieni, to chyba lepiej byłoby użyć ifstream i ofstream, ale to oczywiście nie jest żaden błąd. Kolejną sprawą jest system("pause") na końcu programu - niektórzy zjedzą Cię za to ;) Lepiej użyć cin.get(), jest przenośne i nie odwołuje się do zewnętrznego programu. Ponadto ponieważ masz w strukturze ograniczone miejsce na dane (np. 30 znaków na imię), to warto zabezpieczyć się przed wprowadzeniem dłuższego stringa.
Woniak
Użytkownik
Użytkownik
Posty: 45
Rejestracja: 4 lis 2008, o 15:37
Płeć: Mężczyzna
Podziękował: 22 razy
Pomógł: 1 raz

[C++] Zapis i odczyt txt

Post autor: Woniak »

Mam jeszcze pytanie dot. teorii :)
Ponieważ bd musiał odpowiadać z kodu a mam pewien problem ze zrozumieniem wskaźników.
Czemu dane funkcje 'wymagają' (przynajmniej w takim zapisie jak u mnie) '*' lub '&' (w sensie czemu dana funkcja chce taki operator a nie inny):

Dokładnie chodzi mi o T_baza &baza:

Kod: Zaznacz cały

void TWORZENIE(T_baza &baza, int pozycja)
void WYSWIETLANIE(T_baza &baza)
T_baza *baza

Kod: Zaznacz cały

void SORTOWANIE(T_baza *baza, int wpis)
void ZAPIS(T_baza *baza, int rozmiar)
int ODCZYT(T_baza *baza, int rozm_bazy)
Afish
Moderator
Moderator
Posty: 2828
Rejestracja: 15 cze 2008, o 15:45
Płeć: Mężczyzna
Lokalizacja: Seattle, WA
Podziękował: 3 razy
Pomógł: 356 razy

[C++] Zapis i odczyt txt

Post autor: Afish »

Woniak pisze:

Kod: Zaznacz cały

void TWORZENIE(T_baza &baza, int pozycja)
void WYSWIETLANIE(T_baza &baza)
Gdybyś do funkcji tworzącej przekazał T_baza baza, to funkcja otrzymałaby kopię struktury, która zniknęłaby po wyjściu z funkcji. Ponieważ nam zależy na zmodyfikowaniu oryginalnej struktury, musimy przekazać ją przez referencję.
Wyświetlanie podobnie, aczkolwiek gdybyś przekazał przez kopię, to nie stałoby się nic złego, bo nie modyfikujemy struktury - stracilibyśmy tylko na szybkości.
Woniak pisze:

Kod: Zaznacz cały

void SORTOWANIE(T_baza *baza, int wpis)
void ZAPIS(T_baza *baza, int rozmiar)
int ODCZYT(T_baza *baza, int rozm_bazy)
Do tych funkcji chcemy przekazać tablicę, którą wypiszemy. Gdybyśmy przekazali T_baza baza, to przekazalibyśmy jeden element (i to kopiując go), gdybyśmy przekazali T_baza& baza, to przekazalibyśmy jeden element (ale tym razem nie odbyłoby się kopiowanie). My przekazujemy T_baza* baza, co jest wskaźnikiem na jeden element, ale wykorzystując własności tablic (czyli ciągłe uporządkowanie w pamięci) możemy odnaleźć wszystkie elementy (pytanie-zagadka: czy dałoby się to zrobić, gdybyśmy przekazali T_baza& baza ?).
ODPOWIEDZ