Данные в test.dat (входной файл), данные были:
1 3.3 Langestrasse 2.200000
0 4.4 Koeningsstrasse
0 5.5 Koeniginstrasse
Следующая программа должна (разобрать данные в экземпляры классов Tankstelle / TankstelleDeLuxe и) сохранить данные в обратном порядкепорядок в protokoll.dat
Но вывод, записанный в Windows 10 (вывод g++ --version
:
g++ (x86_64-win32-seh-rev1, Built by MinGW-W64 project) 7.2.0
) в Protokoll.dat:
0 5.5
0 4.4 Koeningsstrasse
1 3.3 Langestrasse 2.200000
Свойство "Koeniginstrasse" равноявно отсутствует.Интересно, что, по словам моего друга (автора программы, у меня есть разрешения на этот вопрос), поведение не происходит в его среде Linux.
tl; dr: Несмотря на тот же Makefile и те же данные компиляции, правильностьисполняемого файла не гарантируется.
Интересно, что, по словам моего друга (автора программы, у меня есть разрешения задать этот вопрос), это неправильное поведение не происходит в его среде Linux.
Мне не удалось сделатьMWE.Даже выходные данные отладки после шага 7 в списке вниз, кажется, не показывают проблем.Сама программа, конечно, не самое элегантное решение, она была сделана для выполнения домашнего задания.
Шаги для воспроизведения:
- Сохранение всех файлов в одной папке
- Запустите make в этой папке.
- Запустите ./main.exe
- Ответ с 3
- Ответ с J
- Ответ с test.dat
- Ответ с J
- Посмотрите на protokoll.dat.Была ли вставлена "Koeniginstrasse"?
Я был бы рад, если бы вы могли дать мне несколько советов
- , если это странное поведение происходит на ваших компьютерах тоже
- почему Koeniginstrasse не сохраняется в protokoll.dat
В main.cpp критической линией является строка 126.
f << meineListe.at(i)->benzinpreisAusgabe() << " " << meineListe.at(i)->adresseAusgabe() << " ";
Заранее большое спасибо!
Файлы: Makefile:
main: main.o tankstelle.o tankstelleDeLuxe.o
g++ -std=c++11 main.o tankstelle.o tankstelleDeLuxe.o -o main
main.o: tankstelle.h tankstelleDeLuxe.h main.cpp
g++ -std=c++11 -c main.cpp
tankstelle.o: tankstelle.cpp tankstelle.h
g++ -std=c++11 -c tankstelle.cpp
tankstelleDeLuxe.o: tankstelle.h tankstelleDeLuxe.cpp tankstelleDeLuxe.h
g++ -std=c++11 -c tankstelleDeLuxe.cpp
clean:
rm main *.o
tankstelle.cpp:
#include <iostream>
#include "tankstelle.h"
//#include <unistd.h>
//#include <stdlib.h>
//#include <cstdlib>
//Initialisierung:
Tankstelle::Tankstelle(std::string adresse, double benzinpreis,bool waschstrasse)
: adresse(adresse), benzinpreis(benzinpreis), waschstrasse(waschstrasse)
{};
double Tankstelle::benzinpreisAusgabe(){
return this->benzinpreis;
}
std::string Tankstelle::adresseAusgabe(){
return this->adresse;
}
bool Tankstelle::waschstrasseAusgabe(){
return this->waschstrasse;
}
tankstelle.h:
//tankstelle.h
#ifndef _TANKSTELLE_H_
#define _TANKSTELLE_H_
#include<string> //fuer Adresse
class Tankstelle
{
public: // oeffentlich
Tankstelle(std::string adresse="Unbekannt", double benzinpreis=0,bool waschstrasse = false ); // // Konstruktor mit Parameter und Defaultwert
double benzinpreisAusgabe();
std::string adresseAusgabe();
bool waschstrasseAusgabe();
bool waschstrasse;
protected: // privat
std::string adresse;
double benzinpreis;
};
#endif //_TANKSTELLE_H_
tankstelleDeLuxe.cpp:
#include "tankstelle.h"
#include "tankstelleDeLuxe.h"
TankstelleDeLuxe::TankstelleDeLuxe(std::string adresse, double benzinpreis, double waeschepreis)
: Tankstelle(adresse, benzinpreis, true), waeschepreis(waeschepreis)
{}
void TankstelleDeLuxe::waeschepreisEingabe(double waeschepreis){
this->waeschepreis = waeschepreis;
}
double TankstelleDeLuxe::waeschepreisAusgabe(){
return this->waeschepreis;
}
tankstelleDeLuxe.h:
#include "tankstelle.h"
#include <iostream>
class TankstelleDeLuxe: public Tankstelle {
double waeschepreis; // in Klassen implizit private
public:
TankstelleDeLuxe(std::string adresse="Unbekannt", double benzinpreis=0, double waeschepreis=0);
void waeschepreisEingabe(double waeschepreis);
double waeschepreisAusgabe();
};
main.cpp:
// einbinden von nützlichen Funktionen
//#include<iostream> // fuers << und >> //eigentlich schon drin
#include<vector> //fuer Vektoren
#include <stdlib.h>//fuer char umwandeln in int
#include <stdio.h> // fuer NULL
#include <unistd.h>//fuer getopt
//#include<string> //eigentlich schon da
#include<fstream> //fuer ein- und auslesen
#include<sstream> //fuer stringstream
#include<algorithm> // fuer reverse
#include "tankstelleDeLuxe.h"
using namespace std;
int main(int argc, char *argv[])
{
int c = 0;
while ((c = getopt (argc, argv, "h")) != -1){
switch (c){
case 'h': {
cout << "Dieses Programm liest n Tankstellen ein." << endl;
cout << "Sie werden aufgefordert das einzugeben." << endl;
cout << "Optionen:" << endl;
cout << "\t-h Ruft diese Hilfe auf." << endl;
return 1;
}
default:{
abort ();
}
}
}
cout << "Bitte geben sie eine Zahl an, die angibt, wieviele Tankstellen eingelesen werden.";
int n;
cin >> n;
vector<Tankstelle*> meineListe;
Tankstelle* neueTankstelle;
cout << "Soll aus einer Datei eingelesen werden?(Falls nein werden Sie aufgefordert alle Daten einzeln einzugeben) \n [J/N]";
char antwort;
cin >> antwort;
if('J'== antwort){
cout << "Geben Sie den Namen der Datei bitte an. Sie muss sich in dem Ordner befinden, indem das aktuelle Programm verwendet wird. ";
string dateiname;
string zeile;
cin >> dateiname;
ifstream datei(dateiname);
if(datei.is_open() ){
while(getline(datei, zeile) ){
stringstream zeilenbestandteile(zeile);
vector<string> meineToken;
string token;
char delimiter = ' ';
while(getline(zeilenbestandteile, token, delimiter)) {
if (token != "") {
meineToken.push_back(token);
}
}
int waschstellenanzeiger = stoi(meineToken.at(0));
double benzinpreis = stod(meineToken.at(1));
string adresse = meineToken.at(2);
if(waschstellenanzeiger == 0){
neueTankstelle = new Tankstelle(adresse, benzinpreis);
}else{
double waschpreis = stod(meineToken.at(3));
neueTankstelle = new TankstelleDeLuxe(adresse, benzinpreis, waschpreis);
}
meineListe.push_back(neueTankstelle);
}
datei.close();
}else{
cout << "Datei konnte nicht geoeffnet werden. Entweder ist sie am falschen Ort oder es liegt ein Tippfehler vor.";
return 1;
}
}else if('N'!=antwort){
cout << "Fehler bei der Eingabe. Programm beendet sich. \n";
return 1;
}else{
for(int i=0; i<n;i++){
cout << "Hat die Tankstelle eine Waschstrasse? \n [J/N]";
char eingabe;
cin >> eingabe;
double waschpreis = 0; //muss fuers compilieren aussen sein
if('J'== eingabe){
cout << "Waschpreis? (double)\n";
cin >> waschpreis;
// waschpreis = strtod(temp, NULL);
} else if ('N' != eingabe){
cout << "Eingabe hat nicht funktioniert. Das Programm wird beeindet. \n";
return 1;
}
cout << "Benzinpreis?(in double) \n ";
double benzinpreis;
cin >> benzinpreis;
// benzinpreis = strtod(temp, NULL);
cout << "Bitte die Adresse: \n ";
string adresse;
cin >> adresse;
if('J'== eingabe){
neueTankstelle = new TankstelleDeLuxe(adresse, benzinpreis, waschpreis);
}else{
neueTankstelle = new Tankstelle(adresse, benzinpreis);
}
meineListe.push_back(neueTankstelle);
}
}
delete neueTankstelle;
reverse(meineListe.begin(), meineListe.end());
cout << "Sollen die Eingaben gespeichert werden?\n[J/N] ";
char einGabe;
cin>>einGabe;
if('J'== einGabe){
fstream f;
f.open("protokoll.dat", ios::app); //erzeuge eine Datei bzw erweitere sie
for(int i=0; i<meineListe.size(); i++){
if(meineListe.at(i)->waschstrasseAusgabe()){
f << 1 << " ";
}else{
f << 0 << " ";
}
cout << "Test-Adresse fuer " << to_string(i) << ": " << meineListe.at(i)->adresseAusgabe() << endl;
f << meineListe.at(i)->benzinpreisAusgabe() << " " << meineListe.at(i)->adresseAusgabe() << " "; //lese Info in die Datei aus
if(meineListe.at(i)->waschstrasseAusgabe()){
f << to_string((static_cast<TankstelleDeLuxe*>(meineListe.at(i)))->waeschepreisAusgabe());
}
f <<endl;
}
f.close();
}
//delete meineListe;
return 0;
}
test.dat как указано.protokoll.dat должен быть создан автоматически.