Testing for a space character inside a string...? - c++

I'm trying to test if a character in a string is a space, and I'm getting extremely frustrated:
string my_string;
cin >> my_string;
for (int i = 0; i < my_string.length(); i++)
{
if (my_string[i] == ' ') // this never becomes true...
{
cout << "this text should pop, but never does" << endl;
}
}
I'm not getting any errors and I've looked online, but people on different forums say this is how to test for a space. Uh.

when you say
cin >> my_string;
you are taking formatted input. std::cin discards any whitespace in that line, and it reads up to and yields only a single word.
try instead
std::string my_string;
std::getline(std::cin, my_string);
to get a single line, or
#include <iterator>
// ...
std::string my_string((std::istreambuf_iterator<char>(std::cin)),
std::istreambuf_iterator<char>());
to get everything up to an end-of-file mark into the string.

Thats because cin stops reading at the first whitespace so you never actually read the entire sentence but the first word. Use getline instead.
std::string my_string;
std::getline(std::cin, my_string);
for (int i = 0; i < my_string.length(); i++)
{
if (my_string[i] == ' ') // this never becomes true...
{
std::cout << "this text should pop, but never does" << std::endl;
}
}

Additionnally to test whether a space is present use std::string::find!
std::string my_string;
std::cin >> my_string; // please do not use « using namespace std; » if possible
size_t space_position = my_string.find(' ');
if(space_position != std::string::npos)
{
std::cout << "found space" << std::endl;
}

Related

C++ I don't know how to find a word(eg.banana,sandwich) inside of a string(sentence) THE USER ENTERS the sentence and then write that word out

I've tried this but I'm stuck honestly.
I'm trying to find the first character, and then search for the ending of that substring (for eg. if the word is "sandwich" and it finds 's' that it figures out that its "sandwich") and then write out the word sandwich. And also I'm new to C++.
#include<iostream>
#include<string>
using namespace std;
int main()
{
string s, word;
char a;
cout << "Enter the sentence that you desire: ";
getline(cin, s);
cout << "Enter the letter that you want: ";
cin >> a;
for (int i = 0; i < s.length; i++)
{
if (s[i] == a)
{
if (s[i] == '\0')
{
word = s;
cout << word;
}
}
}
return 0;
}
The request is a bit foggy but given also the code you posted, i think i got a heck of what you intend to do.
The easiest (yet not necessarily the most performing one) is to use a stringstream, more precisely an istringstream.
You basically build it with a string (the one you passed from keyboard) and then you use it as if it was your cin (it acts as a normalized istream).
At that point you can iterate each word of the sentence and check the first letter.
The first character of a string is either myString[0] or myString.front(). That is up to you.
the code should look like this :
#include <iostream> //cin/cout
#include <sstream> //istringstream
using namespace std ;
int main()
{
//first of all let's get our sentence AND the character you want
cout << "insert sentence here: " ;
string sentence ;
getline(cin, sentence) ;
cout << "insert the character here: " ;
char letter ;
cin >> letter ;
//then let's create an istringstream with said sentence
istringstream sentenceStream(sentence) ;
//let's then iterate over each word
string word ;
while(sentenceStream >> word)
{
//and see if the word starts with the letter we passed by keyboard
if(word.front() == letter)
{
cout << "the word \"" << word << "\" starts with '" << letter << "'\n" ;
}
}
return 0 ;
}
Just a couple of hints:
iostream includes string already, there is no need to re-include it.
[Edit] (as pointed out by whozcraig, this does not follow the standard. guards will "negate" the double inclusion anyway, so yes, including string is not a mistake. as specified in the comment, i'm yet to find an implementation of iostream that does not include string)[/Edit]
It is good practice not to call a variable 's', or 'a': use a name
that makes it recognizable.
You can find the end of a word with std::find_if:
#include <algorithm>
#include <string>
template <typename Is>
std::string find_word(Is& stream, char needle) {
auto const nonword = [](char c) {
if ('a' <= c && c <= 'z') return false;
if ('A' <= c && c <= 'Z') return false;
if (c == '-') return false;
return true;
};
for (std::string w; stream >> w;) {
if (w.size() && w[0] == needle) {
auto const last = std::find_if(std::begin(w),std::end(w),nonword);
return std::string(std::begin(w),last);
}
}
return "";
}
This takes any stream as argument, including std::cin, and can be invoked like this:
std::cout << find_word(std::cin,'w') << "\n";
It is important to specifically find the last character in each chunk handed you by the stream because the streams will only cut along whitespace by default. So if you enter a sentence:
Hello world!
You want the end of the word to be 'd', not '!'.

C++ User defined string needs to contain spaces (but not allowed by program..?)

I'm working on homework for my c++ class, and it's been quite awhile since I've used it. I was wondering if there was a way to allow spaces in a string (instead of it nulling out and ending the string)
my current code is this:
int chapter10() {
string strinput;
char charstr[1000];
int numwords=1;
cout << "Enter a phrase ";
cin >> strinput;
cout << strinput;
const int size = strinput.size() + 1;
strcpy_s(charstr, strinput.c_str());
cout << strinput << endl;
for (int i = 0; i != size; i++) {
if (*(charstr + i) == ' ')
numwords++;
}
cout << "There are " << numwords << " words in that string." << endl;
return 0;
}
The problem I'm having, is for instance, if I type "Hello World" and press enter, it pops the next line (right after the cin) and says "Hello", and the space made it cut the rest of the phrase off.
How does one fix this issue? I don't want to use the str:: things as I barely know what they are, and have really never had to use them, and that would look a bit suspicious to the teacher :P
Update: If you've suggested using getline(cin, strinput); It doesn't work too well. I can from what I see, only type in the 10 to reach my function, but after I press enter, it thinks that I've presses something else, which makes it completely skip the cin to get the string value. But, there is something weird with this, if I type "10 hello world" it does everything correctly. Well, with the exception that it needs to be in the same line as the number to reach the function.
Solved: The use of getline(cin, strinput) works perfectly fine, if you're not using user input before hand. If you are, you're going to need a cin.ignore before the getline(). As stated in the comment by my best answer.
#include <iostream>
#include <iomanip>
#include <string>
#include <limits>
using namespace std;
//~~~Initialize all functions
int chapter10();
//~~~Initializing complete
int main() {
srand(time(0)); //makes rng thingy work instead of choose same numbers cause it doesn't do it on its own. lol
cout << "Enter the chapter number you need to look at: ";
int chapterNumber;
cin >> chapterNumber;
switch (chapterNumber) {
case 1: testingStuff(); break;
case 9: chapter9(); break;
case 10: chapter10(); break;
default: cout << "You chose an invalid chapter number, reload the program."; break;
}
system("pause");//So console doesn't close instantly cause that's not annoying at all...
}
int chapter10() {
string strinput;
char charstr[10000];
int numwords=1;
cout << "Enter a phrase." << endl;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
getline(cin, strinput);
const int size = strinput.size() + 1;
strcpy_s(charstr, strinput.c_str());
for (int i = 0; i != size; i++) {
if (*(charstr + i) == ' ' & *(charstr + (i+1)) != ' ' )//the & is fail safe so multiple space no ++numwords
numwords++;
}
cout << "There are " << numwords << " words in that string." << endl;
return 0;
}
The way I have my code written was I used a switch/case to reach my function. This required user input, which in turn caused my program to 'think' I was still typing for the second input required in the chapter10 function.
Adding in the line of code: cin.ignore(numeric_limits<streamsize>::max(), '\n'); allowed me to cancel the input, and start a new one.
If you want to get all characters an end-user enters on a single line, use getline: instead of cin >> strinput write this:
getline(cin, strinput);
The fact that it is actually std::getline(std::cin, strinput) makes no difference, because your code uses std namespace anyway. In case you were wondering what std:: prefix is, it's a namespace of the Standard C++ library.
You can use getline() function
It copies into a string till a newline is reached or delimiter is found - so it will accept all the spaces till newline is reached
http://www.cplusplus.com/reference/string/string/getline/
or you can also use cin.getline() as shown here -
std::cin input with spaces?
use:
cin >> noskipws >> strinput;
Use std::getline() function. Example:
#include <iostream>
#include <vector>
#include <sstream>
void WordCounter(
const std::vector<std::string> & lines) {
for (int i = 0; i < lines.size(); ++i) {
std::istringstream iss(lines[i]);
std::string word;
int count = 0;
while (iss >> word) {
++count;
}
std::cout << "Line #" << i << " contains " << count << " words." <<
std::endl;
}
}
int main() {
std::string line;
std::vector<std::string> lines;
while (std::getline(std::cin, line)) {
lines.push_back(line);
}
WordCounter(lines);
return 0;
}

How do I remove punctuaution from a string

I am seeking help on a code that reads a string of characters with punctuation included and outputs what was read with the punctuation omitted. I paid a visit to this link C++ Remove punctuation from String I believe my code is solid. When I compile the code it prompts for the string. However upon entering the string and pressing enter, nothing happens there is no output afterwards I've tweaked the code extensively, but to no avail.
int main(){
string line;
cout <<"Please Enter a line"<< endl;
while(getline(cin, line)){
for(decltype(line.size()) index = 0; index != line.size() && !isspace(line[index]); ++index){
if (ispunct(line[index])){
line.erase(index--,1);
line[index] = line.size();
}
}
}
cout<< line << endl;
return 0;
}
You are making this way more complicated (decltype? for this?) than it needs to be. Try:
int main()
{
std::string line;
std::cout <<"Please Enter a line"<< std::endl;
while(std::getline(std::cin, line)){
const char* s = line.c_str();
while(*s){
if (!ispunct(*s)){
std::cout << *s; // not as slow as you would think: buffered output
}
++s;
}
std::cout << std::endl; // flush stdout, that buffering thing
}
}
Simpler is usually better. As a side bonus, this should also be quite a bit faster.
This can be done without any loops. Usage of the algorithm functions is all you need.
In general, if you have a container, and you want to remove items from the container that satisfy a certain condition, you're using a long (and maybe, wrong) approach if you're writing hand-coded loops as you are doing.
Here is an example of usage of the algorithm functions, namely std::remove_if.
#include <algorithm>
#include <cctype>
#include <string>
#include <iostream>
using namespace std;
int main()
{
std::string s = "This is, a, string: with ! punctuation.;";
s.erase(std::remove_if(s.begin(), s.end(), ::ispunct), s.end());
cout << s;
}
Live Example: http://ideone.com/Q6A0vJ
The reason why your code doesn't output anything is because it is stuck in that getline loop.
assuming c++11:
int main(){
string line;
cout <<"Please Enter a line"<< endl;
getline(cin, line);
line.erase(std::remove_if(line.begin(), line.end(),
[](char ch) { return ispunct(ch) ? true : false; }), line.end());
cout << line << endl;
return 0;
}
or
int main(){
string line;
cout <<"Please Enter a line"<< endl;
transform(line.begin(), line.end(), line.begin(),
[](char ch) { return ispunct(ch) ? '\0' : ch; });
cout << line << endl;
return 0;
}

How can I check a string to see if a carriage return exists in C++?

vector<string> wordstocheck;
in.open("readin.txt");
string line;
string word = "";
int linecount = 0;
while (getline(in, line))
{
//cout << line << endl;
for (int i = 0; i < line.size(); i++)
{
if(isalpha(line[i]))
{
word.push_back(tolower(line[i]));
}
else if (line[i] == ' ' || ispunct(line[i]) || line[i] == '\n')
{
wordstocheck.push_back(word);
word = "";
}
}
linecount++;
}
for (int i = 0; i < wordstocheck.size(); i++)
{
cout << wordstocheck[i] << endl;
}
system("pause");
}
The code above reads in the following from a .txt file:
If debugging is the
process of removing bugs.
Then programming must be the
process of putting them in.
I'm trying to get the program to recognize each word, and save that individual word into a vector, and then print that vector of words out. It does pretty well with the exception of the two 'the's on the first and third lines.
Output:
if
debugging
is
theprocess
of
removing
bugs
then
programming
must
be
theprocess
of
putting
them
in
Press any key to continue . . .
It doesn't split up "theprocess" as I had hoped.
getline won't read the newline. However, in this case it's relatively simple to work around this problem.
Where you currently have linecount++;, add these lines before it:
if (word != "")
{
wordstocheck.push_back(word);
word = "";
}
You may want to use the same if (word != "") on the first place where you push the word onto wordstocheck since if the text has "A Word", you'd add the word "A" followed by an empty word for as the seconds space triggers the word to be added to the list.
As an alternative, you could get rid of getline, and just use int ch = in.get() to read a character at a time from the input. Then instead of counting lines inside the while()..., and use ch instead of line[i] al through the loop, and then add a second if inside the else if section, which checks for newline and counts up linecount. This would probably make for shorter code.
I believe the problem is that you're expecting the newline character to be included in the result from getline(), which it isn't. It seems like if you take the two lines you already have in that block:
wordstocheck.push_back(word);
word = "";
And add them alongside the line:
linecount++;
Then it should work as you expect.
If you want to read a word at a time, why use std::getline in the first place?
// read the words into a vector of strings:
std::vector<std::string> words{std::istream_iterator<std::string(in),
std::istream_iterator<std::string()};
You can use std::for_each or std::transform to convert everything to lower case, and finally print them out with for (auto const &w : words) std::cout << w << "\n";
So far i know, getline reads a whole line and does not recognize a carriage return. The only way i know is to read the file, by read it char by char.
Here is a example that gives the correct result:
#include <iostream> // std::cin, std::cout
#include <fstream> // std::ifstream
int main ()
{
char str[256];
int line = 1;
int charcount = 0;
std::cout << "Enter the name of an existing text file: ";
std::cin.get (str,256);
std::ifstream is(str);
if (!is)
{
std::cerr << "Error opening file!" << std::endl;
return -1;
}
char c;
while ((c = is.get()) && is.good()) // loop while extraction from file if possible
{
if (c == 10 || c == 13 || c == 32) // if it is a line break or carriage return or space
{
std::cout << std::endl;
line++;
}
else // everything else
{
std::cout << c;
charcount++;
}
}
is.close();
std::cout << std::endl; // close file
std::cout << line << " lines" << std::endl;
std::cout << charcount << " chars" << std::endl;
return 0;
}

std::cin:: and why a newline remains

Reference Why is the Console Closing after I've included cin.get()?
I was utilizing std::cin.get()
#include<iostream>
char decision = ' ';
bool wrong = true;
while (wrong) {
std::cout << "\n(I)nteractive or (B)atch Session?: ";
if(std::cin) {
decision = std::cin.get();
if(std::cin.eof())
throw CustomException("Error occurred while reading input\n");
} else {
throw CustomException("Error occurred while reading input\n");
}
decision = std::tolower(decision);
if (decision != 'i' && decision != 'b')
std::cout << "\nPlease enter an 'I' or 'B'\n";
else
wrong = false;
}
I read basic_istream::sentry and std::cin::get.
I chose instead to use std::getline as the while loop is executing twice because the stream is not empty.
std::string line; std::getline(std::cin, line);
As the reference I posted above states within one of the answers, std::cin is utilized to read a character and std::cin::get is utilized to remove the newline \n.
char x; std::cin >> x; std::cin.get();
My question is why does std::cin leave a newline \n on the stream?
Because that's its default behavior, but you can change it. Try this:
#include<iostream>
using namespace std;
int main(int argc, char * argv[]) {
char y, z;
cin >> y;
cin >> noskipws >> z;
cout << "y->" << y << "<-" << endl;
cout << "z->" << z << "<-" << endl;
}
Feeding it a file consisting of a single character and a newline ("a\n"), the output is:
y->a<-
z->
<-
It's pretty simple. For example if you would like to write a file with stored names of cities when reading it you wouldn't want to read names with newline characters.
Besides that '\n' is character as good as any other and by using cin you are just fetching one character so why should it skip over anything?
In most use cases when reading char by char you don't want to skip any character because probably you want to parse it somehow, When reading string you don't care about white spaces and so on.