Почему моя улица напечатана на Linux, а не на Windows? - PullRequest
0 голосов
/ 23 ноября 2018

Данные в 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 в списке вниз, кажется, не показывают проблем.Сама программа, конечно, не самое элегантное решение, она была сделана для выполнения домашнего задания.

Шаги для воспроизведения:

  1. Сохранение всех файлов в одной папке
  2. Запустите make в этой папке.
  3. Запустите ./main.exe
  4. Ответ с 3
  5. Ответ с J
  6. Ответ с test.dat
  7. Ответ с J
  8. Посмотрите на 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 должен быть создан автоматически.

1 Ответ

0 голосов
/ 26 ноября 2018

Честь для решения принадлежит @molbdnilo, который заметил случай неопределенного поведения (delete neueTankstelle привел к свисающему указателю в списке).@hyde упомянул возможный случай различных окончаний файла.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...