0

I want to read strings with white spaces into members of a structure. Tried using getline but both the output statements are clubbed with a single cin for both. As per the similar posts here, tried using cin.ignore, but the input is not read into the member of the structure. Pls help. It's a part of my assignment and I'm a beginner in C++. This is how my code looks like:

#include <string.h>
using namespace std;
struct book {
  string title, author;
  int no_of_pages, year;
  float price;
};
int main() {
  int N;
  cout << "Enter the no. of books whose details are to be entered:" << endl;
  cin >> N;
  book b[N];
  int x;
  for (x = 0; x < N; x++) {
    cout << "Enter the title of book #" << x + 1 << ":" << endl;
    getline(cin, (b[x].title));
    // cin.ignore();
    cin.ignore(1000, '\n');
    cout << "Enter the author's name:" << endl;
    getline(cin, (b[x].author));
    cout << "Enter the no. of pages:" << endl;
    cin >> b[x].no_of_pages;
    cout << "Enter the price of book:" << endl;
    cin >> b[x].price;
    cout << "Enter the year of publishing" << endl;
    cin >> b[x].year;
  }
  for (x = 0; x < N; x++) {
    cout << "\n\n";
    cout << "The details of book" << x + 1 << " are:" << endl;
    cout << "Title          :" << b[x].title << endl;
    cout << "Author         :" << b[x].author << endl;
    cout << "No. of pages   :" << b[x].no_of_pages << endl;
    cout << "Price          :" << b[x].price << endl;
    cout << "Publishing year:" << b[x].year << endl;
    cout << "---------------------------------------------";
  }
  return 0;
}
MasterJEET
  • 349
  • 3
  • 14

2 Answers2

0

There's no point in using cin.ignore() in between two calls to getline. ignore is used to discard remaining characters after numeric input. So the place to use it is after numeric input and before the next getline. Like this

cout << "Enter the title of book #" << x + 1 << ":" << endl;
getline(cin, (b[x].title));
cout << "Enter the author's name:" << endl;
getline(cin, (b[x].author));
cout << "Enter the no. of pages:" << endl;
cin >> b[x].no_of_pages;
cout << "Enter the price of book:" << endl;
cin >> b[x].price;
cout << "Enter the year of publishing" << endl;
cin >> b[x].year;
cin.ignore(1000, '\n');

That said I would just read everything using getline, then convert the strings to numbers where needed. That's simpler and cleaner, all you need to know is how to convert a string to an integer, which you can easily research for yourself.

john
  • 85,011
  • 4
  • 57
  • 81
0

There are two places you should put cin.ignore in your code:

  cout << "Enter the no. of books whose details are to be entered:" << endl;
  cin >> N;
  // First cin.ignore here
  cin.ignore(1000, '\n');
    cout << "Enter the year of publishing" << endl;
    cin >> b[x].year;
    // Second cin.ignore here
    cin.ignore(1000, '\n');

Besides this I see two more problems in your code:

  • #include <string> not <string.h>
  • add #include <iostream>

Why cin.ignore is necessary? User is expected to provide new line ('\n') delimited input. When getline is used, it leaves the input stream in such a state that the next attempt to read input from stream will start at next line. This is not true for operator >>. What int x; cin >> x; does here is it reads only the integer not the new line character present right after the integer. Hence, the next attempt to read will continue within the same line. getline will then find no character before new line and hence will fetch an empty string. To avoid this and to effectively start reading from the next line, cin.ignore is necessary.

MasterJEET
  • 349
  • 3
  • 14