My code skips the first line

When I'm running the code it runs but it skips the first line of entry and I'm not sure why. I've tried looking up for solutions like cin.ignore() but it seems to just skip that line too. I'm not sure what I'm doing wrong.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
  #include <iostream>
#include <string>
#include <fstream>
using namespace std;

char decision;
void addAlbum();
void searchMusic();
char mediaFormat;
double serialNumber();

	
int main()
{
	cout << "Would you like to search or enter an album:" << endl <<"Enter (1) to search and (2) to enter an album";
	cin >> decision;
	{
	if (decision == '1')
	{
	  searchMusic();
	}
	if (decision == '2')
	{
	 addAlbum();
	}
	return 0;
	}
}
void addAlbum()
	{
	ofstream outFile;
	
	string albumName, albumArtist, albumGenre;
	
	cout << "Please enter the album name:";
	getline (cin, albumName);

	cout << "Please enter the album genre:";
	getline (cin, albumGenre);
	cout << "Please enter the album artist:";
	getline (cin, albumArtist);
	cout << "Please enter the media format (1). Cassete (2.) Vinyl (3.) Disc (4.)Digital:";
	cin >> mediaFormat;
	cin.ignore();
	outFile.open(albumArtist);
	}
void searchMusic(void)
	{
    

	}
On line 16, your cin statement will eat only one character and ignore everything else. That means if the user inputs something like:
12345\n
or
1\n
You will have some characters left over.

Then, when you reach another cin statement such as on like 36, cin will see the leftover input and immediately read it. You'll need to get rid of the extra stuff after you read your single character, or use getline to get the entire line then parse it yourself.
Last edited on
Okay, I think I understand. Would adding cin.ignore() after line 16 work. I just tried it on it and I think it has worked. I thought that was it but I'm not that great at C++. Thank you!
Hello chocotaco,

What you need to understand is the difference between "std::cin >> aVariable" and "std::getline(std::cin, aString);".

"std::cin >> aVariable" is known as formatted input. I cover that shortly. The way it works is when entering something in from the keyboard what you type is put into the "input buffer" until you press "Enter" when it is put into the variable.

Not everything you type will be put into the variable. The first leading white space, if any, is ignored. Then "std::cin" will take from the "input buffer" up to but not including the first white space or new line it finds whichever comes first also extracting the white space or new line which it throws away and does not use. Leaving whatever may be left in the "input buffer".

As long as you follow the first "std::cin" with another "std::cin" it works.

To the formatted input part I would say it works best when the variable is defined as a numeric variable. For "std::cin >> NumericVariable" The "cin" knows to expect a number for input. Therefor if you should type something other than a number, say a letter like 'a', it causes "cin" to fail. Which is something you have to deal with. The following code can catch this:

1
2
3
4
5
6
7
8
9
10
11
12
std::cin  >> numericVariable;

While (!std::cin)
{
    std::cout << “\n  Invalid Input. Anything else you might want to say.” << std::endl;  // <--- Change message as needed.

    std::cin.clear();  // <--- Clears the state bits on “cin”.
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.

    std::cout << “\n Your prompt” <<std:;endl;
    std::cin >> numericVariable;
}

This will stay in the while loop until you enter a valid number. Which is not to say that the number will be what you want. You will have to add code to validate the number.

The "ignore" function takes two parameters. The first is a number usually something large like 1,000 or 10,000 it could even be 100,000. The bit of code std::numeric_limits<std::streamsize>::max() is just a way of getting the largest number available for your computer and compiler. It comes from the header file "limits". The second parameter is the delimiter. Normally the new line character ('\n'), but can be changed to something else if needed because the "ignore" function can be used for more than clearing the "input buffer".

The std::getline(std::cin, aString); works a bit different. First is that it only works with a "std::string". It will take from the "input buffer" everything entered from the keyboard including the new line character at the end and then it discards the new line character leaving the "input buffer" empty.

"getline" takes three parameters. The first is where the input comes from. This could be “std::cin” or a file stream for reading from a file. The second parameter is the string it will put the information in to and the third parameter is the delimiter. The delimiter has a default value of the new line ('\n') and is why you do not see it all the time.

The problem that most new people have is when they mix “std::cin >> aVariable” and "std::getline(…)" in the same program. What happens is that the "cin" will leave at least the new line character in the "input buffer" and when you get to the "getline" it finds something in the "input buffer" and does not wait, but puts what is there into the variable and moves on.

My best advice is to follow the last "std::cin >> aVariable;" with std::numeric_limits<std::streamsize>::max(),'\n'); before you use "std::getline(…);". Sometimes it is easier to put this line of code just before the "std::getline" if you are not sure where the last "std::cin" is.

Note: using std::cin.ignore(); with no parameter is OK, but the defaults for the parameters are one and new line. Ignoring only one character may work some time, but not all the time. It is better to use std::numeric_limits<std::streamsize>::max(), '\n');

Hope that helps,

Andy
Hello chocotaco,

In your code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
int main()
{
	cout << "Would you like to search or enter an album:" << endl << "Enter (1) to search and (2) to enter an album";
	cin >> decision;

	{
		if (decision == '1')
		{
			searchMusic();
		}
		if (decision == '2')
		{
			addAlbum();
		}
		return 0;
	}
}

Lines 6 and 16 are not necessary. You do not need to create a block for the if statements. Also line 15 should come after line 16 with what you have.

Here is a hint for the future: an if / else if / else statement, for loop and a while loop with only one line of code does not need the {}s to define a block. OK if used though.

Main can be shortened to:
1
2
3
4
5
6
7
8
9
10
11
12
13
int main()
{
	cout << "Would you like to search or enter an album:" << endl << "Enter (1) to search and (2) to enter an album";
	cin >> decision;
	std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file <limits>.

	if (decision == '1')
		searchMusic();
	if (decision == '2')
		addAlbum();

	return 0;
}

The if statements are fine, but if you have learned about "switch" this would be a good place to use it.

The global variables "decision" and "mediaFormat" should be avoided and defined where they are used. "decision" should be in "main" where it is used and "mediaFormat" should be in the function where it is used or you could define it in "main" and pass it to the function. Global variables can be see by any code in the file and changed anywhere in the file. This makes it harder to figure out where the variable was changed when it should not have been changed.

The "cin.ignore" in your function is not necessary because it comes after the "getline"s and is not a problem. The way your program is written the function ends and returns to "main" where the program ends. Even if you put most of "main" in a do/while loop or while loop the cin >> decision; followed by the std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // <--- Requires header file <limits>. will clear the input buffer before you get to the "addAlbum" function.

Hope that helps,

Andy
Thanks guys this is helping me learn.
Topic archived. No new replies allowed.