• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Obsługa plików C++

Object Storage Arubacloud
0 głosów
699 wizyt
pytanie zadane 25 grudnia 2019 w C i C++ przez kaminie318 Bywalec (2,070 p.)
#include <iostream>
#include <fstream>
#include<string>

using namespace std;

int main()
{
	cout << "Witaj w projekcie!"<<endl;
	fstream plik;
	int data, nr_miejsca;
	string symbol, lotniskoStartowe, lotniskoDocelowe, imie, nazwisko;

	plik.open("DaneLotu.txt", ios::in);

	plik >> symbol>> data >> lotniskoStartowe >> lotniskoDocelowe >> imie >> nazwisko >> nr_miejsca;

	cout << symbol <<"   "<< data<<"   "<<lotniskoStartowe<<"   "<<lotniskoDocelowe<<"   "<<imie<<"   "<<nazwisko<<"   "<<nr_miejsca;

	cin.get();

	plik.close();

	return 0;

}

Witam. Robię projekt zaliczeniowy na studia i mam pewiem problem. Mianowicie nie wiem jak pobrać całą datę z kropkami do konsoli.Proszę o pomoc lub jakiekolwiek naprowadzenie.Załączam kod  Pozdrawiam.

komentarz 26 grudnia 2019 przez j23 Mędrzec (194,920 p.)

@adrian17, 

Nie mówię że wx jest kompletnie zły, tylko że powstał dawno temu i ten bagaż historyczny jest czasem widoczny.

Jest niewiele starszy od Qt. wxTextFile::Close także nie musi wywoływać, bo w destruktorze wszystkie zasoby zostaną zwolnione. Nie widzę tutaj problemu ani bagażu historycznego.

komentarz 26 grudnia 2019 przez edwardkraweznik Dyskutant (9,930 p.)
to super :) bo wx to moja ulubiona biblioteka :)
komentarz 26 grudnia 2019 przez adrian17 Ekspert (345,160 p.)

Jest niewiele starszy od Qt. wxTextFile::Close także nie musi wywoływać, bo w destruktorze wszystkie zasoby zostaną zwolnione

Może czegoś nie rozumiem w dokumentacji?

https://docs.wxwidgets.org/3.0/classwx_text_file.html

virtual wxTextFile::~wxTextFile() virtual

Destructor does nothing.

bool wxTextFile::Close()

Closes the file and frees memory, "losing all changes".

Use Write() if you want to save them.

notice that the changes you make to the file will not be saved automatically; calling wxTextFile::Close or doing nothing discards them!

komentarz 26 grudnia 2019 przez j23 Mędrzec (194,920 p.)

Podstawowy błąd, który robisz, to to, że nie przeczytałeś, co ta klasa robi. To nie jest odpowiedź wxów na std::fstream:

Create and open it: this is done with either wxTextFile::Create or wxTextFile::Open function which opens the file (...), reads its contents in memory (in the case of wxTextFile::Open()) and closes it.

Czyli destruktor nie musi zamykać pliku, bo on już na starcie jest zamykany po załadowaniu zawartości do pamięci. Pamięć oczywiście też jest zwalniana.

komentarz 26 grudnia 2019 przez adrian17 Ekspert (345,160 p.)
Przeczytałem ten fragment, ale źle go zinterpretowałem :/ Ups. Przepraszam.

2 odpowiedzi

0 głosów
odpowiedź 25 grudnia 2019 przez adrian17 Ekspert (345,160 p.)

W kodzie masz

int data

Ale w pliku masz

23.12.2019

Co nie wygląda jak liczba całkowita ;)

Zamień typ zmiennej `data` na string i powinno ładnie zadziałać.

komentarz 25 grudnia 2019 przez kaminie318 Bywalec (2,070 p.)
Właśnie tu jest ten myk że nie mogę w projekcie używać żadnego ciągu cyfr jako stringi.Tak to już miałem fajną pętlę z eof na odczytanie danych z całego pliku, a niestety będę musiał jeszcze kombinować z pętlami potem jak czytać cały plik.
komentarz 25 grudnia 2019 przez niezalogowany
char kropka;

plik >> symbol>> dzien>>kropka>>miesiac>>kropka>>rok >> lotniskoStartowe >> lotniskoDocelowe >> imie >> nazwisko >> nr_miejsca;

ale lepiej struct data{} i przeciążyć operator
komentarz 26 grudnia 2019 przez kaminie318 Bywalec (2,070 p.)
W sumie spoko rozwiązanie ale bardzo karkołomne xd. Nie da się tego wykombinować inaczej ? Ale w każdym bądź razie bardzo dziękuję na pomysł z tą kropką .Jak na podstawie tych danych mam utworzyć listy pasażerów dla każdego lotu ? Wpadłem na pomysł z listą jednokierunkową,jednak nie za bardzo wiem jak się za to zabrać. Czy powinienem najpierw wczytać dane wszystkich pasażerów z pliku i jakoś to zapętlić czy jak ?
komentarz 26 grudnia 2019 przez niezalogowany

lepiej posłuchać mądrzejszych i nie wywarzać otwartych drzwi (mokrowski). i nie tworzyć własnych struktur i class na to co jest już zrobione (tm)

ale jak byś się nudził to taki prototypik

struct data {}; // co by nie było dat 30\36/21487
istream & operator >>(istream & in, data &d){}
struct record {};
istream & operator >>(istream & in, record & r){}

int policzRekordy (istream &) {} // policz '\n'

int main (){

.....
int size=policzRekordy(file);
vector <record> tab(size);
//lub record * tab =new record[size];

for(auto & x:tab){
file>>x;
}
// delete tab[];
}

 

komentarz 26 grudnia 2019 przez kaminie318 Bywalec (2,070 p.)
edycja 26 grudnia 2019 przez kaminie318
Vektory również odpadają. Muszę to robić za pomocą dynamicznych struktur danych :( Poza tym średnio rozumiem ten kod, wiele instrukcji i zapisów z którymi jeszcze nie miałem styczności :/
0 głosów
odpowiedź 26 grudnia 2019 przez mokrowski Mędrzec (155,460 p.)
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <optional>

struct Record {
	std::string iataCode;
	std::tm date;
	std::string departure;
	std::string arrival;
	std::string name;
	std::string surname;
	unsigned placeNumber;
};

std::optional<const Record> parse_record(const std::string& str) {
    std::optional<const Record> opt;
	Record record{};
	std::istringstream ss{str};

	ss >> record.iataCode
	   >> std::get_time(&(record.date), "%d.%m.%Y")
	   >> record.departure
	   >> record.arrival
	   >> record.name
	   >> record.surname
	   >> record.placeNumber;

    if(ss) {
        opt.emplace(record);
    }
    return opt;
}

void show_record(const Record& record) {
	std::cout << "IATA Code: " << record.iataCode << '\n'
	          << "Date:      " << std::put_time(&(record.date), "%d-%m-%Y") << '\n'
	          << "Departure: " << record.departure << '\n'
	          << "Arrivall:  " << record.arrival << '\n'
	          << "Name:      " << record.name << '\n'
	          << "Surname:   " << record.surname << '\n'
	          << "Place:     " << record.placeNumber << '\n';
}

int main() {
	std::ifstream file{"DaneLotu.txt"};
	if(!file) {
		std::cerr << "File open error!\n";
		return 1;
	}
	std::string line;
	std::getline(file, line);
	const auto record = parse_record(line);
	if(record) {
		show_record(*record);
	} else {
		std::cerr << "Record parse error!\n";
		return 2;
	}
}

Np. tak.. W formie "łopatologicznej" :)

komentarz 27 grudnia 2019 przez mokrowski Mędrzec (155,460 p.)

Nie tak:

    while ((!file.eof())) 

a tak:

    while (!file) 

i nie tak..

        if (record) {
            show_record(*record);
            cout << endl;
            _getch();
        }
        else {
            cerr << "Record parse error!\n";
            return 2;
        }

Już nie masz przypadku że będzie zwracany optional więc:

1. Nie ma "wyłuskania przez *" co robisz dla std::optional

2. Nie ma sekcji błędu parsowania bo parsowanie załamie się już w funkcji parsowania a nie w main(..)

tak więc:

        show_record(record);
        cout << '\n'; // Nie używaj bez potrzeby std::endl
        _getch(); // W VS jest tryb budowy debug który nie wymaga używania tej "protezy"

 

komentarz 27 grudnia 2019 przez kaminie318 Bywalec (2,070 p.)
edycja 27 grudnia 2019 przez kaminie318
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <optional>
#include<conio.h>
#include <cassert>

using namespace std;

struct Record {
	string symbol;
	tm data;
	string odlot;
	string przylot;
	string imie;
	string nazwisko;
	unsigned numerMiejsca;
};

Record parse_record(const string& str)
{
	Record record{};
	istringstream ss{ str };

	ss >> record.symbol
		>> get_time(&(record.data), "%d.%m.%Y")
		>> record.odlot
		>> record.przylot
		>> record.imie
		>> record.nazwisko
		>> record.numerMiejsca;

	if (!ss)
	{
		cout << "Bledny rekord danych!";
		assert(false);
	}

	return record;
}

void show_record(const Record& record) {
	cout << "Symbol Lotu: " << record.symbol << '\n'
		<< "Data:      " << put_time(&(record.data), "%d-%m-%Y") << '\n'
		<< "Odlot: " << record.odlot << '\n'
		<< "Przylot:  " << record.przylot << '\n'
		<< "Imie:      " << record.imie << '\n'
		<< "Nawisko:   " << record.nazwisko << '\n'
		<< "Miejsce:     " << record.numerMiejsca << '\n';
}

int main() {
	ifstream file{ "DaneLotu.txt" };
	if (!file) {
		cout << "Blad otwarcia pliku!\n";
		return 0;
	}
	while ((!file.eof()))
	{
		string line;
		getline(file, line);
		const auto record = parse_record(line);
		show_record(record);
		cout << '\n';
		_getch();
	}
	_getch();

}

Pozwoliłem sobie na kilka swoich poprawek (nie koniecznie dobrych) i mam kilka pytań:

1.Paradoksalnie while(!false) nie działa, a while ((!file.eof())) jak najbardziej. Co jest powodem?

2.Czy mogę zastąpić cerry coutami? Wiem, że cerr wyrzuca błąd na ekran ale czy nie da się zastąpić po prostu tego zwykłym coutem ?

3.W przypadku assert program powinien wyrzucić komunikat o błędzie i zakończyć działanie programu. Niestety u mnie program w tym momencie się zawiesza, stąd pytanie czy nie da się zastąpić tego po prostu exit(0) ?

4.Zacząłem analizować tą funkcję "Record parse_record(const string& str)" .Ona po prostu zwraca Record(strukture) a przyjmuje za argument str, czyli ten nasz przekonwertowany tekst na stringa za pomocą istringstream. 

5.Czy dobrze rozumiem funkcja get_time po prostu konwertuje znaki na stringa i rzuca wskaźnik na element struktury(stąd ta referencja) a drugi argument odpowiada za format czyli po prostu np. w ilu liczbach jest podany rok itp(tylko po co te procenty frown, zawsze muszą być przed symbolem jakiegoś znaku) . ?

komentarz 27 grudnia 2019 przez mokrowski Mędrzec (155,460 p.)

1, while(!false)

   ma być: while(!file)

2. Co do zasady strumień błędów powinien być oddzielony od strumienia normalnych danych. Oczywiście będzie działało jeśli zamienisz std::cerr na std::cout tylko ktoś kto będzie używał programu nie będzie mógł ich rozdzielić w skrypcie. To się często robi np w GNU/Linux (strumień o numerze 2 to std::cerr).

3. assert ma służyć do gwałtownego zakończenia programu ponieważ wystąpił błąd uniemożliwiający jego poprawne działanie. exit(0) wbrew pozorom nie jest (w większości przypadków) poprawnym zakończeniem programu. Nie wywołuje destruktorów obiektów. Na Twoim poziomie wiedzy, sugeruję zostawienie assert(...).

4 Tak.

5. Ta funkcja pobiera string z danymi w postaci czasu i konwertuje tenże na poprawny czas w strukturze std::tm. System dba by nie występowały tam daty spoza kalendarza, nie były możliwe niepoprawne formatowania itp. (np. 30.02.2019 to trochę data "niefajna"). Dlatego jest to lepsze niż samodzielne rozwiązywanie problemów roku przestępnego czy innych problemów formatowania których.. nie rozwiążesz łatwo. Data i czas to bardzo złożone zagadnienie.

 

komentarz 27 grudnia 2019 przez kaminie318 Bywalec (2,070 p.)

Przypomniałem sobie , że na uczelni wręcz zakazali używania exit, radzili bardziej trzymac się return 0, jednak program zawiesza mi się na w momencie assert i nie wiem jak rozwiązać ten problem omijając exit(0)frown Teraz chce utworzyć listy pasażerów dla każdego lotu, gdzie dla każdego lotu należy utworzyć oddzielny plik z listą pasażerów. Chciałbym zrobic to na liscie jednokierunkowej.Czy powinienem w strukturze Record robić wskaznik na następny element ? Czy robić nową strukturę ze wskaznikiem? Nie wiem jak to ogarnąć żeby było dobrze.

komentarz 27 grudnia 2019 przez kaminie318 Bywalec (2,070 p.)
edycja 28 grudnia 2019 przez kaminie318
#include <iostream>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <optional>
#include <conio.h>
#include <cassert>

using namespace std;

struct Record {
    string symbol;
    tm data;
    string odlot;
    string przylot;
    string imie;
    string nazwisko;
    unsigned numerMiejsca;
    Record* next;    // wskaźnik na następny element
};


void addFront(Record*& head)
{
    Record* temp = head;
    while(temp)
    {
        temp = new Record;
        temp->symbol;
        temp->data;
        temp->odlot;
        temp->przylot;
        temp->imie;
        temp->nazwisko;
        temp->numerMiejsca;
        temp->next = head;
        head = temp;
    }
}

void printList(Record*& head)
{
    Record* temp = head;
    while (temp)
    {
        cout << temp->symbol <<endl;
        cout << temp->data << endl;
        cout << temp->odlot << endl;
        cout << temp->przylot << endl;
        cout << temp->imie << endl;
        cout << temp->nazwisko << endl;
        cout << temp->numerMiejsca << endl;
        temp = temp->next;
    }
    cout << endl << endl;
}

void deleteList(Record*& head)
{
    Record* temp;
    while (head)
    {
        temp = head;
        cout << head->symbol << "\n";
        cout << head->data << "\n";
        cout << head->odlot << "\n";
        cout << head->przylot << "\n";
        cout << head->imie << "\n";
        cout << head->nazwisko << "\n";
        cout << head->numerMiejsca << "\n";
        head = head->next;
        if (head)
        {
            cout << head->symbol << "\n";
            cout << head->data << "\n";
            cout << head->odlot << "\n";
            cout << head->przylot << "\n";
            cout << head->imie << "\n";
            cout << head->nazwisko << "\n";
            cout << head->numerMiejsca << "\n";
        }
        delete temp;
    }
}


Record parse_record(const string& str)
{
    Record record{};                    //tworzenie obiektu struktury o nazwie record
    istringstream ss{ str };

    ss >> record.symbol
        >> get_time(&(record.data), "%d.%m.%Y")
        >> record.odlot
        >> record.przylot
        >> record.imie
        >> record.nazwisko
        >> record.numerMiejsca;

    if (!ss)
    {
        cerr << "Bledny rekord danych!";
        assert(0);
    }

    return record;
}

void show_record(const Record& record) {
    cout << "Symbol Lotu: " << record.symbol << '\n'
        << "Data:      " << put_time(&(record.data), "%d-%m-%Y") << '\n'
        << "Odlot: " << record.odlot << '\n'
        << "Przylot:  " << record.przylot << '\n'
        << "Imie:      " << record.imie << '\n'
        << "Nawisko:   " << record.nazwisko << '\n'
        << "Miejsce:     " << record.numerMiejsca << '\n';
}

int main() 
{
    ifstream file{ "DaneLotu.txt" };
    if (!file) {
        cout << "Blad otwarcia pliku!\n";
        return 0;
    }
    while (!false)
    {
        string line;
        getline(file, line);
        const auto record = parse_record(line);
        show_record(record);
        cout << '\n';
        _getch();
    }
    _getch();
    
    Record* head = nullptr;
    addFront(head);
    printList(head);
    deleteList(head);
    
    return 0;
}

Trochę podziałałem z tym kodem ale nie mam pojęcia czemu nie działa i jak to naprawić i czy to w ogóle dobra koncecja...

Podobne pytania

0 głosów
0 odpowiedzi 542 wizyt
pytanie zadane 21 grudnia 2021 w PHP przez Darth Vader Początkujący (270 p.)
0 głosów
0 odpowiedzi 605 wizyt
pytanie zadane 25 września 2017 w C i C++ przez B0nkers Początkujący (310 p.)
0 głosów
1 odpowiedź 1,222 wizyt
pytanie zadane 21 września 2015 w JavaScript przez Michał_J Nowicjusz (160 p.)

92,596 zapytań

141,445 odpowiedzi

319,719 komentarzy

61,980 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...