' ' seems to be treated as '\0'? - c++

Code
I created the following program:
#include <iostream>
void f(char v[])
{
for(char* p = v; *p != 0; p++)
{
std::cout << *p << std::endl;
}
}
int main()
{
std::cout << int(' ') << std::endl;
char c[256];
std::cin >> c;
f(c);
return 0;
}
Compiler
I compiled with GNU GCC Compiler in Code::Blocks with the -std=c++0x flag (with no warnings).
Problem
The problem I have is that if I enter a string containing one or more spaces (i.e. "one and two") then only the letters prior to the first space are printed (i.e. 'o', 'n', 'e').
What I've tried
The only thing that sprung to mind was to do a quick reality check. I added the line:
std::cout << "Val: " << int(' ') << std::endl;
and, as expected, the value printed isn't 0 (because, obviously, it's not the null '\0' character)...
I'm not sure what I'm missing. Is it the case that the line:
std::cin >> c;
uses ' ' as some sort of termination character?
Thanks.

std::cin >> c;
will only read one word delimited by whitespace. That's the functionality for all the >> operators.
If you want to read a whole line, use the getline function instead.

Stream operators >> are formatted input, which uses whitespace as field separators. If you want to retain whitespace in your input, use std::getline() or the stream member function read().

Try getline to input your sentence, space is used as a delimiter between inputs by cin>>.

Related

Skip leading whitespaces but not the newline C++ istreams

I am trying to remove leading whitespace and store the characters after the whitespace. I don't want the newline to be considered
This is a file that I am reading from:
Map: Out of planet
Player: Max
My expected result and what I am looking for should be
cout << kill.killMap << endl;
Out of planet // NOTICE THERE IS NO WHITESPACE
cout << kill.player << endl;
Max // NOTICE THERE IS NO WHITESPACE
If the file looks like this...
Map:
Player: Max
Nothing should be stored in the map variable and player variable.
Although the ws function removes whitespace from the stream, I don't think it does the same with char arrays. Would really appreciate it if someone could tell me a way of getting ws to work or just simply an efficient way of removing the whitespace
This is what I am getting:
cout << kill.killMap << endl;
Out of planet //THERE IS WHITESPACE
cout << kill.player << endl;
Max //THERE IS WHITESPACE
Is there a way of doing this without using C++ strings or Vectors. I intend on using C Style strings
THIS IS MY EDITED CODE, HOWEVER IT DOESN'T WORK IF THERE ARE VALID CHARACTERS AFTER THE DELIMITER :... WOULD REALLY APPRECIATE IT IF SOMEONE COULD FIX MY CODE, WOULD MEAN A LOT TO ME.
istreams.get(characters, 50, ':');
istreams.get(c);
istreams.getline(kill.killMap, 35);
while ((is.get(c) != "\n") && (is.get(c) != '\0') )
{
is >> ws;
}
is.getline(kill.killMap, DATA_FILE_SIZE);
if(kill.killMap[0] = '\0)
{
cout << "Error;
break;
}
istreams >> ws;
istreams.get(characters, 50, ':');
istreams.get(c);
while ((is.get(c) != "\n") && (is.get(c) != '\0') )
{
is >> ws;
}
istreams.getline(kill.player, 35);
if(kill.player[0] = '\0)
{
cout << "Error;
break;
}
You can do something like this:
void eatwhites(istream& stream)
{
const string skip=" \t";//put here all wanted skip chars (here i put only SPACE and TAB
while(string::npos != skip.find(stream.peek())){ //if next char in stream exist in skip string
stream.ignore();//then ignore it (1 character).
}
}
EDIT
Here is how i tested it and it works for me:
note you still have to trim the string after you read it, means put the '\0' after the last non white character.
if there is a problem you can tell what input it was and what have you got.
int main()
{
string s1,s2;
eatwhites(cin);
getline(cin,s1, ':');//read until ":"
eatwhites(cin);
getline(cin,s2); //read until "\n"
cout<<"'"<<s1<<"':'"<<s2<<"'"<<endl;
return 0;
}
inputs I've tried:
[SPACE] 123:[SPACE] 456 gives: '123':'456'
[SPACE] 123:[SPACE] gives: '123':''
EDIT2:
With char array it can be used just the same, like this:
#define MAX_FIELD 128
int main()
{
char s1[MAX_FIELD],s2[MAX_FIELD];
eatwhites(cin);
cin.getline(s1, MAX_FIELD, ':');
eatwhites(cin);
cin.getline(s2, MAX_FIELD);
cout<<"'"<<s1<<"':'"<<s2<<"'"<<endl;
return 0;
}
Same results for same input.

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;
}
}

C++ getline method not working

I'm sorry but I'm quite new to C++ but not programming in general. So I tried to make a simple encryption/decryption. However when I added the modification to my previous code (so there isn't two programs for encrypting and decrypting) I found that the code 'getline()' method no longer works. Instead it's just ignoring it when the code is ran. Here's the code:
int main(){
std::string string;
int op = 1; //Either Positive or Negative
srand(256);
std::cout << "Enter the operation: " << std::endl;
std::cin >> op;
std::cout << "Enter the string: " << std::endl;
std::getline(std::cin, string); //This is the like that's ignored
for(int i=0; i < string.length(); i++){
string[i] += rand()*op; //If Positive will encrypt if negative then decrypt
}
std::cout << string << std::endl;
std::getchar(); //A Pause
return 0;
}
That's because std::cin >> op; leaves a hanging \n in your code, and that's the first thing getline reads. Since getline stops reading as soon as it finds a newline character, the function returns immediately and doesn't read anything more. You need to ignore this character, for example, by using cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); (std::numeric_limits is defined in header <limits>), as stated on cppreference.
This is because you still have the newline character in the buffer which makes getline() stop reading as soon as it encounters it.
Use cin.ignore() to ignore the newline character from the buffer. This will do in your case.
In general, if you want to remove characters from your buffer untill a specific character, use:
cin.ignore ( std::numeric_limits<std::streamsize>::max(), ch )
Use :
cin.ignore ( std::numeric_limits<std::streamsize>::max(), '\n' );
to eat newlines from previous input std::cin >> op;
header - <limits>
Other way would be :
while (std::getline(std::cin, str)) //don't use string
if (str != "")
{
//Something good received
break;
}
As other stated already, the formatted input (using in >> value) start skipping space abd stop when they are done. Typically this results in leaving some whitespace around. When switching between formatted and unformatted input you typically want to get rid of leading space. Doing so can easily be done using the std::ws manipulator:
if (std::getline(std::cin >> std::ws, line)) {
...
}
You must use std::cin.ignore() before std::getline(std::cin, string) to clear the buffer, because when you use std::cin >> op before the getline a \n gets in the buffer and std::getline() reads it. std::getline() takes only the line you type, when you skip a line, std::getline() closes, so when std::getline() picks up \n from the buffer it is already terminated before you type something, because /n skips a line.
Try this way:
int main(){
std::string string;
int op = 1; //Either Positive or Negative
srand(256);
std::cout << "Enter the operation: " << std::endl;
std::cin >> op;
std::cout << "Enter the string: " << std::endl;
std::cin.ignore();
std::getline(std::cin, string); //This is the like that's ignored
for(int i=0; i < string.length(); i++){
string[i] += rand()*op; //If Positive will encrypt if negative then decrypt
}
std::cout << string << std::endl;
std::getchar(); //A Pause
return 0;
}

Stringstream don't copy new lines

Special characters disappear when I pass a string into a stringstream.
I tried this code which can directly be tested:
#include <iostream>
#include <sstream>
using namespace std;
int main(int argc, char* argv[]) {
string txt("hehehaha\n\t hehe\n\n<New>\n\ttest:\t130\n\ttest_end:\n<New_end>\n");
cout << txt << endl; // No problem with new lines and tabs
stringstream stream;
stream << txt;
string s;
while(stream >> s) {
cout << s; // Here special characters like '\n' and '\t' don't exist anymore.
}
cout << "\n\n";
return 0;
}
What can I do to overcome this?
Edit: I tried this:
stream << txt.c_str();
and it worked. But I don't know why...
basically, you are just printing it wrong, it should be:
cout << stream.str() << endl;
Some details. You are calling operator<<(string) which
overloads operator<< to behave as described in ostream::operator<<
for c-strings
The referred to behaviour is explained here:
(2) character sequence Inserts the C-string s into os. The terminating
null character is not inserted into os. The length of the c-string is
determined beforehand (as if calling strlen).
Strlen documentation says that the result is affected by nothing but
the terminating null-character
Indeed, strlen(tmp) in your examples outputs 55.
The stream, hence, gets "assigned" everything which comes up to the 55th character in your input string.
cout << stream.str() << endl;
will show you that this is indeed what happens.
A parenthesis: you can modify the behaviour of the stream << txt line by means of setting/unsetting flags, as in
stream.unsetf ( std::ios::skipws );
which you should try out.
The statement
while(stream >> s)
Is the problem, it gives you one token on each call, using white spaces for splitting and therefor ignoring them.

whitespace identification in c++

My code has to identify whitespace characters using cin, so when I use space as an input it should identify the space. How do I do this?
You can use std::noskipws to disable the whitespace skipping that std::cin does by default:
#include <iostream>
#include <iomanip>
int main() {
char c;
std::cin >> std::noskipws;
while (std::cin >> c) {
if (c == ' ')
std::cout << "A space!" << std::endl;
}
return 0;
}
string str;
getline(cin, str); // get the whole line
If you want to deal with c-strings you could use the mentioned cin.getline(....) which is different from strings getline.
Cin breaks on whitespace, of any kind. If you need to read an entire line, you need to use the get line function:
getline(cin, line);
Where line is a std::string. This will still cut off any new lines or carriage returns.
To test the string for spaces examine every character in the string and compare it to the space character " ". That is left as an exercise for the reader ;)
Use cin.getline to read the line with the space.
http://www.cplusplus.com/reference/iostream/istream/getline/