Cin from stdin when it his the end of a line - c++

I have a file for example
M
4
2
//comments
.#..
It is given to the program via stdin. I can't use fstream, just iostream.
If I want to read the whole thing character by character could I do?
char first_letter, first_num, second_num;
cin >> first_letter;
cin >> first_num;
cin >> second_num;
Or would the end of the line mess up cin? As in, does cin know after it reads M for first_letter, that it needs to go to the end line?
Secondly I dont want to read the comment lines. My plan is that if I see a / I will use getline to "trash" the line then move to the . # . . and store those in my array. Would that be the best way to do that?

Firstly, streams skip whitespace (space, tabs, newlines) by default, so that part is easy.
Now, concerning the comment lines, this is a bit more complicated. You can use std::getline() to read one line. This will store the line in a string and discard the trailing newline. However, if you e.g. read the first letter in your code above, the newline remains in the stream, so getline() will read an empty string. In short, don't mix line-based and token-based input.
In practice, you read a line and either parse the it manually or you create a stream for that:
while(getline(in, line)) {
if(line.empty()) continue; // empty line
if(line[0] == '#') continue; // comment line
// parse line
std::stringstream s(line);
char c;
s >> c;
}

Related

istringstream not working It does not separate the numbers that I put [duplicate]

I wish to read from cin in C++ from the current position up until a newline character into a string. The characters to be read may include spaces. My first pass fails because it stops on the first space:
string result;
cin >> result;
If cin is given:
(cd /my/dir; doSometing)\n
The variable result only gets:
(cd
I would think I should be able to use stream manipulators to accomplish this, but the skipws was not quite right in that it throws carriage returns in with spaces and tabs, plus it sounds like that is for leading whitespace to be skipped.
Perhaps I need to use streambuf something like this?
streambuf buf;
cin >> buf;
std::string str;
std::getline( std::cin, str);

cin is not accepting input with space in them in C++?

#include <iostream>
using namespace std;
int main(){
string doi, name, address, phone;
cout<<"Please provide these credentials:\n";
cout<<"1.Date of issue\n";
cin>>doi;
cout<<"2.Name\n";
cin>>name;
cout<<"3.Address\n";
cin>>address;
cout<<"4.Phone Number\n\n";
cin>>phone;
return 0;
}
When I am giving name input with spaces, for eg ("John Doe"), instead of storing this value is name it split value by space and store "John" in name and "Doe" in address.
If you have spaces in the string you want to read, you could use std::getline like this:
std::getline(std::cin, name);
instead of the line:
std::cin >> name;
Note that the getline will read all characters up to a newline character.
Also, please avoid using namespace std;.
You should use getline() in place of cin when you need to input strings with spaces.
In your case the syntax will be
string name;
getline(cin,name);
for more info on getline https://www.geeksforgeeks.org/getline-string-c/
There's a lot of muddled terminology in the comments and the answers. std::cin is an object; it doesn't do anything on its own.
Functions that read from input streams fit into one of two categories: they do formatted input or unformatted input. Formatted input functions translate the text that they get from the input stream (here, std::cin) into the data type that they're trying to read:
int i;
std::cin >> i; // operator>> reads text and translates it into an integer value
Formatted input functions begin by skipping whitespace, then they read characters and translate them; when the function encounters a character that isn't valid for the type that they're reading, or when they see whitespace, they stop. So in the example above, if you typed " 32 ", the stream extractor would skip the leading space, read the 3 and the 2, see the following space, and stop reading. The value stored into i would be 32.
std::string data;
std::cin >> data;
Here, if you type "Hello, world", the stream extractor (operator>>) will read up to the space, and store "Hello," in data.
If you want to read whitespace as well as non-whitespace you need an unformatted input function:
std::string data;
std::getline(std::cin, data);
Here, the call to getline reads text from std::cin up to the first newline character or to the end of the input stream. So if you typed " 32 " for this code, data would hold the text " 32 ". If you typed "Hello, world", data would hold the text "Hello, world".
And note that if you mix formatted input functions with unformatted input functions you have to be careful about leftover whitespace:
int i;
std::string data;
std::cin >> i;
std::getline(std::cin, data);
If you typed "32 Hello, world" on a single line, i would get the 32, and data would get " Hello, world".
On the other hand, if you type two lines of input, the first with "32" and the second with "Hello, world", you'll get 32 in i, but data will be empty. That's because the stream extractor read the 3 and the 2, then saw a newline character, and stopped, leaving the newline in the input buffer. std::getline then read that newline character and it, too, stopped. But it read the entire line: it swallowed the newline character.
So when your code switches from formatted input to unformatted you have to deal with whitespace characters remaining in the input buffer. If you want to read them, fine; but if you don't, you need to remove them:
int i;
std::string data;
std::cin >> i;
std::getline(std::cin, data); // read the rest of the line
std::getline(std::cin, data); // read the next line of text
A better approach is to do that cleanup with something like std::cin.ignore(42, '\n');. std::ignore is an unformatted input function; in this call it reads up to 42 characters, looking for a newline character. It stops reading when it has read 42 characters, sees a newline character, or hits the end of the input. That's better than using std::getline(std::cin, data) because it doesn't store the text into data, which could require a bunch of resizing if there's a lot of text in the remainder of the line. The more usual form for that call is to pass std::numeric_limits<int>::max() as the size argument; that's a special case, and it puts no limit on the number of characters to be read. So std::cin.ignore(std::numeric_limits<int>::max(), '\n'); will read characters until it finds a newline or hits the end of the input.
int i;
std::string data;
std::cin >> i;
std::cin.ignore(std::numeric_limits<int>::max(), '\n'); // flush the rest of the line
std::getline(std::cin, data); // read the next line of text

Ignoring the input character

So, I want to use the cin.ignore(200,'\n') to input a line and save it into a string without saving the \n as the string. But when I do:
cin.ignore(200,'\n');
getline(cin,name);
It asks me to input something twice, but I just want to ask me once and save it into name.
I've read something about the cin.clear(), but I think it's not what I need, or perhaps, I missunderstood what that clear does.
Thanks!
cin.ignore(n, ch) discards characters from the stream associated with std::cin until either n characters have been skipped, or until ch is seen. The cin.ignore(200, '\n'); is discarding the first input, up to the newline character. You're then getting a line, which will accept your second input.
You may need to use the cin.ignore(n, ch); construct if you want to read a line immediately after you perform a whitespace-delimited input operation, like
int i = 0;
std::cin >> i; // reads an integer, possibly leaving a '\n' in the stream
std::cin.ignore(200, '\n'); // reads and discards until a newline is seen
std::string name;
std::getline(std::cin, name); // reads a full line
In your case, if you haven't done any whitespace-delimited input, the cin.ignore is skipping over the first attempt to provide your line input. You should simply use std::getline immediately. The newline character at the end of the line is not appended to the string, but it is removed from the input stream.
The documentation for std::getline explains this in the "Notes" section.
For a more robust line input function, where you cannot be sure whether the previous input operation left a newline character (or whatever delimiter you're using) on the stream, you can do something like:
char ch;
std::cin.peek(ch);
if (ch == '\n') {
std::cin.ignore(1, '\n'); // or std::cin.get(ch);
}
std::string line;
std::getline(std::cin, line);
The peek member function will return the next character to be read, without removing it from the stream. If it's a newline, you can go ahead and ignore it. Otherwise, the getline call will read the entire line, including the character you just peeked at.
Alternatively, if you only want to consume whitespace, you can use the std::ws manipulator.
You don't need to use ignore() in this case. getline() will not put the new line character to the string.
The reason its asking you for an input twice is because the ignore() function is removing until your first 200 input characters or up to the newline(your deliminator) so the next getline() probably will not have anything to read thus asking you for input(unless of course your first input contains more than 200 characters,in that case it will read the remaining characters in the buffer).
std::getline() will not add the delimiter character to the string that is read, which is the newline character by default.

Reading a text file in c++

string numbers;
string fileName = "text.txt";
ifstream inputFile;
inputFile.open(fileName.c_str(),ios_base::in);
inputFile >> numbers;
inputFile.close();
cout << numbers;
And my text.txt file is:
1 2 3 4 5
basically a set of integers separated by tabs.
The problem is the program only reads the first integer in the text.txt file and ignores the rest for some reason. If I remove the tabs between the integers it works fine, but with tabs between them, it won't work. What causes this? As far as I know it should ignore any white space characters or am I mistaken? If so is there a better way to get each of these numbers from the text file?
When reading formatted strings the input operator starts with ignoring leading whitespace. Then it reads non-whitespace characters up to the first space and stops. The non-whitespace characters get stored in the std::string. If there are only whitespace characters before the stream reaches end of file (or some error for that matter), reading fails. Thus, your program reads one "word" (in this case a number) and stops reading.
Unfortunately, you only said what you are doing and what the problems are with your approach (where you problem description failed to cover the case where reading the input fails in the first place). Here are a few things you might want to try:
If you want to read multiple words, you can do so, e.g., by reading all words:
std::vector<std::string> words;
std::copy(std::istream_iterator<std::string>(inputFile),
std::istream_iterator<std::string>(),
std::back_inserter(words));
This will read all words from inputFile and store them as a sequence of std::strings in the vector words. Since you file contains numbers you might want to replace std::string by int to read numbers in a readily accessible form.
If you want to read a line rather than a word you can use std::getline() instead:
if (std::getline(inputFile, line)) { ... }
If you want to read multiple lines, you'd put this operation into a loop: There is, unfortunately, no read-made approach to read a sequence of lines as there is for words.
If you want to read the entire file, not just the first line, into a file, you can also use std::getline() but you'd need to know about one character value which doesn't occur in your file, e.g., the null value:
if (std::getline(inputFile, text, char()) { ... }
This approach considers a "line" a sequence of characters up to a null character. You can use any other character value as well. If you can't be sure about the character values, you can read an entire file using std::string's constructor taking iterators:
std::string text((std::istreambuf_iterator<char>(inputFile)),
std::istreambuf_iterator<char>());
Note, that the extra pair of parenthesis around the first parameter is, unfortunately, necessary (if you are using C++ 2011 you can avoid them by using braces, instead of parenthesis).
Use getline to do the reading.
string numbers;
if (inputFile.is_open())//checking if open
{
getline (inputFile,numbers); //fetches entire line into string numbers
inputFile.close();
}
Your program does behave exactly as in your description : inputFile >> numbers; just extract the first integer in the input file, so if you suppress the tab, inputFile>> will extract the number 12345, not 5 five numbers [1,2,3,4,5].
a better method :
vector< int > numbers;
string fileName = "text.txt";
ifstream inputFile;
inputFile.open(fileName.c_str(),ios_base::in);
char c;
while (inputFile.good()) // loop while extraction from file is possible
{
c = inputFile.get(); // get character from file
if ( inputFile.good() and c!= '\t' and c!=' ' ) // not sure of tab and space encoding in C++
{
numbers.push_back( (int) c);
}
}
inputFile.close();

Why does getline return empty lines if none exist

I have a file containing the following lines:
5556
0 bla.dxf
1 blub.dxf
2 buzz.dxf
The numbers and text are seperated by a singular tab each, there is no whitespace character after 5556. The following code is used for parsing.
int main(int, char**){
std::ifstream file("test.bld");
std::string buildingName;
file >> buildingName;
std::cout << buildingName << std::endl;
std::string buf;
while(getline(file, buf)) {
if(buf.empty()){std::cout << "String was empty"<<std::endl;}
else std::cout << buf << std::endl;
}
return 0;
}
When I parse the file I get an empty line although there obviously is none.
The output reads as follows:
5556
String was empty
0 bla.dxf
1 blub.dxf
2 buzz.dxf
This is only a minimal example. The whole file and the parser is more complex and I would very much like to use direct parsing for the first element and getline for the rest. What am I misunderstanding about line parsing with getline and how do I avoid getting empty lines?
operator>>(istream, string) reads up to but not including the first whitespace character after the extracted token.
To skip the rest of the line after extracting a token, you can either use
std::cin >> std::ws;
(if you know that there is only a newline remaining), or
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
to skip to the end of the line regardless.
I'm assuming because
file >> buildingName;
doesn't move the cursor to the next line, but leaves it at the end of the current line. So when you call getline, you'll read an empty string and then move to the next.