Wrong order of output while using map in C++ - c++

I have written a program in which certain entries are made into a map. Later, using an iterator, I wanted to see the key-value pairs in this format
key=value.
But the output is coming as
=key value.
Here's the code
int main() {
map<string,string> mp;
int n;
string name, number;
cin>>n;
for(int i=0; i<n; ++i)
{
getline(cin,name);
getline(cin,number);
mp.insert(pair<string,string>(name,number));
}
string line;
map<string,string>::iterator fndr;
fndr = mp.begin();
cout << (*fndr).first << "=" << (*fndr).second;
return 0;
}
Here's the input
2
abhay 239487
hello 23478
Here's the output
=abhay 239487

Your .first is empty and the whole thing is going in .second. getline() is taking the whole string input and storing it in number variable. Quick solution (but won't work for names that contain spaces):
cin >> name;
cin >> number;
Explanation:
Before using getline(), you have used cin >> n to input the number of strings. After the input, when you press Enter a \n is appended at the end of your input. So your input actually looks like this:
2\n
abhay 239487\n
hello 23478\n
Now cin >> n uses 2 in the first line to store it in n variable but the \n is still there in the stream. When getline() is used for the next input, it finds the \n in the input stream and terminates thus storing nothing in name variable (\n is a delimiter for getline()). The next getline() finds the string abhay 239487 before it encounters another \n and terminates.
Thus, we need to ignore the \n after 2 before the first execution of getline()). We can use cin.ignore() between the last cin and the first getline(). This will ignore the next character in the input stream.
Code
int main() {
map<string,string> mp;
int n;
string name, number;
cin>>n;
cin.ignore();
for(int i=0; i<n; ++i) {
getline(cin,name);
getline(cin,number);
mp.insert(pair<string,string>(name,number));
}
string line;
map<string,string>::iterator fndr;
fndr = mp.begin();
cout << (*fndr).first << "=" << (*fndr).second;
return 0;
}
You can notice after using cin.ignore(), abhay 239487 goes in name and hello 23478 goes in number. The output is:
abhay 239487=hello 23478
which is expected for this case.
How to workaround the problem of segregating key: value pair ? There are two ways:
Either you can input the name (key) and the corresponding number (value) in two different lines (This method will work for strings which contains spaces in name) like this:
2
abhay nayar
239487
hello
23478
Or, you can use cin >> name >> number to get those values (but you cannot use names that contain spaces because any whitespace character is a delimiter for cin).

Related

Array of string type

I have declared a string array of [15]. Actually to store names. I execute it fine, but when I enter the complete name (including space; First name+[space]+last name) the program misbehaves. I cannot find the fault
I have declared multiple string arrays in the program, when I input the name with space it doesn't executes fine. I am using cin>> function to input in the array. like
string name[15];
int count=0; cout << "enter your name" << endl;
cin >> name[count];
I am using cin>> function to input in the array.
That is the problem. operator>> is meant for reading formatted input, so it stops reading when it encounters whitespace between tokens. But you want unformatted input instead. To read a string with spaces in it, use std::getline() instead:
string name[15];
int count=0;
cout << "enter your name" << endl;
getline(cin, name[count]);
Online Demo

How to get a certain element from an input (C++)

I am new to programming in C++.
I am trying to ask the user an input (for example):
std::string numbers;
std::cout << What is your favorite number;
std::cin >> numbers
If the user entered
1, 2, 3
How do I extract only the number "2"? I know in python, you would do something like numbers[1], but is there a same way in C++ as well?
So, "what are your favorite numbers?"
The idea is the same as in python or any other language: split the input line by the separator character, trim if you care, and finally get the element you want, if it exists.
Splitting a string by a character
Eventually, trim
Finally, you should have a vector of string, and you can get the second with v[1] or similar, checking if it exists
you can get the length of string by numbers.length().
then you can use for loop.
for(int i =0 ; i < numbers.length();i++)
{
if(numbers[i] == '2')
// do what you want you do here with 2
}
Keep in mind, your cin won't get entire "1, 2, 3" string because of whitespace. You should use getline instead of cin.
such as..
getline(cin, numbers,'\n');
To catch a line of numbers:
int main()
{
std::vector<int> numbers;
std::string line;
std::getline(std::cin, line); // First read the whole line of input
std::stringstream linestream(line); // Set up to parse the line
int number;
while(linestream >> number) { // Read a number
char x; // for the comma
linestream >> x; // remove the comma
numbers.push_back(number); // Add to the vector (array)
}
// Print the number
std::cout << "The second number is: " << numbers[1] << "\n"; // vectors are 0 indexed
}

Getline keeps on getting newline character. How can I avoid this?

Basically I first takes an integer as input and then test case follows. My each test case is an string. I am suppose to print the string back if the starting patten of string matches "HI A" and it is case-insensitive. I wrote the code below to accomplish to this. My problem is that when I press enter after each input, getline takes newline character as new input. I have tried to tackle this by using extra getline after each input but the issue is still there. Program gets stuck in the loop even though I have put a break condition. What am I doing wrong?
#include <iostream>
#include <string>
using namespace std;
int main(){
int N;
cin >>N;
string nl;
getline(cin,nl);
for (int i=0;i<N;i++){
string s;
getline(cin,s);
//cout <<"string"<<s<<endl;
int flag=0;
if ((s.at(0)=='h'||s.at(0)=='H')&&(s.at(1)=='i'||s.at(1)=='I')&&(s.at(2)==' ')&&(s.at(3)=='a'||s.at(3)=='A')) flag=1;
if (flag==1) cout << s;
//cout << "not " <<s;
string ne;
cout << "i="<< i<<endl;
if (i==N-1) {break;}
getline(cin,ne);
}
}
Here is sample input:
5
Hi Alex how are you doing
hI dave how are you doing
Good by Alex
hidden agenda
Alex greeted Martha by saying Hi Martha
Output should be:
Hi Alex how are you doing
ignore() function does the trick. By default, it discards all the input suquences till new line character.
Other dilimiters and char limit can be specified as well.
http://www.cplusplus.com/reference/istream/istream/ignore/
In your case it goes like this.
cin >> N;
cin.ignore();
Your cin >>N stops at the first non-numeric character, which is the newline. This you have a getline to read past it, that's good.
Each additional getline after that reads the entire line, including the newline at the end. By putting in a second getline you're skipping half your input.
So, your real problem isn't that getline eats newlines, but that your second getline(cin, ne) is eating a line...
And that is because you mistakenly think that you need two getline operations to read one line - or something like that. Mixing "linebased" and "itembased" input does have confusing ways to deal with newlines, so you do need something to "skip" the newline left behind frin cin >> N;, but once you have got rid of that, you only need ONE getline to read up and including the newline at the end of a line.
I am writing this answer with the hopes that it may help someone else out there that wants a very simple solution to this problem.
In my case the problem was due to some files having different line endings such as '\r' vs. '\n'. Everything worked fine in windows but then it failed in Linux.
The answer was actually simple. I created a function removeNewLineChar after each line was read in. That way the char was removed. The removeNewLineChar takes in the line that was read in and copies it over character by character into a new string but it avoids copying either of the newline characters.
Here is an example:
string trim(string line)
{
string newString;
for (char ch : line)
{
if (ch == '\n' || ch == '\r')
continue;
newString += ch;
}
return newString;
}
//some function reading a file
while (getline(fin, line)) {
line = trim(line);
//... do something with the line
line = "";
}
you just need to accept the fact that getline will give you '\n' at the end. One solution is remove '\n' after getting it. Another solution is do not write the additional 'endl'. for example, for your problem, you can use this code
int N;
cin >> N;
string line;
getline(cin, line); // skip the first new line after N.
for (int i = 0; i < N; i++) {
string line;
getline(cin, line);
string first4 = line.substr(0, 4);
// convert to upper case.
std::transform(first4.begin(), first4.end(), first4.begin(), std::ptr_fun<int, int>(std::toupper)); // see http://en.cppreference.com/w/cpp/algorithm/transform
if (first4 == "HI A") {
cout << line; // do not include "<< endl"
}
}
cin.ignore() worked for me.
void House::provideRoomName()
{
int noOfRooms;
cout<<"Enter the number of Rooms::";
cin>>noOfRooms;
cout<<endl;
cout<<"Enter name of the Rooms::"<<endl;
cin.ignore();
for(int i=1; i<=noOfRooms; i++)
{
std::string l_roomName;
cout<<"Room"<<"["<<i<<"] Name::";
std::getline(std::cin, l_roomName);
}
}
std::string line;
std::cin>>std::ws; // discard new line not processed by cin
std::getline(std::cin,line);
From Notes section https://en.cppreference.com/w/cpp/string/basic_string/getline
When consuming whitespace-delimited input (e.g. int n; std::cin >> n;) any whitespace that follows, including a newline character, will be left on the input stream. Then when switching to line-oriented input, the first line retrieved with getline will be just that whitespace. In the likely case that this is unwanted behaviour, possible solutions include:
An explicit extraneous initial call to getline
Removing consecutive whitespace with std::cin >> std::ws
Ignoring all leftover characters on the line of input with cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

Input Validation to make sure only number c++

Ok, I'm trying to get good at using pointers so I'm trying to write a input validation for the user input to make sure that anything that isn't a number is handled correctly. When I use isdigit() isn't working for me. I still get an exception when I enter a alphabet. Any suggestions? Thanks. Check this out:
#include<iostream>
#include<algorithm>
#include<string>
#include<cctype>
using namespace std;
void EnterNumbers(int * , int);
int main()
{
int input = 0;
int *myArray;
cout << "Please enter the number of test scores\n\n";
cin >> input;
//Allocate Array
myArray = new int[input];
EnterNumbers(myArray,input);
delete[] myArray;
return 0;
}
void EnterNumbers(int *arr, int input)
{
for(int count = 0; count < input; count++)
{
cout << "\n\n Enter Grade Number " << count + 1 << "\t";
cin >> arr[count];
if(!isdigit(arr[count]))
{
cout << "Not a number";
}
}
}
If you test if (!(cin >> arr[count])) ... instead - isdigit(arr[digit]) tests if the value of arr[digit] is the ASCII code of a digit [or possibly matches Japanese, Chinese or Arabic (that is, as an Arabic script typeface, not that it's a 0-9 like our "Arabic" ones) digit]. So if you type in 48 to 57, it will say it's OK, but if you type 6 or 345, it's complaining that it is not a digit...
Once you have discovered a non-digit, you will also need to either exit or clean out the input buffer from "garbage". cin.ignore(1000, '\n'); will read up to the next newline or a 1000 characters, whichever happens first. Could get annoying if someone has typed in a million digits, but otherwise, should solve the problem.
You will of course also need a loop to read the number again, until a valid number is entered.
The way I do this kind of input validation is that I use std::getline(std::cin, str) to get the whole line of input and then I parse it using the following code:
std::istringstream iss(str);
std::string word;
// Read a single "word" out of the input line.
if (! (iss >> word))
return false;
// Following extraction of a character should fail
// because there should only be a single "word".
char ch;
if (iss >> ch)
return false;
// Try to interpret the "word" as a number.
// Seek back to the start of stream.
iss.clear ();
iss.seekg (0);
assert (iss);
// Extract value.
long lval;
iss >> lval;
// The extraction should be successful and
// following extraction of a characters should fail.
result = !! iss && ! (iss >> ch);
// When the extraction was a success then result is true.
return result;
isdigit() applies to char not to int as you're trying. The cin >> arr[count]; statement already ensures an integer numeric digits format is given in the input. Check cin.good() (!cin respectively) for possible input parsing errors.

Having issue with cin function in a loop

I'm an just trying to fill an array with strings using a loop. My problem is that when it enters the loop to input names it will instantaneously input a blank line for the first slot in the vector. Why does this happen? And how can I fix it. Please don't mind my lack of code style, I'm a noob trying to regain my knowledge of programming before I start in a class this winter...
Here's some sample output:
How many people are in your family?
4
Please enter the names of all of your family members
check name:
Please enter the names of all of your family members
Matt
check name:Matt
Please enter the names of all of your family members
Evan
check name:Evan
Please enter the names of all of your family members
Michelle
check name:Michelle
Matt
Evan
Michelle
and this is my code:
vector<string> Names;
bool complete=0;
while(!complete)
{
int number;
cout << "How many people are in your family?" << endl;
cin >> number;
for(int i=0; i<number; i++)
{
string names;
cin.clear();
cout << "Please enter the names of all of your family members" << endl;
getline(cin,names);
Names.push_back(names);
cout << "check name:" << names << endl;
}
complete = 1;
}
for (int i=0; i< Names.size(); i++)
{
cout << Names[i] << endl;
}
The reason you see this behavior is mixing the >> reads with getline. When you read the count, the input pointer is advanced to the end of the numeric input, i.e. 4, and stops right before the new line character is read.
This is when you call getline; the new line character is read, and the new line is returned right away.
To fix this problem, add a call to getline right after the cin >> number call, and discard the result.
May I suggest you try
std::cin >> names;
instead of
getline(std::cin, names);
getline takes in std::endl or the \n from your std::cout print string. The idea is that getline will read until the \n character (which is an indication of an endline), but it will also consume the endline character. This is why it is consuming the newline character into your vector.
Consider doing this . . .
std::cin.get();
which will read std::endl character and then use the getline function.
The problem is mixing fonatted input (std::cin >> number) with unformatted input (std::getline(std::cin, names)). The formatted input stops at first non-integer character, most likely the newline you entered after the count. The easiest fix is to skip leading whitespace explicitly:
std::getline(std::cin >> std::ws, names);
Note, that you also need to check after each input that it was successful:
if (std::cin >> number) {
// do something after a successful read
}