determining the end of user char input c++ - c++

i want to proccess user input which is a line of string. with string library it's just easy as cin >> mystring; , but for performance reasons, i'd like to process a character at a time without saving previous characters or using any kind of arrays. so i wrote this code:
char myc;
while(cin >> myc){
dosomething(myc);
}
but after writing a line of string as input and hitting enter, it processes input characters and still waits for more input characters to come.
i also used cin.eof() and while(myc) but none of them worked.

You have to check for line break but you can't do it with std::istream::operator>> because it is formatted read and skips newline. Use
char myc;
while ((myc = cin.get()) != '\n')
dosomething(myc);
}

To read a stream character-wise use std::basic_istream<CharT,Traits>::get function:
for(char c; std::cin.get(c);) {
std::cout << c;
}

Related

Reading sentences as string inputs from users

I have been trying to implement a simple code which takes a sentence as an input from the user, stores it in a string and displays it back.
Here are the issues:
1. When T = 1, the program exits immediately.
2. When T>1, the loop runs for only T-1 times.
I think the usage of cin to store the value of T is an issue here. Is the value of T entered being stored as a string due to some buffer capacity of cin?
#include <iostream>
#include <string>
int main()
{
int T;
std::cin >> T;
while (T--)
{
std::string song;
getline(std::cin, song);
std::cout << song << std::endl;
}
return 0;
}
How do you terminate the input that becomes T? With a newline. What happens with that newline after you read into T? It's still left in the input buffer. What will happen when you next call std::getline, what is the first character it will read? The newline, and what happens next? The loop iterates and then T is zero (for the first case where T was originally 1) and the loop and then the program exits.
The solution to this problem is to ignore characters up to and including the newline.
Add a getchar after cin as the \n after the input of T stays in buffer.
std::cin >> T;
getchar();
This is a strange way to do it. So you ask the user to tell the program, before any other input, how many lines will follow? Why not simply:
std::string s;
while (getline(std::cin, s)) {
std::cout << s << std::endl;
}
(This will simply echo every line (press enter to end the line) until end-of-file (Ctrl-d).
Either way, the problem with your code is the while (T--): so why don't you try to see what your T is, and what your getline gives you on each iteration? (I will let you figure it out on your own). Why not use the idiomatic:
for (int i = 0; i < T; ++i)
?
P.S. If you want to read sentences, and not lines, you might want to consider reading up to a delimiter (for example .). getline will do that for you, too:
getline(std::cin, s, '.');

To take sentence as a input in c++

I am trying to take the input of the two sentences one after the other,but while printing it is printing a blank space and in the next line it is printing the first sentence and the loop is exiting.
Here is my code:
int main()
{
char b[100000];
char c[100000];
int t;
cin>>t;
while(t--)
{
cin.getline(b,100000);
cin.getline(c,100000);
cout<<b<<"\n"<<c<<"\n";
}
}
The input:
1
run run
good sentence
The output:
Blankspace
run run
cin >>t;
This will prompt the user for some input. Assuming the user does what's expected of them, they will type some digits, and they will hit the enter key.
The digits will be stored in the input buffer, but so will a newline character, which was added by the fact that they hit the enter key.
cin will parse the digits to produce an integer, which it stores in the num variable. It stops at the newline character, which remains in the input buffer.
cin.getline(b,100000);
cin.getline(c,100000);
Later, you call cin.getline(b,100000);, which looks for a newline character in the input buffer. It finds one immediately, so it doesn't need to prompt the user for any more input. So it appears that the first call to getline didn't do anything, but actually it did.
Big arrays are not good idea. Try use std::string instead.
#include <iostream>
#include <string>
int main() {
std::string lineOne;
std::string lineTwo;
std::getline(std::cin, lineOne);
std::getline(std::cin, lineTwo);
std::cout << lineOne << "\n" << lineTwo;
return 0;
}
The reason is that cin>>t stops at the first non-numeric character, which is the newline. The next cin.getline(b,100000) will read this newline character into b and "run run" to c.
To avoid this, you can first read the newline character into somewhere else. Like
cin >> t;
// read the newline character
getchar();
while(t--){...}

Readfile is not reading the the blank spaces from my text file?

I am reading in a text file and have found that it will not print the blank characters between the words. I want to read each character a character at a time and then print the character to the output window. The read will read the file but does not show the blank spaces and I have not been able to find out why the blank spaces are being skipped.
Question: Why is my read not reading the blank characters in my test file?
When i find a blank character I want to print the word Blank Space.
Code:
#include "stdafx.h"
#include "iostream"
#include<iostream>
#include<fstream>
void readTestFile()
{
char ch;
std::fstream fin("C:/Users/itpr13266/Desktop/myTest.txt", std::fstream::in);
while (fin >> ch) {
std::cout << "Letter: " << ch << std::endl;
if (ch == ' ') <-- should catch a blank spaces
{
std::cout << "Blank Space" << std::endl;
}
else <-- Just write the letter
{
std::cout << ch << std::endl;
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
readTestFile();
getchar();
return 0;
}
Test File:
This is testing for fprintf...
This is testing for fputs...
Output
Letter: T
T
Letter: h
h
...etc...
The standard input function istream::operator>>() skips all leading whitespace before performing input. If you need to obtain spaces, there are a couple options you can use:
std::noskipws
By setting the std::ios_base::noskipws flag, the stream will not discard leading whitespace and ch will be given the value of each consecutive character. Note that this succeeds only with the overload that takes a char (ch will be given the value of the space). For any other data type this will not work:
while (fin >> std::noskipws >> ch)
{
// ...
}
std::istream::get()
get() is an UnformattedInputFunction function, and thus will not parse the input beforehand.
while (fin.get(ch))
{
// ...
}
std::istreambuf_iterator<>
You can also use iterators to work directly with the buffer. std::istreambuf_iterator<> also doesn't parse the input:
std::copy(std::istreambuf_iterator<char>{fin},
std::istreambuf_iterator<char>{},
std::ostreambuf_iterator<char>{std::cout},
You are performing formatted input, use unformatted input
std::fstream::traits_type::int_type ch;
while((ch = fin.get()) != std::fstream::traits_type::eof()) {
// ...
}
By default, operator>> on streams skips any leading whitespace before parsing the value. This is, for example, what allows you to read the input 30 60 95 with int i,j,k; fin >> i >> j >> k; (otherwise reading j would fail because after the 30, there follows a space, not an integer).
You now have two options if you want to read the spaces as well:
(preferred): Use the member function get() for unformatted reading of a character.
Instruct the stream not to eat whitespace before reading: fin >> std::noskipws >> ch.
Read more about the different iostream methods. In particular, you are using istream's operator>>. Take careful note of how it is designed to work; it uses whitespace as a delimiter and does not store the whitespace.
If you want to read every char from your stream (e.g. a file stream), you should not be using >>, but rather consider using istream::get().
// stream is an istream, such as cin or ifstream
char ch;
while (ch = stream.get()) { }
This worked for me. I set it in a function so you can copy paste. It detects the space, and also the change in line. I tried it with ASCII art and it worked fine.
void print2()
{
char ch;
std::fstream myStream("GameOver.txt", std::fstream::in);
while (myStream.get(ch))
{
std::cout << ch;
}
}

How to signify no more input for string ss in the loop while (cin >> ss)

I used "cin" to read words from input stream, which like
int main( ){
string word;
while (cin >> word){
//do sth on the input word
}
// perform some other operations
}
The code structure is something like the above one. It is compilable. During the execution, I keep inputting something like
aa bb cc dd
My question is how to end this input? In other words, suppose the textfile is just "aa bb cc dd". But I do not know how to let the program know that the file ends.
Your code is correct. If you were interactively inputting, you would need to send a EOF character, such as CTRL-D.
This EOF character isn't needed when you are reading in a file. This is because once you hit the end of your input stream, there is nothing left to "cin"(because the stream is now closed), thus the while loop exits.
As others already answer this question, I would like add this important point:
Since Ctrl-Z on Windows (and Ctrl-D on unix systems) causes EOF to reach, and you exit from the while loop, but outside the while loop you cannot read further input, since the EOF is already reached.
So to enable reading using cin again, you need to clear eof flag, and all other failure flags, as shown below:
cin.clear();
After doing this, you can start reading input using cin once again!
int main() {
string word;
while (cin >> word) {
// do something on the input word.
if (foo)
break;
}
// perform some other operations.
}
Hit Ctrl-Z (Ctrl-D on *nix systems) and hit enter. That sends an EOF and invalidates the stream.
cin >> some_variable_or_manipulator will always evaluate to a reference to cin. If you want to check and see if there is more input still to read, you need to do something like this:
int main( ){
string word;
while (cin.good()){
cin >> word;
//do sth on the input word
}
// perform some other operations
}
This checks the stream's goodbit, which is set to true when none of eofbit, failbit, or badbit are set. If there is an error reading, or the stream received an EOF character (from reaching the end of a file or from the user at the keyboard pressing CTRL+D), cin.good() will return false, and break you out of the loop.
I guess you want to jump out at the end of file.
You can get the value of basic_ios::eof , it returns true at the end of stream.
Take the input from a file. Then you will find that the while loop terminates when your program stops taking input.
Actually cin stops taking input when it finds an EOF marker. Each input file ends with this EOF marker. When this EOF marker is encountered by operator>> it modifies the value of internal flag eofbit into false and consequently the while loop stops.
It helps me to terminate loop by hitting ENTER.
int main() {
string word;
while(getline(cin,word) && s.compare("\0") != 0) {
//do sth on the input word
}
// perform some other operations
}
You can make a check for a special word in input.
F.e. "stop":
int main( ){
string word;
while (cin >> word){
if(word == "stop")
break;
//do sth on the input word
}
// perform some other operations
}
you can try this
string word;
vector<string> words;
while (cin >> word) {
words.push_back(word);
if (cin.get() == '\n')
break;
}
in this way, you don't have to end with CTRL+D(Z). program will quit while sentence end
your program doesn't take in count white spaces. make difference between cin and getline...
here is an example with a trick: the program get input and prints output until you hit twice Enter to quit:
#include <iostream>
#include <string>
using namespace std;
int main(){
char c = '\0';
string word;
int nReturn = 0;
cout << "Hit Enter twice to quit\n\n";
while (cin.peek())
{
cin.get(c);
if(nReturn > 1)
break;
if('\n' == c)
nReturn++;
else
nReturn = 0;
word += c;
cout << word;
word = "";
}
cout << endl;
return 0;
}

cin.eof() functionality

I understand that cin.eof() tests the stream format. And while giving input, end of character is not reached when there is wrong in the input. I tested this on my MSV C++ 2010 and am not understanding the strange results. No matter what I give the input, I am getting Format Error message that is present in the program.
#include <iostream>
using namespace std;
int main()
{
int i;
cin>> i;
if(!cin.eof())
{
cout<< "\n Format Error \n";
}
else
{
cout<< "\n Correct Input \n";
}
getchar();
return 0;
}
Results I expected:
Values for i =
10 => Correct Input but the output is Format Error
12a => Format Error
Could someone explain where I am going wrong. Thanks.
std::cin.eof() tests for end-of-file (hence eof), not for errors. For error checking use !std::cin.good(), the built-in conversion operator (if(std::cin)) or the boolean negation operator (if(!std::cin)).
Use a direct test of the status of the stream with:
while (cin >> i)
{
...
}
For an input stream to enter the EOF state you have to actually make an attempt to read past the end of stream. I.e. it is not enough to reach the end-of-stream location in the stream, it is necessary to actually try to read a character past the end. This attempt will result in EOF state being activated, which in turn will make cin.eof() return true.
However, in your case you are not only not doing that, you (most likely) are not even reaching the end of stream. If you input your 10 from the keyboard, you probably finished the input by pressing the [Enter] key. This resulted in a new-line character being added to the input stream. So, what you are actually parsing with >> operator in this case is actually a 10\n sequence. Since you requested an int value from the stream, it only reads the numerical characters from the stream, i.e. it reads 1 and 0, but it stops at \n. That \n remains in the stream. You never read it. So, obviously, your code never reaches the end-of-file position in the stream. You have to reason to expect cin.eof() to become true in such case.
#include <iostream>
int main() {
using namespace std;
int i;
if (cin >> i) {
cout << "Extracted an int, but it is unknown if more input exists.\n";
char c;
if (cin.get(c)) { // Or: cin >> c, depending on how you want to handle whitespace.
cin.putback(c);
cout << "More input exists.\n";
if (c == '\n') { // Doesn't work if you use cin >> c above.
cout << "But this was at the end of this line.\n";
}
}
else {
cout << "No more input exists.\n";
}
}
else {
cout << "Format error.\n";
}
return 0;
}
Also see Testing stream.good() or !stream.eof() reads last line twice.
Sample session with the above program, note that input lines are marked with comments not present in the actual output:
$ your-program
12 # input
Extracted an int, but it is unknown if more input exists.
More input exists.
But this was at the end of this line.
$ your-program
12a # input
Extracted an int, but it is unknown if more input exists.
More input exists.
$ echo -n 12 | your-program
Extracted an int, but it is unknown if more input exists.
No more input exists.
$ your-program
a # input
Format error.
Assuming your input is line based, I suggest that you read the whole line using std::getline(). Once you have the line, you can analyse it and decide whether it contains correct or wrong input. Put the line into std::istringstream and do something like the following:
Edit: Changed !! iss to static_cast<bool>(iss) for compatibility with C++0x.
std::istringstream iss (line);
char ch;
long lval;
// read the input
iss >> lval;
// result variable will contain true if the input was correct and false otherwise
result
// check that we have read a number of at least one digit length
= static_cast<bool>(iss)
// check that we cannot read anything beyond the value read above
&& ! (iss >> ch);
Adding to the previous answer:
After reading your input (like 10), you are not at end-of-file, as you can easily type some more. How is the system to know that you will not?
When reading your second input (12a), it correctly reads all the digits that can be part of an integer. The letter 'a' cannot, so it is left for some possible later input. For example, you can read all parts of 12a with this code
int i;
char c;
cin >> i >> c;
cin.eof() test if the stream has reached end of file which happens if you type something like Ctrl+C (on Windows), or if input has been redirected to a file etc.
To test if the input contains an integer and nothing but an integer, you can get input first into a string and then convert that with a stringstream. A stringstream indeed reaches eof if there's no more to be extracted from it.
#include <iostream>
#include <sstream>
#include <string>
int main() {
using namespace std;
int i;
string input;
cin >> input; //or getline(cin, input)
stringstream ss(input);
if (ss >> i && ss.eof()) { //if conversion succeeds and there's no more to get
cout<< "\n Correct Input \n";
}
else {
cout<< "\n Format Error \n";
}
return 0;
}