Jak korzystać z plików?

0

Cześć
Na wstępie - pisałam w C++ kilka dobrych lat temu, wtedy ostatecznie skorzystałam z funkcji dostępu do plików żywcem wziętych z C. Obecnie chcę pisać czysto w C++... 'botak'.
Problem: nie wiem jak korzystać z plików: Dawno temu jak się uczyłam pisać to nauczyłam sie korzystać z try catch i łapania wyjątków, tak jak tu:

bool fileexists(string nazwapliku) {
       ifstream plik;
       try {
               plik.open(nazwapliku, ios::in);
               if(plik.good()) {
                        plik.close();
                        return(true);
               } else { return(false);}
        } catch (exception& e) {
               cout << e.what() << endl;
               return(false);
        }
}

Ale na necie znalazłam coś takiego:

if(plik.good()) {rób swoje}
else
  {rób coś innego}

To drugie rozwiązanie nie pozwala na wyłapanie nic?

Kolejna sprawa - zrobiłam się ciekawska i muszę wiedzieć CO robi każde polecenie. A wiec zapisuję sobie coś do pliku:

pwyj.write((char*)&znak,1);

I czytam:

pwej.read((char*)&znak,1);

Dlaczego definiując wskaźnik korzystam z typu i po co to robić? Co tu porabia "(char*)" właściwie? Na co mi adres &znak ? (dobrze rozumiem, żę to wskazuje adres zmiennej do/z której ma być pobrana wartość? 1 jak rozumiem to wielkość przesyłanej zmiennej, ok.

1

Co do pierwszego pytania, to w dokumentacji napisano jasne i wyraźnie
Co do drugiego ..
metody read i write przyjmują char* oraz ile bajtów od tego miejsca czytać/pisać.
Więc pobieramy adres tego znaku w pamięci i odczytujemy/zapisujemy jeden znak.
W przypadku jeżeli znak ma typ char konwersja na (char*) jest zbędna.

0

Dzieki za odpowiedź na II pytanie, jednak nadal mam wątpliwości co do I.
Gdybym znalazła odpowiedź na I pytanie to bym nie pytała. Poza tym interesuje mnie zdanie osób, które w C++ piszą na co dzień i wiedzą z doświadczenia z czego warto i należy korzystać.

0

http://www.cplusplus.com/reference/fstream/ifstream/open/

Return Value
none
If the function fails to open a file, the failbit state flag is set for the stream (which may throw ios_base::failure if that state flag was registered using member exceptions).

Exception safety
Basic guarantee: if an exception is thrown, the stream is in a valid state.
It throws an exception of member type failure if the function fails (setting the failbit state flag) and member exceptions was set to throw for that state.

0

BTW C++17 ma już gotową funkcję do sprawdzania czy plik istnieje -> std::filesystem::exists

0

ja wrzucę tutaj swój kod na działaniu na plikach. Nie pamiętam czy mam funkcję sprawdzającą czy plik istnieje ale na pewno jest odczyt/zapis

plik zbiornik.h

#ifndef ZBIORNIK_H
#define ZBIORNIK_H

class zbiornik
{
private:
    float pojemnosc_zbiornika, poprzedni_stan_licznika, obecny_stan_licznika;
    float ilosc_wody, pobierz, jaki_jest_stan_wody_zbiornika;
    //bool zawor1, zawor2;

    int stan_wody_w_zbiorniku ();
    void napelnij_zbiornik ();
    int licznik ();
    int zapamietaj_stany();

public:
    //float pojemnosc_zbiornika;
    int pobierz_wode_ze_zbiornika(float);
};

#endif // ZBIORNIK_H

plik zbiornik.cpp

#include <fstream>
#include <string.h>
#include <stdlib.h>
#include "zbiornik.h"
#include <iostream>

using namespace std;

int zbiornik::pobierz_wode_ze_zbiornika(float pobieraj)
{
    pobierz = pobieraj;
    pojemnosc_zbiornika = 100.0f; /*litrów*/

    if (pobierz > pojemnosc_zbiornika)
    {
        cout << "Nie można wybrać większej ilości wody niż pojemność zbiornika" << endl;
        cout << "wylewam MAX " << pojemnosc_zbiornika << " litrów" << endl;
        cout << endl;
        pobierz_wode_ze_zbiornika(pojemnosc_zbiornika);
        cout << endl;
    }

    /*else if (jaki_jest_stan_wody_zbiornika < pobierz)
    {
        cout << "Wylewam " << jaki_jest_stan_wody_zbiornika << " litrów";
        cout << endl;
        pobierz_wode_ze_zbiornika(jaki_jest_stan_wody_zbiornika);
        cout << endl;
    }*/

    else if (pobierz < 0)
    {
        cout << "Nie można pobrać takiej ilości wody" << endl;
    }

    else
    {
    //ile wody zostało w zbiorniku po wylaniu przez użytkownika
        ilosc_wody = pojemnosc_zbiornika - pobierz;

        zapamietaj_stany();
    }

    return ilosc_wody;
}

inline int zbiornik::licznik()
{
    //zliczanie ile wybrano wody
    this->obecny_stan_licznika = this->poprzedni_stan_licznika + this->pobierz;

    return this->obecny_stan_licznika;
}

inline int zbiornik::stan_wody_w_zbiorniku()
{
    //obliczanie ile zostało wody w zbiorniku
    this->jaki_jest_stan_wody_zbiornika = this->ilosc_wody - this->pobierz;

    return this->jaki_jest_stan_wody_zbiornika;
}

int zbiornik::zapamietaj_stany()
{
    fstream wczytaj_licznik_txt, wczytaj_stan_zbiornika_txt;
    ofstream zapisz_licznik_txt, zapisz_stan_zbiornika_txt;

    wczytaj_licznik_txt.open("licznik.txt", ios_base::out | ios_base::in);

    //wczytywanie stanu licznika i zapisywanie stanu licznika
    if (wczytaj_licznik_txt.is_open() == true)
    {
        string wczytaj_stan_licznika_z_pliku;
        getline(wczytaj_licznik_txt, wczytaj_stan_licznika_z_pliku);

        cout << "stan licznika - " << wczytaj_stan_licznika_z_pliku << endl;

        float conversion = atof(wczytaj_stan_licznika_z_pliku.c_str());

        poprzedni_stan_licznika = conversion;

        licznik();

        cout << "stan licznika po wylaniu " << pobierz << " litrów wody " << obecny_stan_licznika << endl;

        zapisz_licznik_txt.open("licznik.txt", ios_base::out | ios_base::in | ios_base::trunc);
        zapisz_licznik_txt << obecny_stan_licznika;

        cout << endl;

        wczytaj_licznik_txt.close();
        zapisz_licznik_txt.close();
    }

    else
    {
        cout << "Błąd otwarcia pliku - licznik.txt" << endl;
    }

        wczytaj_stan_zbiornika_txt.open("stan.txt", ios_base::out | ios_base::in);

    //wczytywanie stanu zbiornika i zapisywanie stanu zbiornika

    if (wczytaj_stan_zbiornika_txt.is_open() == true)
    {
        string wczytaj_stan_zbiornika_z_pliku;
        getline(wczytaj_stan_zbiornika_txt, wczytaj_stan_zbiornika_z_pliku);

        cout << "stan zbiornika - " << wczytaj_stan_zbiornika_z_pliku << endl;

        float conversion = atof(wczytaj_stan_zbiornika_z_pliku.c_str());

        ilosc_wody = conversion;

        stan_wody_w_zbiorniku();

        cout << "stan wody w zbiorniku po wylaniu - " << pobierz << " litrów wody " << jaki_jest_stan_wody_zbiornika << endl;

        zapisz_stan_zbiornika_txt.open("stan.txt", ios_base::in | ios_base::out | ios_base::trunc);
        zapisz_stan_zbiornika_txt << jaki_jest_stan_wody_zbiornika;

        wczytaj_stan_zbiornika_txt.close();
        zapisz_stan_zbiornika_txt.close();

        napelnij_zbiornik();
    }

    else
    {
        cout << "Błąd otwarcia pliku - stan.txt" << endl;
    }

return 1;
}

void zbiornik::napelnij_zbiornik()
{
    if (jaki_jest_stan_wody_zbiornika <= 20)
    {
        cout << endl;
        cout << "Napelniam zbiornik" << endl;

        ofstream napelnij;
        napelnij.open("stan.txt", ios_base::out | ios_base::in | ios_base::trunc);
        napelnij << pojemnosc_zbiornika;

        napelnij.close();
    }

    else
    {
        cout << endl;
        cout << "Zbiornik jest pełny" << endl;
    }
}

plik main.cpp

#include <iostream>
#include "zbiornik.h"

using namespace std;

int main ()
{
    zbiornik *podaj_ile_chcesz_wody;
    cout << "Ile chcesz pobrac wody ?" << endl;
    float ile;
    cin >> ile;
    //podaj_ile_chcesz_wody.pobierz_wode_ze_zbiornika(ile);
    podaj_ile_chcesz_wody = new zbiornik();
    podaj_ile_chcesz_wody->pobierz_wode_ze_zbiornika(ile);
}

Sądzę, że może to być dla ciebie bardzo pomocne

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