Formatowanie danych z pliku tekstowego

0

Chciałbym napisać program który pobierze mi z pliku dane i zapisze je do nowego pliku z odpowiednim formatowaniem. W jaki sposób mogę zrobić takie formatowanie?
plik z danymi:

12 95.0 krzeslo
2 145.34 stol plastikowy
5 57.23 parasol ogrodowy
9 333.5 stol drewniany
135 7.0 pilka plazowa
3 49.99 stół z połamanymi
2 12.2 koc ratunkowy
4 25.05 woda gazowana
5 199.99 krzeslo skladane

I tak chciałbym sformatować dane i zapisać w pliku txt

1 krzeslo.................. 12 x 95.00 zł 1140.00 zł
2 stol plastikowy.......... 2 x 145.34 zł 290.68 zł
3 parasol ogrodowy......... 5 x 57.23 zł 286.15 zł
4 stol drewniany........... 9 x 333.50 zł 3001.50 zł
5 pilka plazowa............135 x 7.00 zł 945.00 zł
-----------------------------------------------------------
Razem 5663.33 zł
gdzie każda linijka sformatowana jest wg następującego wzorca:
         1         2         3         4         5         6
123456789012345678901234567890123456789012345678901234567890123456789
5 pilka plazowa............135 x 7.00 zł 945.00 zł
---------------------------------------------------------------------
Razem 5663.33 zł

Program odczytuje dane z pliku i zapisuje go do nowego:


#include <iostream>
#include <cstdlib>
#include <fstream>
#include <string>
#include <limits>

using namespace std;

int main()
   {
string NazwaPliku;
    cout << "Podaj nazwe pliku wejsciowego: "<< endl;
    cin >> NazwaPliku;

    fstream plikDoOdczytu;
    plikDoOdczytu.open( NazwaPliku.c_str(), ios::in );
    if(plikDoOdczytu.good()==false)
    cout<<"Nie mozna otworzyc pliku";
        string linia;     // Zmienna do przechowywania odczytanych wierszy tekstu
        int ilosc;
        double cena;
        fstream ladne;
        ladne.open( "ladne.txt", ios::out );
        while(!plikDoOdczytu.eof()){
        getline( plikDoOdczytu, linia);
        ladne<<linia<<"\n";
         }
       ladne.close();
return 0;
}
0

Dla pliku .txt:

12 95.0 krzeslo
2 145.34 stol
5 57.23 parasol
9 333.5 stolik
135 7.0 pilka
3 49.99 biurko
2 12.2 koc
4 25.05 woda
5 199.99 krzeslo

(jedno-wyrazowe nazwy przedmiotów)

#include <iostream>
#include <fstream>
#include <string>

#define DOTS_NUMBER 20

int main()
{
    std::string filename;
    std::cin >> filename;
    std::ifstream ist{ filename };
    if (ist) {
        std::ofstream ost{ "ladne.txt" };
        if (ost) {
            std::string name{};
            int i = 1; // line counter
            int quantity = 0;
            double price = 0.0;
            double total = 0.0;
            while (ist >> quantity >> price >> name) {
                ost << i++ << " " << name;
                for (int k = name.size(); k < DOTS_NUMBER; k++)
                    ost << ".";
                ost << " " << quantity << " x " << price << " zl " << quantity * price << " zl" << std::endl;
                total += price * quantity;
            }
            ost << "Razem: " << total << " zl";
        }
    }
    return 0;
}

Dasz radę dla kilku wyrazowych?

Przy czym warto zwrócić uwagę na wielokrotne wykonywanie się ost << "."; - nie wiem czy wydajność tego nie jest tragiczna i lepiej by nie wyszło spreparowanie wcześniej stringa o odpowiedniej ilości kropek i załadowanie go 'za jednym zamachem'.

4

std::setw do określania "szerokości"
std::setfill do ustawienia jaki znak ma być "wypełniaczem"
std::left/std::right/std::internal do określenie po której stronie ma być wypełnienie

0

Poprawiłem trochę kod i już w miarę formatuje ale mam problem z wczytaniem nazwy kilkuwyrazowej.

#include <iostream>
#include <fstream>
#include <string>
#include <limits>
#include<iomanip>

using namespace std;
int main()
   {
    string fileName;
    cout << "Podaj nazwe pliku: ";
    cin >> fileName;
fstream plikDoOdczytu;
        plikDoOdczytu.open( fileName.c_str(), ios::in );
        if(plikDoOdczytu.good()==false)
        cout<<"Nie mozna otworzyc pliku";
        fstream ladne;
        ladne.open( "ladne.txt", ios::out );
        if(ladne){
        string linia;
        int licznik = 1;     // Zmienna do przechowywania odczytanych wierszy tekstu
        int ilosc = 0;
        double cena = 0.0;
        double razem = 0.0;
        while(getline(plikDoOdczytu, linia))  {
        plikDoOdczytu>>ilosc>>cena>>linia;
        ladne<<"  "<<setw(1)<<licznik<<" "<<linia<<setw(25)<<setfill('.')<<ilosc<<" x"<<setw(7)<<setfill(' ')<<cena<<"\n";
        licznik++;
         }
     }
       ladne.close();
return 0;
}
1
#include <iostream>
#include <fstream>
#include <string>

int main()
   {
    std::string fileName;
    std::cout << "Podaj nazwe pliku: ";
    std::cin >> fileName;
    std::fstream plikDoOdczytu;
    std::fstream plikDoZapisu;
    int line = 0, dots = 25;
    double sum = 0;
    
    plikDoZapisu.precision(2);
    plikDoZapisu.setf(std::ios::fixed,std::ios::floatfield);
    
    plikDoOdczytu.open(fileName);
    plikDoZapisu.open("ladne.txt");
    
    while(plikDoOdczytu.good() && (plikDoOdczytu.peek() != EOF)){
        //ps. nie polecam nazywać zmiennych a,b,c :)
        int a;
        double b;
        std::string c;
        plikDoOdczytu>>a>>b;
        std::getline(plikDoOdczytu, c);
        plikDoZapisu<<++line<<" "<<c;
        for(int i=0;i<dots-c.length();++i)
            plikDoZapisu<<".";
        plikDoZapisu<<a<<" x "<<b<<" zł "<<a*b<<" zł\n";
        sum+=a*b;
    }
    plikDoZapisu<<"-----------------------------------------------------------\nRazem "<<sum<<" zł";
    
    plikDoOdczytu.close();
    plikDoZapisu.close();
    return 0;
}

1

Czytasz tak:

while(plikDoOdczytu >> ilosc >> cena && 
	std::getline(plikDoOdczytu >> std::ws, nazwa))
{
	...
}
0

Kod już poprawiony:

#include <iostream>
#include <fstream>
#include <string>
#include <limits>
#include<iomanip>

using namespace std;
int main()
   {
    string fileName =;
    cout << "Podaj nazwe pliku: ";
    cin >> fileName;
    double razem = 0.0;
    fstream plikDoOdczytu;
    plikDoOdczytu.open( fileName.c_str(), ios::in );
    if(plikDoOdczytu.good()==false)
    cout<<"Nie mozna otworzyc pliku";
    fstream ladne;
    ladne.precision(2);
    ladne.setf(std::ios::fixed,std::ios::floatfield);
    ladne.open( "ladne.txt", ios::out );
    if(ladne){
        string linia;
        int licznik = 1, dots=25;    // Zmienna do przechowywania odczytanych wierszy tekstu
        int ilosc = 0;
        double cena = 0.0;
        while(plikDoOdczytu >> ilosc >> cena &&
        std::getline(plikDoOdczytu >> std::ws, linia)){
        ladne<<"  "<<licznik++<<" "<<linia;
        for (int i = 0; i<dots-linia.length();++i)
             ladne<<".";
        ladne<<setw(3)<<ilosc<<" x "<<setw(8)<<cena<<setw(2)<<std::right<<" zł"<<setw(8)
        <<setfill(' ')<<""<<std::right<<setw(7)<<ilosc*cena<<" zł\n";

        razem+=ilosc*cena;
    }
         }
         ladne<<setw(61)<<setfill('-')<<"";
         ladne<<setw(61)<<setfill(' ')<<"Razem"<<setw(8)<<" "<<razem<<" zł";
        plikDoOdczytu.close();
       ladne.close();
        return 0;
}

W jaki sposób mogę wyświetlić długość najdłuższego wiersza w pliku (sprawdzając czy wiersze wymagające wielokrotnego
zastosowania metody getline() traktuje jak pojedyncze wiersze )?
cpp max_size() nie byłby tutaj dobrym rozwiązaniem?

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