0

I have a program that needs to read 3 attributes from the user. It can read the first 2 just fine, when it tries to read the 3rd attribute (a double) it freezes until you enter an integer.

Here is the code

#include <iostream>
#include <fstream>
#include <map>
#include <string>
#include <iomanip>
using namespace std;

#include <string>
#include "book.h"


Book::Book(const std::string &serialNo, const std::string &title, double price) : serialNo(serialNo), title(title),
                                                                                  price(price) {}
const std::string &Book::getSerialNo() const {
    return serialNo;
}

void Book::setSerialNo(const std::string &serialNo) {
    Book::serialNo = serialNo;
}

const std::string &Book::getTitle() const {
    return title;
}

void Book::setTitle(const std::string &title) {
    Book::title = title;
}

double Book::getPrice() const {
    double scale = .1;
    return (int)(price / scale) * scale;
}

void Book::setPrice(double price) {
    Book::price = price;
}


map<string, Book *> addNewBook(map<string, Book *> inventory) {
    printf("**Add New Book**\n\nNote: Type quit and enter on the serial no. to return to the Main Menu\n");
    string serialNo, title;
    double price;
    while(serialNo != "quit") {
        printf("Serial No.:");
        cin >> serialNo;
        if (serialNo == "quit") {
            continue;
        }
        cin.clear();
        cin.ignore(100, '\n');
        printf("\nTitle: ");
        getline(cin, title);
        printf("\nPrice: ");
        cin.clear();
        cin.ignore(100, '\n');
        cin >> price;
        if (inventory.find(serialNo) == inventory.end()) {
            inventory[serialNo] = new Book(serialNo, title, price);
        } else {
            printf("Serial No. exist already, please enter again:\n");
        }
        cin.clear();
        cin.ignore(100, '\n');
    }
    return inventory;
}

int main() {
    map<string, Book*> inventory;
    addNewBook(inventory);
}

If you enter some string for the first 2 inputs, and something like 2.5 for the 3rd it will hang until you enter something like 12.

How do I prevent the hang and have it read the 2.5?

John Hamlett IV
  • 495
  • 11
  • 23
  • When you call `addNewBook(inventory);`, do you forget that the function has a return value? – Arnav Borborah Jan 11 '18 at 14:27
  • Not in my actual project, this is just a contrived example. In my actual project I do inventory = addNewBook(inventory) – John Hamlett IV Jan 11 '18 at 14:28
  • Possible duplicate of [When and why do I need to use cin.ignore() in C++?](https://stackoverflow.com/questions/25475384/when-and-why-do-i-need-to-use-cin-ignore-in-c) – Arnav Borborah Jan 11 '18 at 14:54

2 Answers2

1

I am unsure what the actual error is, but to solve your problem, I just removed the second and third cin.clear()/cin.ignore(), and your code works. I believe the problem may lie with you ignoring the third input, so that that you have to reenter the price. You don't even need the second and third cin.ignore(), since getline() is before both (Source). Here is a working repl.

Arnav Borborah
  • 11,357
  • 8
  • 43
  • 88
0

The combo

cin >> serialNo;
cin.clear();
cin.ignore(100, '\n');

is used to eat the newline character left in the input buffer by operator>>. This is done so that a getline following it will not treat the buffer as empty-line+\n.

However, getline is different in that it does consume the \n at the end when reading a whole line, and leaves nothing in the input buffer.

So now

getline(cin, title);
cin.clear();
cin.ignore(100, '\n');

expects one '\n'for the getline and another one for the ignore.

That's why you have to type anything+enter to continue.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203