This should accept only letters, but it is not yet correct:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
std::string line;
double d;
while (std::getline(std::cin, line))
{
std::stringstream ss(line);
if (ss >> d == false && line != "") //false because can convert to double
{
std::cout << "its characters!" << std::endl;
break;
}
std::cout << "Error!" << std::endl;
}
return 0;
}
Here is the output:
567
Error!
Error!
678fgh
Error!
567fgh678
Error!
fhg687
its characters!
Press any key to continue . . .
fhg687 should output error because of the numbers in the string.
Accepted output should contain letters only, such as ghggjh.
You'd be much better off using std::all_of on the string, with an appropriate predicate. In your case, that predicate would be std::isalpha. (headers <algorithm> and <cctype> required)
if (std::all_of(begin(line), end(line), std::isalpha))
{
std::cout << "its characters!" << std::endl;
break;
}
std::cout << "Error!" << std::endl;
Updated: to show a fuller solution.
The simplest approach would probably be to iterate through each char in the input and check whether that char is within English-letter ranges in ascii (upper + lower):
char c;
while (std::getline(std::cin, line))
{
// Iterate through the string one letter at a time.
for (int i = 0; i < line.length(); i++) {
c = line.at(i); // Get a char from string
// if it's NOT within these bounds, then it's not a character
if (! ( ( c >= 'a' && c <= 'z' ) || ( c >= 'A' && c <= 'Z' ) ) ) {
std::cout << "Error!" << std::endl;
// you can probably just return here as soon as you
// find a non-letter char, but it's up to you to
// decide how you want to handle it exactly
return 1;
}
}
}
You can also use regular expressions, which may come in handy if you need more flexibility.
For this question, Benjamin answer is perfect, but just as a reference, this is how regex could be used (notice that regex is also part of the C++11 standard):
boost::regex r("[a-zA-Z]+"); // At least one character in a-z or A-Z ranges
bool match = boost::regex_match(string, r);
if (match)
std::cout << "it's characters!" << std::endl;
else
std::cout << "Error!" << std::endl;
If string contains only alphabetic characters and at least one of them (the +), then match is true.
Requirements:
With boost: <boost/regex.hpp> and -lboost_regex.
With C++11: <regex>.
Related
I need to make a program which converts all letters to uppercase.
But first I need to get an input from the user. And I need to check if there are characters that are not space or alphabet.
This is what I tried.
#include <iostream>
#include <cctype>
using namespace std;
int main()
{
string s;
cout << "Enter a string: ";
while (getline(cin, s)){
for (int i = 0; i<s.length(); i++){
if ((isspace(s[i]) || isalpha(s[i]))){
for (int i = 0; i < s.length(); i++){
s[i] = toupper(s[i]);
}
cout << s << endl;
return 1;
}
cout << "Invalid string. Please input only alphabets or space character. " << endl << "Enter a string: ";
}
}
//if the input value is valid convert and print
return 0;}
This program successfully make error messages to pure numbers and pure question marks. But the problem is if there are invalid characters and valid characters mixed in the input, it cannot distinguish it.
For example, if input is "Hi?", the program thinks its a valid input. But with questions marks, the string should be invalid.
I think the for statement is the problem. How can I solve this?
I've made a few changes to deal with the break out conditions in your loops without changing the structure of your program too much.
Here's one example how you could get it to work. Comments in the code.
#include <cctype>
#include <iostream>
#include <string>
int main() {
std::string s;
while(std::cout << "Enter a string: " && std::getline(std::cin, s)) {
bool valid = true; // will stay true unless at least one char is invalid
for(char& ch : s) { // use a range-based for loop
// ch is now a reference to the char in the string
// convert to unsigned char - these functions are not safe
// otherwise:
if(std::isspace(static_cast<unsigned char>(ch)) ||
std::isalpha(static_cast<unsigned char>(ch)))
{
ch = std::toupper(static_cast<unsigned char>(ch));
continue; // continue to check the next character
}
std::cout << "Invalid character ('" << ch << "') in string.\n"
"Please input only alphabets or space character.\n";
valid = false; // to let the user enter a new string
break; // no need to check more characters, the string is invalid
}
if(valid) break; // break out only if all characters are valid
}
if(std::cin)
std::cout << "The valid string is now " << s << '\n';
}
A similar program could use algorithms from <algorithm> to do the check and the transformation of the string to uppercase.
Example:
#include <algorithm>
#include <cctype>
#include <iostream>
#include <string>
int main() {
std::string s;
// the manual loop replaced by a simple algorithm that checks if any
// character in the string is invalid by using a lambda, here called
// "is_invalid":
auto is_invalid = [](unsigned char ch) {
return !(std::isspace(ch) || std::isalpha(ch));
};
while(std::cout << "Enter a string: " &&
std::getline(std::cin, s) &&
std::any_of(s.begin(), s.end(), is_invalid))
{
std::cout << "Invalid character in string.\n"
"Please input only alphabets or space character.\n";
}
if(std::cin) {
// transform the valid string to uppercase using another lambda.
// the lambda is here only to make the chars into unsigned chars
// to make the use of std::toupper safe
auto to_upper = [](unsigned char ch) { return std::toupper(ch); };
std::transform(s.begin(), s.end(), s.begin(), to_upper);
std::cout << "The valid string is now " << s << '\n';
}
}
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 '!'.
So far, this is my code:
while(bet > remaining_money || bet < 100)
{
cout << "You may not bet lower than 100 or more than your current money. Characters are not accepted." << endl;
cout << "Please bet again: ";
cin >> bet;
}
It works fine but I'm trying to figure out how to make it loop if the user inputs anything that isn't a number as well.
When I press a letter or say a symbol/sign, the code just breaks.
Using the function
isdigit()
This function returns true if the argument is a decimal digit (0–9)
Don't forget to
#include <cctype>
I would use std::getline and std::string to read the whole line and then only break out of the loop when you can convert the entire line to a double.
#include <string>
#include <sstream>
int main()
{
std::string line;
double d;
while (std::getline(std::cin, line))
{
std::stringstream ss(line);
if (ss >> d)
{
if (ss.eof())
{ // Success
break;
}
}
std::cout << "Error!" << std::endl;
}
std::cout << "Finally: " << d << std::endl;
}
A good way of doing this is to take the input as a string. Now find the length of the string as:
int length = str.length();
Make sure to include string and cctype. Now, run a loop that checks the whole string and sees if there is a character that is not a digit.
bool isInt = true;
for (int i = 0; i < length; i++) {
if(!isdigit(str[i]))
isInt = false;
}
If any character is not a digit, isInt will be false. Now, if your input(a string) is all digits, convert it back to an integer as:
int integerForm = stoi(str);
Store integerForm in your array.
In a C++ code, I'm trying to search for a word in a sentence but it keeps doing partial search. I want it to search only for the complete word not parts of it too, any help?
size_t kk;
string word="spo";
string sentence="seven spoons";
kk=sentence.find(word);
if (kk !=string::npos)
cout << "something" << endl;
It sounds like what you want is handled by the concept of word boundaries or word characters in regular expressions.
Here's a program that will return only a complete match. That is, it will only return a word if that word completely matches the exact word you're searching for. If some word in sentence has your target word as a strict substring then it will not be returned.
#include <regex>
#include <string>
#include <iostream>
int main() {
std::string word = "spo"; // spo is a word?
std::string sentence = "seven spoons";
std::regex r("\\b" + word + "\\b"); // the pattern \b matches a word boundary
std::smatch m;
if (std::regex_search(sentence, m, r)) { // this won't find anything because 'spoons' is not the word you're searching for
std::cout << "match 1: " << m.str() << '\n';
}
sentence = "what does the word 'spo' mean?";
if (std::regex_search(sentence, m, r)) { // this does find the word 'spo'
std::cout << "match 2: " << m.str() << '\n';
}
}
Or alternatively maybe you mean you want to find any word that matches a partial word you're searching for. regex can do that as well:
std::string partial_word = "spo";
std::regex r("\\w*" + partial_word + "\\w*"); // the pattern \w matches a word character
This produces:
match 1: spoons
match 2: spo
There are a bunch of options here:
a) Search for [space]WORD[space] instead of just WORD
string word="spo";
string sentence="seven spoons";
kk=sentence.find(" "+word+" ");
Note that this wont work, if your words are separated by newline characters or other white spaces.
b) Split the string into words, store them in a vector, and check if the desired word is somewhere in the vector, by using std::find.
stringstream parser(sentence);
istream_iterator<string> start(parser);
istream_iterator<string> end;
vector<string> words(start, end);
if(find(words.begin(), words.end(), word)!=words.end()) cout<<"found!";
If you're gonna search for words often, this maybe the best choice, since you can store the vector somewhere for future reference, so you don't have to split it. Also - if you want this to work, be sure to #include <algorithm> and #include <vector>.
c) Search for the word and check if isspace(string[position-1]) && isspace(string[position+wordLength])
string word="spo";
string sentence="seven spoons";
kk=sentence.find(" "+word+" ");
if(kk!=string::npos){
if((kk==0 || isspace(sentence[kk-1])) && (kk+word.length()==sentence.length() || isspace(kk+word.length()+1)))
cout << "found!";
}
Something like this :
std::size_t kk;
std::string word="spoo";
std::string sentence="seven spoons tables";
std::stringstream ss(sentence) ;
std::istream_iterator<std::string> f ;
auto it =std::find_if( std::istream_iterator<std::string> (ss),
f,
[=](const std::string& str){
return str == word;
}
);
if(it != f )
std::cout << "Success" <<std::endl;
See here
I think the best way is to split your string using whitespace and punctuation characters as delimiters, then use std::find on the result.
#include <boost/algorithm/string.hpp>
#include <vector>
#include <string>
#include <algorithm>
int main()
{
std::string word="spo";
std::string sentence="seven spoons";
std::vector<std::string> words;
boost::split(words, sentence, boost::is_any_of("\n\t .,!?\"()"));
auto match = std::find(begin(words), end(words), word);
if (match != end(words))
{
// Found it!
}
else
{
// Not there.
}
}
string word="spo";
string sentence="seven spoons";
string::size_type nIndex = sentence.find( word, 0 );
if( nIndex != string::npos )
{
if ((nIndex + word.length() + 1) == sentence.length())
{
cout << "Found" << endl;
}
else
{
string::size_type nSpace = sentence.find( " ", nIndex );
if (nSpace == (nIndex + word.length()))
{
cout << "Found" << endl;
}
}
}
else
{
cout << "No Match" << endl;
}
This seems to have worked.
#include <string>
/*find word in sentence and return the index of first occurrence*/
int find_whole(string sentence,string word){
size_t pos=sentence.find(word);
size_t offset=pos+sentence.size()+1;
if((pos!=string::npos) && (sentence.substr(pos,offset)==word))
return pos;
return string::npos;
}
I wrote the following code to check whether the input(answer3) is a number or string, if it is not a number it should return "Enter Numbers Only" but it returns the same even for numbers. Please suggest me a solution.
#include <iostream>
#include <string>
#include <typeinfo>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
using namespace std;
int main ()
{
string ques1= "Client's Name :";
string ques2 = "Client's Address :";
string ques3 = "Mobile Number :";
char answer1 [80];
string answer2;
int answer3;
cout<<ques1<<endl;
cin>>answer1;
cout<<ques2<<endl;
cin>>answer2;
cout<<ques3<<endl;
cin>>answer3;
if (isdigit(answer3))
{
cout<<"Correct"<<endl;
}
else
{
cout<<"Enter Numbers Only"<<endl;
}
system("pause>null");
return 0;
}
You can use regex to do this:
#include <regex>
bool isNumber(std::string x){
std::regex e ("^-?\\d+");
if (std::regex_match (x,e)) return true;
else return false;}
If you want to make isNumber() a generic function which can take any type of input:
#include <regex>
#include <sstream>
template<typename T>
bool isNumber(T x){
std::string s;
std::regex e ("^-?\\d+");
std::stringstream ss;
ss << x;
ss >>s;
if (std::regex_match (s,e)) return true;
else return false;}
The above isNumber() function checks for integer only, double or float value with precision (which contains dot .) will not return true.
If you want precision too, then change the regex line to:
std::regex e ("^-?\\d*\\.?\\d+");
If you want a more efficient solution, see this one.
If you're using C++98, you can use stringstreams (#include <sstream>):
std::string s = "1234798797";
std::istringstream iss(s);
int num = 0;
if (!(iss >> num).fail()) {
std::cout << num << std::endl;
}
else {
std::cerr << "There was a problem converting the string to an integer!" << std::endl;
}
If boost is available to you, you can use lexical_cast (#include <boost/lexical_cast.hpp>):
std::string s = "1234798797";
int num = boost::lexical_cast<int>(si);//num is 1234798797
std::cout << num << std::endl;
If C++11 is available to you, you can use the builtin std::stoi function from <string>:
std::string s = "1234798797";
int mynum = std::stoi(s);
std::cout << mynum << std::endl;
OUTPUTS:
1234798797
The function isdigit() is used to test for only digits ( 0,1,...,9)
use this function to check for numbers
bool is_number(const std::string& s)
{
std::string::const_iterator it = s.begin();
while (it != s.end() && std::isdigit(*it)) ++it;
return !s.empty() && it == s.end();
}
The input to isdigit is an integer value. However, it will return true (non-zero) only if the value corresponds to '0'-'9'. If you convert them to integer values, they are 48-57. For all other values, isdigit will return false (zero).
You can check whether you got an integer by changing checking logic:
if ( cin.fail() )
{
cout<<"Correct"<<endl;
}
else
{
cout<<"Enter Numbers Only"<<endl;
}
Another answer using strtod:
bool isNumber(const std::string& s){
if(s.empty() || std::isspace(s[0]) || std::isalpha(s[0])) return false ;
char * p ;
strtod(s.c_str(), &p) ;
return (*p == 0) ;
}
To be able to handle any type of parameter use template:
#include <sstream>
template<typename T>
bool isNumber(T x){
std::string s;
std::stringstream ss;
ss << x;
ss >>s;
if(s.empty() || std::isspace(s[0]) || std::isalpha(s[0])) return false ;
char * p ;
strtod(s.c_str(), &p) ;
return (*p == 0) ;
}
Note:
White space will make it return false.
NAN and INF will make it return false (to be exact, any character except valid exponent will make it return false). If you want to allow nan and inf, delete the || std::isalpha(s[0]) part.
scientific form is allowed i.e 1e+12 will return true.
Double/float or integer will return true.
This is more efficient than the regex answer. (regex is heavy).
The interest phenomenon are the isdigit requires char to be cast to unsigned char. (Also see here).
This is a somewhat old question, but I figured I'd add my own solution that I'm using in my code.
Another way to check if a string is a number is the std::stod function, which has been mentioned, but I use it a bit differently. In my use case, I use a try-catch block to check if the input is a string or number, like so with your code:
...
try {
double n = stod(answer3);
//This will only be reached if the number was converted properly.
cout << "Correct" << endl;
} catch (invalid_argument &ex) {
cout << "Enter Numbers Only" << endl;
}
...
The primary problem with this solution is that strings that begin with numbers (but aren't all numbers) will be converted to numbers. This can be easily fixed by using std::to_string on the returned number and comparing it to the original string.