0

If i input number 2 for std::cin >> menu;, the code after std::cin >> menu; won't execute. At first, i think the problem is in the function, but the code haven't even go to the switch (i have debugged it with std::cout in the switch and after std::cin >> menu;).

After i input 2, it's just stuck there like loading some massive proccess, while all i do is just take the menu to be the switch parameter.

what is wrong with my code can someone help?

#include <iostream>
#include <fstream>
#include <unistd.h>

struct jadwal {
    std::string Jurusan;
    int Jam;
    int Durasi;
};

void daftarMenu() {
    std::cout << "aplikasi pertemuan" << std::endl;
    std::cout << "menu : " << std::endl;
    std::cout << "[1]. Input" << std::endl;
    std::cout << "[2]. Output" << std::endl;
    std::cout << "[3]. Hasil" << std::endl;
    std::cout << "[4]. Exit" << std::endl;
}

void inputJadwal() {
    int jumlah;
    jadwal jadwal[100];
    std::cout << "Masukkan jumlah jadwal yang ingin ditambahkan : ";
    std::cin >> jumlah;

    std::ofstream file;
    file.open("file1.txt", std::ios::app);
    if(!file) {
        file.open("file1.txt", std::ios::trunc);
    };

    for(int i = 0; i < jumlah; i++) {
        std::cin.ignore();
        std::cout << "Jurusan : ";
        getline(std::cin, jadwal[i].Jurusan);
        file << jadwal[i].Jurusan;

        file << std::endl;

        std::cout << "Jam : ";
        std::cin >> jadwal[i].Jam;
        file << jadwal[i].Jam;

        file << std::endl;

        std::cout << "Durasi : ";
        std::cin >> jadwal[i].Durasi;
        file << jadwal[i].Durasi;

        file << std::endl;
    };

    file.close();

    std::cout << "Data berhasil di input, mengembalikan ke menu utama..." << std::endl;
    sleep(2);
};

void outputJadwal() { 
    jadwal jadwal[100];
    std::ifstream file;
    file.open("file1.txt");
    std::cout << "tes";
    if(!file) {
        std::cout << "Tidak ada jadwal terdaftar" << std::endl;
        sleep(2);
        return;
    };

    std::cout << "tes";
    int index = 0;
    while(!file.eof()) {
        file >> jadwal[index].Jurusan;
        file >> jadwal[index].Jam;
        file >> jadwal[index].Durasi;
        index++;
    }

    int total = index + 1;

    for(int i = 0; i < total; i++) {
        std::cout << "Jurusan : " << jadwal[i].Jurusan;
        std::cout << "Jam " << jadwal[i].Jam;
        std::cout << "Durasi " << jadwal[i].Durasi;
    }

    file.close();
};

void hasilJadwal() {

};

int main() {
    int menu;
    int jumlah;
    
    do{
        //
        daftarMenu();
        std::cout << "Pilih : ";
        std::cin >> menu;
        
        // this code won't execute if i enter number 2 for the menu, but it is okay if i enter 1, 3, 4, 5, or more
        std::cout << "you are choosing menu " << menu;

        switch(menu) {
            case 1:
                inputJadwal();
                break;
            case 2:
                std::cout << "case 2 selected";
                outputJadwal();
                break;
            case 3:
                hasilJadwal();
                break;
            case 4:
                std::cout << "Mengeliminasi program...";
                return 0;
            default:
                std::cout << "Input tidak valid, mengembalikan ke menu utama..." << std::endl;
                sleep(2);
                break;
        }

    }while(true);
    return 0;
}

I have tried this solution from Chat GPT but it doesn't do anything.

if(std::cin.fail()) {
            std::cerr << "Error: Invalid input. Clearing input buffer and retrying..." << std::endl;
            std::cin.clear(); // Clear the error flags
            std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Discard invalid input
            sleep(2);
            continue; // Retry the loop
        }

        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

I personally don't think there is any problem in my code, atleast in the int main(), because my problem is only in int main();

10

2 Answers 2

0

Ok I was able to reproduce the issue.

The problem appears when code expects to read an integer value but the stream contains something else.

To reproduce, you need invalid data in the file file1.txt: https://godbolt.org/z/d8orMd3dr

When data is valid, code works: https://godbolt.org/z/84McMnhGq

The problem was nailed by comment from Retired Ninja which links this: Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?

Basically, when the data is invalid, the stream goes to an invalid state and eof is never raised, leading to an infinite loop.

Fixed version:

    while(file >> jadwal[index].Jurusan
        >> jadwal[index].Jam
        >> jadwal[index].Durasi) {
        index++;
    }

Resolves the issue: https://godbolt.org/z/WYv68GeEW

Now, the loop iterates as long as the last reading operation was successful. Any kind of error will now stop the loop.

Sign up to request clarification or add additional context in comments.

Comments

0

I solved it differently and used a helper function.

first of all, I used the std::getline function to read the file line by line. But how to differentiate between Jurusan , Jam and Durasi ? I assumed that Jurusan is an alphabetic word so we need to check the first line for each iteration, it should be an alphabetic word so I used this helper function

   bool isAlphabetic(const std::string& word) {
for (char c : word) {
    if (!std::isalpha(static_cast<unsigned char>(c))) {
        return false; // Return false if any character is not alphabetic
    }
}
return true; // Return true if all characters are alphabetic

}

then the line after the alphabetic word should be a number (Jam) so I used a flag isPrevLineAlpha which works as an indicator that the previous line was alphabetic and this is Jam's turn to read the line and convert it into an integer and update the flag to indicate that the next iteration is Dursai's turn

int index = 0;
std::string line;
bool isPrevLineAlpha = false ; 

while (std::getline(file, line)) {
    

    if (isAlphabetic(line)){
         jadwal[index].Jurusan=line;
         isPrevLineAlpha = true;
    }else if ( isPrevLineAlpha ){
        jadwal[index].Jam=std::stoi(line);
        isPrevLineAlpha = false;
    }else{  
        jadwal[index].Durasi=std::stoi(line);
        isPrevLineAlpha = false;
        index++;
    }
     
    
}

but you have to make sure to validate the inputs from the user so that he doesn't enter integer at the beginning and string afterwards, that will ruin you whole code.

so the whole function will be like that

void outputJadwal() { 
jadwal jadwal[100];
std::ifstream file;
file.open("file1.txt");
std::cout << "tes" << std::endl;
if(!file) {
    std::cout << "Tidak ada jadwal terdaftar" << std::endl;
    sleep(2);
    return;
};

std::cout << "tes" << std::endl;
int index = 0;
std::string line;
bool isPrevLineAlpha = false ; 

while (std::getline(file, line)) {
    

    if (isAlphabetic(line)){
         jadwal[index].Jurusan=line;
         isPrevLineAlpha = true;
    }else if ( isPrevLineAlpha ){
        jadwal[index].Jam=std::stoi(line);
        isPrevLineAlpha = false;
    }else{  
        jadwal[index].Durasi=std::stoi(line);
        isPrevLineAlpha = false;
        index++;
    }
     
    
}

for(int i = 0; i < index; i++) {
    std::cout << "Jurusan : " << jadwal[i].Jurusan << std::endl;
    std::cout << "Jam " << jadwal[i].Jam << std::endl;
    std::cout << "Durasi " << jadwal[i].Durasi << std::endl;
}

file.close();

};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.