How to Read charcters and digits from string in c++ - c++

I'm trying to read a string that will show digits and characters separately.
Additional Info:
1. the program is showing 10 (ten) as 1 and 0 i.e two separate digits
2. It is also counting space as a character, which it should skip.
3. If a user input 10 20 + it should display:
digit is 10
digit is 20
other Character is +
Here is what I've tried
#include <iostream>
#include <string>
using namespace std;
int main() {
string s("10 20 +");
const char *p = s.c_str();
while (*p != '\0')
{
if(isdigit(*p))
{
cout << "digit is: "<< *p++ << endl;
}
else
{
cout<<"other charcters are:"<<*p++<<endl;
}
}
system("pause");
}
Edit Now it becomes :
#include <iostream>
#include <string>
using namespace std;
int main() {
string x;
string s("1 2 +");
const char *p = s.c_str();
while (*p != '\0')
{
while(isspace(*p)){
*p++;
if(isdigit(*p))
{
while(isdigit(*p))
{
x+=*p++;
cout << "digit is: "<< x<< endl;
}
}
else{
while(!isdigit(*p)&& !isspace(*p))
x+=*p++;
cout<<"other charcters are:"<<x<<endl;
}
}
}
system("pause");
}
Not workingg

You could use a stringstream instead.
[...]
stringstream ss;
ss << s;
while(!ss.eof())
{
char c = ss.peek(); // Looks at the next character without reading it
if (isdigit(c))
{
int number;
ss >> number;
cout << "Digit is: " << number;
}
[...]
}

While the character is space (check the isspace function) skip it.
If the current character is a digit, then while the current character is a digit put it in a temporary string. When the character is no longer a digit, you have a number (which might be a single digit).
Else if the character is not a digit or not a space, do the same as for numbers: collect into a temporary string and display when it ends.
Start over.
Edit Code sample on request:
std::string expression = "10 20 +";
for (std::string::const_iterator c = expression.begin(); c != expression.end(); )
{
std::string token;
// Skip whitespace
while (isspace(*c))
c++;
if (isdigit(*c))
{
while (isdigit(*c))
token += *c++;
std::cout << "Number: " << token << "\n";
}
else
{
while (!isidigit(*c) && !isspace(*c))
token += *c++;
std::cout << "Other: " << token << "\n";
}
}

Related

how do I check if all characters in a string is space or alphabet? C++

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

print 2nd word in a string with its size in C++

I am trying to make a program in which a user enters a string and i will print out the second word in the string with its size.
The delimiter's are space( ), comma(,) and tab( ).
I have used a character array and fgets to read from user and a character pointer that points to the first element of the array.
source code:
#include"iostream"
#include<stdio.h>
#include<string>
using namespace std;
// extract the 2nd word from a string and print it with its size(the number of characters in 2nd word)
int main()
{
char arr[30], arr1[30];
char *str = &arr1[0];
cout<<"Enter a string: ";
fgets(str, 30, stdin);
int i = 0, j, count = 1, p = 0; // count is used to find the second word
// j points to the next index where the first delimiter is found.
// p is used to store the second word found in character array 'arr'
while(*(str+i) != '\n')
{
if(*(str+i) == ' ' || *(str+i) == ',' || *(str+i) == ' ')
{
count++;
if(count == 2)
{
// stroing 2nd word in arr character array
j = i+1;
while(*(str+j) != ' ' || *(str+j) != ',' || *(str+j) != ' ')
{
arr[p] = *(str+j);
cout<<arr[p];
p++;
i++;
j++;
}
break;
}
}
i++;
}
arr[p+1] = '\0'; // insert NULL at end
i = 0;
while(arr[i] != '\0')
{
cout<<arr[i];
i++;
}
cout<<"("<<i<<")"<<endl;
return 0;
}
Help me out with this.
To start, don't use std::cin for testing. Just set a value in your code for consistency and ease of development. Use this page for a reference.
#include <iostream>
#include <string>
int main() {
std::string str("this and_that are the tests");
auto start = str.find_first_of(" ,\n", 0);
auto end = str.find_first_of(" ,\n", start + 1);
std::cout << str.substr(start, end - start);
return 0;
}
And this is still somewhat of a hack, it just depends where you are going. For instance the Boost library is rich with extended string manipulation. If you are going to parse out more than just one word it can still be done with string manipulations, but ad-hoc parsers can get out of hand. There are other tools like Boost Spirit to keep code under control.
The delimiters used when extracting from a stream depends on the locale currently in effect. One (cumbersome) way to change the extraction behaviour is to create a new locale with a special facet in which you specify your own delimiters. In the below example the new locale is used to imbue a std::stringstream instead of std::cin directly. The facet creation part is mostly copy/paste from other answers here on SO, so you'll find plenty of other examples.
#include <iostream>
#include <locale> // std::locale, std::ctype<char>
// https://en.cppreference.com/w/cpp/locale/ctype_char
#include <sstream> // std::stringstream
#include <algorithm> // std::copy_n
#include <vector> // a container to store stuff in
// facet to create our own delimiters
class my_facet : public std::ctype<char> {
mask my_table[table_size];
public:
my_facet(size_t refs = 0)
: std::ctype<char>(&my_table[0], false, refs)
{
// copy the "C" locales table to my_table
std::copy_n(classic_table(), table_size, my_table);
// and create our delimiter specification
my_table[' '] = (mask)space;
my_table['\t'] = (mask)space;
my_table[','] = (mask)space;
}
};
int main() {
std::stringstream ss;
// create a locale with our special facet
std::locale loc(std::locale(), new my_facet);
// imbue the new locale on the stringstream
ss.imbue(loc);
while(true) {
std::string line;
std::cout << "Enter sentence: ";
if(std::getline(std::cin, line)) {
ss.clear(); // clear the string stream from prior errors etc.
ss.str(line); // assign the line to the string stream
std::vector<std::string> words; // std::string container to store all words in
std::string word; // for extracting one word
while(ss>>word) { // extract one word at a time using the special facet
std::cout << " \"" << word << "\" is " << word.size() << " chars\n";
// put the word in our container
words.emplace_back(std::move(word));
}
if(words.size()>=2) {
std::cout << "The second word, \"" << words[1] << "\", is " << words[1].size() << " chars\n";
} else {
std::cout << "did not get 2 words or more...\n";
}
} else break;
}
}
#include"iostream"
#include<stdio.h>
#include<string>
#include <ctype.h>
using namespace std;
int main()
{
char c;
string str;
char emp = ' ';
cout<<"Enter a string: ";
getline (cin,str);
int j = 0, count = 1, counter = 0;
for (int i = 0; i < str.length() && count != 2; i++)
{
cout<< str[i] <<endl;
if( isspace(str[i]) || str[i] == ',' || str[i] == '\t' )
{
count++;
if(count == 2)
{
j = i+1;
while(j < str.length())
{
if (isspace(str[j]) || str[j] == ',' || str[j] == '\t')
{
break;
}
cout<<str[j];
counter++;
j++;
}
cout<<endl;
}
}
}
cout<<"size of the word: "<<counter<<endl;
return 0;
}
This is a simple answer to what you want, hope to help you.
// Paul Adrian P. Delos Santos - BS Electronics Engineering
// Exercise on Strings
#include <iostream>
#include <sstream>
using namespace std;
int main(){
// Opening Message
cout << "This program will display the second word and its length.\n\n";
// Ask for a string to the user.
string input;
cout << "Now, please enter a phrase or sentence: ";
getline(cin, input);
// Count the number of words to be used in making a string array.
int count = 0;
int i;
for (i=0; input[i] != '\0'; i++){
if (input[i] == ' ')
count++;
}
int finalCount = count + 1;
// Store each word in a string array.
string arr[finalCount];
int j = 0;
stringstream ssin(input);
while (ssin.good() && j < finalCount){
ssin >> arr[j];
j++;
}
// Display the second word and its length.
string secondWord = arr[1];
cout << "\nResult: " << arr[1] << " (" << secondWord.size() << ")";
return 0;
}

C++ print string one word at a time, count characters, and average of characters

how can I print a single word from a string in each line with the number of characters right next to it and the average of the characters together? I'm suppose to use a string member function to convert the object into a c string. The function countWords accepts the c string and returns an int. The function is suppose to read in each word and their lengths including the average of characters. I have done how much words are in the string except I don't know how continue the rest.
For example: super great cannon boys
super 5
great 5
cannon 6
boys 4
average of characters: 5
This is my program so far:
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int countWords(char *sentence);
int main()
{
const int size=80;
char word[size];
double average=0;
cout<<"Enter words less than " <<size-1<<" characters."<<endl;
cin.getline(word, size);
cout <<"There are "<<countWords(word)<<" words in the sentence."<<endl;
return 0;
}
int countWords(char *sentence)
{
int words= 1;
while(*sentence != '\0')
{
if(*sentence == ' ')
words++;
sentence++;
}
return words;
}
Unless this is something like homework that prohibits doing so, you almost certainly want to use std::string along with the version of std::getline that works with a std::string instead of a raw buffer of char:
std::string s;
std::getline(std::cin, s);
Then you can count the words by stuffing the line into a std::istringstream, and reading words out of there:
std::istringstream buffer(s);
auto word_count = std::count(std::istream_iterator<std::string>(s),
std::istream_iterator<std::string());
To print out the words and their lengths as you go, you could (for example) use std::for_each instead:
int count = 0;
std::for_each(std::istream_iterator<std::string>(s),
std::istream_iterator<std::string>(),
[&](std::string const &s) {
std::cout << s << " " << s.size();
++count;});
This should not be far from you requirements - I only did minimal modification to your present code.
Limits :
you'd better use
string line;
getline(cin, line);
to read the line to be able to accept lines of any size
my present code assumes
no spaces at beginning or end of line
one single space between 2 words
it should be improved to cope with extra spaces, but I leave that to you as an exercise :-)
The code :
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int countWords(char *sentence, double& average);
int main()
{
const int size=80;
char word[size];
double average=0;
cout<<"Enter words less than " <<size-1<<" characters."<<endl;
cin.getline(word, size);
cout <<"There are "<<countWords(word, average)<<" words in the sentence."<<endl;
cout << "Average of the sentence " << average << endl;
return 0;
}
int countWords(char *sentence, double& average)
{
int words= 1;
int wordlen;
char *word = NULL;
while(*sentence != '\0')
{
if(*sentence == ' ') {
words++;
wordlen = sentence - word;
average += wordlen;
*sentence = '\0';
cout << word << " " << wordlen<< endl;
word = NULL;
}
else if (word == NULL) word = sentence;
sentence++;
}
wordlen = sentence - word;
average += wordlen;
cout << word << " " << wordlen<< endl;
average /= words;
return words;
}
For input : super great cannon boys
Output is :
Enter words less than 79 characters.
super great cannon boys
super 5
great 5
cannon 6
boys 4
There are 4 words in the sentence.
Average of the sentence 5
You can inspire here. Basically use std::getline to read from std::cin to std::string.
#include <iostream>
#include <string>
#include <cctype>
inline void printWordInfo(std::string& word) {
std::cout << "WORD: " << word << ", CHARS: " << word.length() << std::endl;
}
void printInfo(std::string& line) {
bool space = false;
int words = 0;
int chars = 0;
std::string current_word;
for(std::string::iterator it = line.begin(); it != line.end(); ++it) {
char c = *it;
if (isspace(c)) {
if (!space) {
printWordInfo(current_word);
current_word.clear();
space = true;
words++;
}
}
else {
space = false;
chars++;
current_word.push_back(c);
}
}
if (current_word.length()) {
words++;
printWordInfo(current_word);
}
if (words) {
std::cout << "AVERAGE:" << (double)chars/words << std::endl;
}
}
int main(int argc, char * argv[]) {
std::string line;
std::getline(std::cin, line);
printInfo(line);
return 0;
}
Going along the lines of what you already have:
You could define a countCharacters function, like your countWords:
int countCharacters(char *sentence)
{
int i;
char word[size];
for(i = 0; sentence[i] != ' '; i++) //iterate via index
{
word[i] = sentence[i]; //save the current word
i++;
}
cout <<word<< <<i<<endl; //print word & number of chars
return i;
}
which you can call inside your countWords function
int countWords(char *sentence)
{
int words = 1;
for(int i; sentence[i] != '\0';) //again this for loop, but without
//increasing i automatically
{
if(sentence[i] == ' ') {
i += countCharacters(sentence[++i]); //move i one forward to skip
// the space, and then move
// i with the amount of
// characters we just counted
words++;
}
else i++;
}
return words;
}

Count the number trailing blank space in a string

Can anyone help me in decreasing the complexity of the code below which counts the number of trailing blank spaces in a string.
void main()
{
string url = "abcd ";
int count = 1;
for (int i = 0; i < url.length(); i++)
{
if (url.at(i) == ' ')
{
for (int k = i + 1; k < url.length(); k++)
{
if (url.at(k) != ' ')
{
count = 1;
break;
}
else
{
count++;
i++;
}
}
}
}
cout<< count;
}
#include <iostream>
#include <string>
#include <algorithm>
#include <cstring>
using namespace std;
int main()
{
string url = "abcd "; // four spaces
string rev = url;
reverse(rev.begin(), rev.end());
cout << "There are " << strspn(rev.c_str(), " ") << " trailing spaces." << endl;
return 0;
}
We can do this without reversing the string, and without using a C function like strspn. For example, look up the string::find_last_not_of function. It will find the last character in the string which is not in the specified set, and return its position. If your set is the set " " (space) then it finds the last non-space character. The difference between that position and the string length is the count of trailing spaces.
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
int main()
{
string url = "abcd "; // four spaces
size_t last_nonspace = url.find_last_not_of(" ");
cout << "There are " << url.length() - last_nonspace - 1 << " trailing spaces." << endl;
return 0;
}
Note that if there is no non-space character in the string (the string is either empty or contains only spaces), the find_last_not_of function returns string::npos which is just (size_t) -1, the largest value of size_t. When this is subtracted from the length, and then 1 is subtracted, the resulting value is just the length. The arithmetic works out in all cases.
start backward counting the white space
void main() {
string url = "abcd ";
int count = 0;
for (int i = url.length(); i > 0; i--) {
if (url.at(i) == ' ') {
count++;
} else {
break;
}
}
cout<< count;
}
You can do this by using the find_if() algorithm function:
#include <algorithm>
#include <string>
#include <cctype>
#include <iostream>
using namespace std;
int main()
{
string s = "This string has spaces at the end ";
string::iterator it =
find_if(s.rbegin(), s.rend(), [](char ch) { return !isspace(ch); }).base();
cout << "The number of trailing spaces is " << std::distance(it, s.end());
}
Basically we start from the end of the string, and let find_if() find the first non-space character (I used isspace instead of the hard-coded 32).
After that, the iterator that is returned will point to the non-space character, so it's a matter of just knowing the "distance" between that point and the end (that is what std::distance will do for us).

Determining input to be int or char in C++

I'm working on a small program for school to compute a factorial of an inputted number. I've got a good amount of experience in Java, but this is my first go at C++.
My problem: I need to be able to have a single input from the user, which is either an integer or the character 'q', which signifies the application needs to quit.
Here is my current attempt:
#include <stdio.h>
#include <iostream>
#include "Header.h"
using namespace std;
int x=0;
char y;
int main(int argc, char *argv[])
{
printf("Hello, please enter a number to compute a factorial (or 'q' to quit): ");
cin >> y;
x= (y-'0');
if(y=='q')
{ printf("Thanks for playing!\n");
exit(1);
}
long result= print_Factorial(x);
cout << x << "!= " << result << "\n";
return result;
}
This casting does not work, however. If I enter a double digit number, such as 12, it only converts to x the first digit of the two and computes that factorial. I'm sure this is simple, what am I missing?
Explicit answer or a lead to where I can learn more about this problem, anything is appreciated.
There are functions you can use to try and covert a string into a number, and which you can check if the conversion was a success or not. The std::strtol function is one of them:
std::string input;
std::cin >> input;
char* endptr = nullptr;
const char *input_ptr = input.c_str();
long value = std::strtol(input_ptr, &endptr, 10);
if (endptr == input_ptr)
{
// Input was not a valid number
}
else if (*endptr != '\0')
{
// Input starts with a valid number, but ends with some extra characters
// (for example "123abc")
// `value` is set to the numeric part of the string
}
else
{
// Input was a valid number
}
If you don't mind exceptions, then you can use e.g. std::stoi instead:
std::string input;
std::cin >> input;
int value = 0;
try
{
size_t endpos = 0;
value = std::stoi(input, &endpos);
if (endpos != input.length())
{
// Input starts with a valid number, but ends with some extra characters
// (for example "123abc")
// `value` is set to the numeric part of the string
}
else
{
// Input is a valid number
}
}
catch (std::invalid_argument&)
{
// Input not a valid number
}
catch (std::out_of_range&)
{
// Input is a valid number, but to big to fit in an `int`
}
The reason you're getting the first digit is because you're using
cin >> y; where y is a char, which holds one character. So you're only getting one character.
What you probably would want to do is get the answer as a string, and once you check that the string is not == "q", then you could convert it to an int.
#include <iostream>
#include <sstream>
int main() {
std::string in;
std::cout << "Please enter a digit: ";
while(std::cin >> in) {
std::cout << "Input: " << in << std::endl;
if(in.size() == 1) {
if(in[0] == 'q' || in[0] == 'Q') {
std::cout << "Quit" << std::endl;
return 0;
}
}
std::istringstream parse(in);
int value;
if(parse >> value) {
if(parse.eof()) {
std::cout << "Success" << std::endl;
return 0;
}
}
std::cout << "Please try again: ";
}
std::cerr << "This should not happen <control + d>" << std::endl;
return 1;
}
Your user can enter whatever line of text, you you have to read a "line of text" to validate.
#include <iostream>
#include <string>
#include <stdexcept>
int main()
{
std::string text;
std::getline(std::cin,text);
if(text.size()==1 && text[0]=='q')
{
std::cout << "quit command";
return 0;
}
try
{
int i = std::stoi(text); //may throw if text is not convertible
/* whatever elaboration and output */
return 0;
}
catch(const std::exception& e)
{
std::cout << "bad input: " << text << '\n';
std::cout << "caused excpetion: " << e.what() << std::endl;
}
return 3; //means "excpetion thorown"
}