Given in test.dat (the input file), the data were:
1 3.3 Langestrasse 2.200000
0 4.4 Koeningsstrasse
0 5.5 Koeniginstrasse
The following program should (parse the data into instances of the classes Tankstelle / TankstelleDeLuxe and ) save the data in reversed order in protokoll.dat
But the output written under Windows 10 (output of g++ --version
:
g++ (x86_64-win32-seh-rev1, Built by MinGW-W64 project) 7.2.0
) into Protokoll.dat is:
0 5.5
0 4.4 Koeningsstrasse
1 3.3 Langestrasse 2.200000
The property "Koeniginstrasse" is clearly missing. Interestingly, according to my friend (the program's author, I have the permissions to ask this question), the behaviour does not occur under his Linux environment.
tl;dr: Despite the same Makefile and the same compilation data, the correctness of the executable file is not guaranteed.
Interestingly, according to my friend (the program's author, I have the permissions to ask this question), this wrong behaviour does not occur under his Linux environment.
I was not able to make a MWE. Even the debugging output after step 7 in the list downward seems to show no problems. The program itself is certainly not the most elegant solution, it was made to fulfill a homework exercise.
Steps to reproduce:
- Save all given files in the same folder
- Run make in this folder.
- Run ./main.exe
- Answer with 3
- Answer with J
- Answer with test.dat
- Answer with J
- Look at protokoll.dat. Was "Koeniginstrasse" inserted?
I would be glad if you could give me some hints
- wether this strange behaviour occurs on your PCs too
- why Koeniginstrasse is not saved into protokoll.dat
The critical line seems to be line 126 in main.cpp.
f << meineListe.at(i)->benzinpreisAusgabe() << " " << meineListe.at(i)->adresseAusgabe() << " ";
Many thanks in advance!
Files: 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 as given. protokoll.dat should be created automatically.
Aucun commentaire:
Enregistrer un commentaire