Trying to temporarily convert entire string to lowercase and remove spaces - c++

So my program is a palindrome checker function using only the string library and C++ sting objects. In order to check if the string input by the user is a palindrome, I need to convert the entire string to lowercase and remove the spaces to check if the string and its reverse are equal. I've tried looking up solutions but I've only found answers using different libraries and creating new functions. This is the code I have so far.
#include <iostream>
#include <string>
using namespace std;
string checkPalin();
int main()
{
string result = checkPalin();
cout << "The palindromes are: " << result;
}
string checkPalin()
{
int stringNum, time = 0;
string list;
string str1;
string reverse;
cout << "How many strings? " << endl;
cin >> stringNum;
cout << "Enter the strings: " << endl;
do
{
getline(cin, str1);
int size = str1.length();
for (int i = size - 1; i >= 0; i--)
reverse += str1[i];
if ((str1.compare(reverse)) == 0)
{
list += str1;
}
time++;
} while (time <= stringNum);
return list;
}

How about something like this
std::string inputString = "WhatEver", cleanString;
for (char & c : inputString)
if (c != ' ')
cleanString += std::tolower(static_cast<unsigned char>(c));
std::tolower is undefined if the char value is not representable as unsigned char, hence the cast.

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

How I do split a string into 2 different variables (string and integer) at a certain point? C++

My program receives input from the user, in this exact form: string, integer. An example would be: Brady, 12. I need to split the string at the comma, and store the first part into a vector of strings, and the 2nd part into a vector of integers. How do I go about this? (Sorry, I'm very new to programming)
This is what my code currently looks like:
while(true) {
cout << "Enter a data point (-1 to stop input): " << endl;
getline(cin, dataPoint);
if (dataPoint == "-1") { //Ends Program
break;
}
if (dataPoint.find(",") == std::string::npos) {
cout << "Error: No comma in string." <<endl;
}
}
We wouldn't normally write your code for you, but I'm going to offer a few hints.
First, storing the data the way you're going to do is probably the wrong approach, unless it's required for your homework. I'd keep it related:
class Person {
... various methods
private:
std::string name;
int age;
}
I would parse the data into one of these and store THAT into a std::vector<Person>. That keeps your data together.
As for splitting the string:
size_t pos = str.find(",");
if (pos == string::npos) {
... no comma found
}
else {
string name = str.substr(0, pos);
string ageStr = str.substr(pos + 1);
}
There's more you have to do, of course, but that's how you can divide the string into two pieces.
Here is the solution:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
cout << "Enter a data point (-1 to stop input): " << endl;
string input;
getline(cin, input);
if (input == "-1") return 0;
int comma = input.find(","); //find separator
string name = input.substr(0, comma); //find name and nuber using this number
string snumber = input.substr(comma + 2); // comma itself and space
cout << "The name is: " << name << " The number is: " << snumber << endl;
int number = stoi(snumber); //switch string to int
vector<string> names;
vector<int> numbers;
names.push_back(name); // add to vector
numbers.push_back(number);
return 0;
}

Reversing a cstring array in a function using pointers c++

I have an assignment that wants me to get a cstyle string (just 1 word) from the user then use a function to reverse its letters. The function has to take in 2 parameters, the first that is the destination string, and the other that is the source string. It will take whatever is in the source string, reverse it, then store the reversed version in the second string.
But everytime I compile, I typed in hello it prints out: \370\365\277\357\376. I just learned how to use pointers and cstyle strings so I don't really know how to use them and I think thats what is messing up my code. I'm dont understand it that well though so I cant figure out where I'm going wrong at.
Please let me know if you know what I'm doing wrong. Thank you!
#include <iostream>
#include <cstring>
#include <string>
#include <cctype>
using namespace std;
void IsPalindrome(char *cstring);
void Reverse(char *str2[], char *str1[]);
int main() {
// user variables
char str1[81];
char reverse;
char str2[81];
strcpy (str2, str1);
//prompt user to input string
cout << "\nPlease input a string (80 chars max): ";
cin >> str1;
cout << "\nYour string is: " << str1 << endl;
//call function
Reverse(str2[81], str1[81]);
//Output reversed string
cout << "Your string reversed is: " << str2 << endl;
cout << "This is a " << "." << endl;
return 0;
}
void Reverse(char *str2, char *str1)
{
char* front, *rear;
int len = strlen(str1);
char temp;
front = str1;
rear = &str1[len - 1];
while(front < rear)
{
temp = *front;
*front = *rear;
*rear = temp;
front++;
rear --;
}
}
void IsPalindrome(char cstring)
{
}
Pointers make life harder, don't use them if you don't need them. As your assignment is to reverse a string, so just use string. string is const char* inside but it's much easier to handle.
Beside your problem with pointers and arrays in your code, you are getting your string from input using std::cin. Remember that this way you can't get strings that have white space one them (you will just get the first word).
Also there is some algorithm that do this kind of tasks for you these days but for educational reasons it's not bad to do it yourself.
Here is what you can do, in the code I mentioned places that you could use ready to use algorithms to do the task for you.
#include <iostream>
#include <cstring>
#include <string>
#include <cctype>
#include <algorithm>
void Reverse(std::string &inputStr);
int main()
{
// user variables
std::string str1 = "";
std::cout << "\nPlease input a string (80 chars max): ";
std::getline(std::cin, str1);
std::cout << "\nYour string is: " << str1 << std::endl;
Reverse(str1);
//You also can use stl algorithm to reverse string for you and don't do it manually like below, but as it is an assignment it would not be good
//std::reverse(str1.begin(), str1.end());
//Output reversed string
std::cout << "Your string reversed is: " << str1 << std::endl;
std::cout << "This is a " << "." << std::endl;
system("pause");
return 0;
}
void Reverse(std::string &str)
{
int n = str.length();
for(int i = 0; i < n / 2; i++)
{
char temp = str[i];
str[i] = str[n - i - 1];
str[n - i - 1] = temp;
//You also can use stl algorithm to do the swap for you like below
//std::swap(str[i], str[n - i - 1]);
}
}
NOTE: This example will reverse your original string that user entered, if you want to have the both original and reversed, you need to pass a copy of input to the function. something like this :
std::string str2(str1);
Reverse(str2);
std::cout << "Reversed : " << str2;
EDIT: To match your assignment requirements (have a function with two parameters and single word string) you can easily change the above code like this :
void Reverse(std::string inputStr, std::string &outputStr);
int main()
{
// user variables
std::string str1 = "";
std::string str2 = "";
std::cout << "\nPlease input a string (80 chars max): ";
std::cin >>str1;
std::cout << "\nYour string is: " << str1 << std::endl;
Reverse(str1, str2);
//You also can use stl algorithm to reverse string for you and don't do it manually like below, but as it is an assignment it would not be good
//std::reverse(str1.begin(), str1.end());
//Output reversed string
std::cout << "Your string original is: " << str1 << std::endl;
std::cout << "Your string reversed is: " << str2 << std::endl;
system("pause");
return 0;
}
void Reverse(std::string inputStr, std::string &outputStr)
{
outputStr = inputStr;
int n = outputStr.length();
for(int i = 0; i < n / 2; i++)
{
char temp = outputStr[i];
outputStr[i] = outputStr[n - i - 1];
outputStr[n - i - 1] = temp;
//You also can use stl algorithm to do the swap for you like below
//std::swap(str[i], str[n - i - 1]);
}
}
There is no need of using pointers for reversing a character array to another character array.
void Reverse(char *str2, char *str1)
{
int len = strlen(str1);
for(int n = 0; n< len; n++)
{
str2[n] = str1[len-n-1];
}
}

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

reverse of the string using recursion

Hey guys i get stuck in the unusual situation. This is my code, it works perfectly for returning the reverse of the string but it gives output with including the space so I don't want that space to be included in my programme output so anyone has suggestions about this plz share it... by the way this is my code :
#include <iostream>
using namespace std;
string reverse(string str, int size) {
if (size == -1)
return "";
else
{
char a;
a = str[size];
return a + reverse(str, size - 1);
}
}
int main() {
int size;
cout << "the size of the string : ";
cin >> size;
string str;
cout << "enter the word : ";
cin >> str;
cout << reverse(str, size);
}
Since you use std::string, you don't need to specify the size of the string, but use the std::string::size() or std::string::length() member functions. Also, a = str[size]; is problematic when size equals to the size of the string, since you perform an out of bound access (remember that C++ uses zero-based indexing). You can simplify the code a lot, ending up with
#include <iostream>
#include <cstddef> // for std::size_t
using namespace std;
string reverse(string str, std::size_t pos) {
return (pos == 0 ? "" : str[pos - 1] + reverse(str, pos - 1));
}
int main() {
string str;
cout << "enter the word : ";
getline(cin, str); // allow for spaces in the string
cout << reverse(str, str.size()) << endl;
}
Here, instead of using cin >> str, I used getline(cin, str), since cin reads up to the first whitespace, whereas getline allows to read strings that containg spaces.
Change the implementation of the function reverse to the following.
string reverse(string str ,int size){
if (size==-1)
return "";
else
{
char a;
a=str[size];
if (' ' == a )
return reverse(str,size-1)
else
return a+reverse(str,size-1);
}
}
Alternatively, do some pre-processing on th input.