Questions regarding C++ string - c++

phrase.erase(remove_if (phrase.begin(), phrase.end(), ::isdigit), phrase.end());
In the above code, why do I have to use :: even though I used using namespace std?
#include "Palindrome.h"
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
Palindrome::Palindrome (string Phrase){
phrase=Phrase;
}
void Palindrome::removeNonLetters()
{
phrase.erase(remove_if (phrase.begin(), phrase.end(), ::isdigit), phrase.end());
phrase.erase(remove_if (phrase.begin(), phrase.end(), ::ispunct), phrase.end());
phrase.erase(remove_if (phrase.begin(), phrase.end(), ::isspace), phrase.end());
}
void Palindrome::lowerCase()
{
for (int i=0; i<phrase.length(); i++)
{
phrase[i] = tolower(phrase[i]);
}
}
bool Palindrome::isPalindrome()
{
int length=phrase.length();
int a=0;
for (int i=0;i<length/2;i++)
{
if(phrase[i] != phrase[length-a-1])
{
return false;
break;
}
a++;
}
return true;
}
The above code is to check if the string is a Palindrome. I don't understand why I need to use the first part which is
Palindrome::Palindrome (string Phrase){
phrase=Phrase;
}
I will always get "yes" if I deleted the above part.
The test code in main is
if(test.Palindrome::isPalindrome() == 1){
cout<<"Yes"<<endl;
}
else {
cout<<"No"<<endl;
}
One more question. I try to change the lowercase of above code, I got error. Do anyone know what happen with it? The new code was from https://www.geeksforgeeks.org/conversion-whole-string-uppercase-lowercase-using-stl-c/
Before
void Palindrome::lowerCase()
{
for (int i=0; i<phrase.length(); i++)
{
phrase[i] = tolower(phrase[i]);
}
}
After
void Palindrome::lowerCase(){
transform(phrase.begin(), phrase.end(), phrase.begin, ::tolower);
}
Can anyone explain it to me? Many thanks!

There are multiple isdigit, ispunct, and isspace functions - ones in the global namespace in the <ctype.h> header, and several in the std namespace in the <cctype> and <clocale> headers. Prefixing them with :: says you want to use the ones from the global namespace.
You need to use <string> instead of <string.h> in order to use the std::string class.
Assuming test is a Palindrome object, then test.Palindrome::isPalindrome() should be just test.isPalindrome().
If you omit the Palindrome constructor, then the phrase member remains blank, and your isPalindrome() implementation returns true for a blank phrase (length is 0) because there is nothing for the for loop to check. Which is technically correct - a blank string is a palindrome.

The :: indicates that you're using isdigit and the others from the global namespace. The isdigit is a part of other header files, such as <ctype.h>.

Related

How to capitalize the first letter of each name in an array?

Here is the question:
Create a function that takes an array of names and returns an array where only the first letter of each name is capitalized.
example
capMe(["mavis", "senaida", "letty"]) ➞ ["Mavis", "Senaida", "Letty"]
And the code I wrote to answer this question:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void capme(vector<string> name)
{
char ch;
for(int i = 0; i < name[i].size(); i++)
{
putchar(toupper(name[i][0]));
cout << name[i] << endl;
}
}
int main()
{
vector <string> name = {"mavis", "senaida", "letty"};
capme(name);
return 0;
}
As you can see, it prints "Mmavis", "Ssenaida", "Lletty", which is wrong. Can you guys help me in answering this question as I don't know how?
To change the input argument, we have two choice: make the argument mutable reference, or add a return type, here I choose the first one.
putchar can be used to print only one character, it recommended to use cout to print a string, possible solutions:
with traditional loop: capme
with range for-loop since c++11 : capme2
with stl algorithm transform: capme3
Don't forget to check if the string element is empty, or you may crash while accessing the first character.
To obey the single-responsibility principle (SRP), it's better to print the string vector out of the capme function.
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
using namespace std;
void capme(vector<string>& name) {
for (int i = 0; i < name[i].size(); i++) {
if (name[i].empty()) continue;
name[i][0] = toupper(name[i][0]);
}
}
void capme2(vector<string>& names) {
for (auto& name : names) {
if (name.empty()) continue;
name[0] = toupper(name[0]);
}
}
void capme3(vector<string>& names) {
std::transform(names.begin(), names.end(), names.begin(), [](auto& s) {
return s.empty() ? s : (s[0] = toupper(s[0]), s);
});
}
Online demo
You have used the wrong function. What you need is a replacement and not a prepend. Try using std::string::operator[] to access the first element of the words in the vector. This is how I would write this code:
std::vector<string> capitaliseInitLetter(std::vector<string> vec) {
for (auto& word : vec) {
word[0] -= 32; //add a check to see if the letter is already capital
}
return vec;
}
The above code is just an example which assumes that the input is valid. You'll have to add checks and exception handling for invalid inputs on your own. (Hint: Take a look at #prehistoricpenguin's answer)
You are calling putchar() which writes a character to standard output, and in this case is printing the first letter of each string in name as uppercase, then you are writing the entire string to standard output immediately after.
Additionally, your function does not meet the requirements you stated above saying it should return an array where the strings have the first letter capitalized.
What you could do is change the signature of capme() to return a std::vector<std::string>, and perhaps utilize the for_each() function to handle changing the first letter of each string in your vector then return it.
For reference:
#include <vector>
#include <string>
#include <algorithm>
#include <cctype>
std::vector<std::string> capme(std::vector<std::string> name)
{
std::for_each(name.begin(), name.end(), [](std::string &s) {
s[0] = toupper(s[0]);
});
return name;
}
Or as kesarling suggested, a simple for each loop:
std::vector<std::string> capme(std::vector<std::string> name)
{
for (auto& s : name) {
s[0] = toupper(s[0]);
}
return name;
}

I'am working on a C++ program where I'am facing a error while execution of if-else statement [duplicate]

#include <iostream>
using namespace std;
int main() {
char word[10]="php";
char word1[10]="php";
if(word==word1){
cout<<"word = word1"<<endl;
}
return 0;
}
I don't know how to compare two char strings to check they are equal. My current code is not working.
Use strcmp.
#include <cstring>
// ...
if(std::strcmp(word, wordl) == 0) {
// ...
}
Use std::string objects instead:
#include <iostream>
#include <string>
using namespace std;
int main() {
string word="php";
string word1="php";
if(word==word1){
cout<<"word = word1"<<endl;
}
return 0;
}
To justify c++ tag you'd probably want to declare word and word1 as std::string. To compare them as is you need
if(!strcmp(word,word1)) {
word and word1 in your submitted code are pointers. So when you code:
word==word1
you are comparing two memory addresses (which isn't what you want), not the c-strings they point to.
#include <iostream>
**#include <string>** //You need this lib too
using namespace std;
int main()
{
char word[10]="php";
char word1[10]="php";
**if(strcmp(word,word1)==0)** *//if you want to validate if they are the same string*
cout<<"word = word1"<<endl;
*//or*
**if(strcmp(word,word1)!=0)** *//if you want to validate if they're different*
cout<<"word != word1"<<endl;
return 0;``
}

C++ Check if whole string is uppercase

I am trying to check if the whole word is upper case, if this is true it should return true, else return false.
My current code is:
#include "UpperCaseFilter.h"
#include "ReadFilteredWords.h"
#include "ReadWords.h"
#include <locale>
bool UpperCaseFilter::filter(string word) {
if(!word.empty()) {
for(int i = 0; i < word.length(); i++) {
if(isupper(word[i])) {
return true;
}
else {
return false;
}
}
}
}
The problem with this code is, if i have for example HeLLO, it will return true because my last character is true. How would I only return true if the whole string is true. I did it using a counter method but it is not the most efficient.
I also tried using the all_of method but I think I dont have the correct compiler version because it says all_of isn't defined (Even with correct imports).
I'm not sure what other approaches there are to this.
Alternatively utilize the std::all_of function in combination with std::isupper in predicate:
#include <iostream>
#include <string>
#include <algorithm>
int main() {
std::string s = "HELLo";
if (std::all_of(s.begin(), s.end(), [](unsigned char c){ return std::isupper(c); })) {
std::cout << "Is uppercase." << '\n';
} else {
std::cout << "Is not uppercase." << '\n';
}
}
Used as part of a function:
bool isUpper(const std::string& s) {
return std::all_of(s.begin(), s.end(), [](unsigned char c){ return std::isupper(c); });
}
bool is_all_upper(const std::string& word)
{
for(auto& c: word)
if(!std::isupper(static_cast<unsigned char>(c)))
return false;
return true;
}
I assume that, if the string is empty, it can be considered all-uppercase.
You shouldn't have two return conditions inside your loop. Rather, you can use the loop to find problems and, if there are no problems, you'll escape the loop and can tell the user that everything was alright at the end.
In the comments you say "i believe it doesn't need to return anything if the string is empty"; however, a function with a return type, such as this one always returns something. If you don't specify a return value it will give you one, whether you like it or not. Therefore, you must decide what the output should be for every conceivable input. Accordingly, I've added an if statement that emphasizes the special condition of an empty string.
#include "UpperCaseFilter.h"
#include "ReadFilteredWords.h"
#include "ReadWords.h"
#include <locale>
bool UpperCaseFilter::filter(const string &word) {
if(word.empty()) //You'll need to do the right thing here
return true;
//Even if the right thing to do were to return true, so that
//the check above would be redundant, you'd want to leave a
//comment here pointing out that you've handled the special case
for(size_t i = 0; i < word.length(); i++)
if(!isupper(static_cast<unsigned char>(word[i])))
return false;
return true;
}
Note that your previous function signature was:
bool UpperCaseFilter::filter(string word) {
I've changed this to:
bool UpperCaseFilter::filter(const string &word) {
The const guarantees that the function will not alter word and the & symbol passes the string to the function without copying it. This makes the function faster and saves memory.
#include "UpperCaseFilter.h"
#include "ReadFilteredWords.h"
#include "ReadWords.h"
#include <locale>
bool UpperCaseFilter::filter(string word)
{
int k=0;
if(!word.empty())
{
for(int i = 0; i < word.length(); i++)
{
if(isupper(word[i]))
k++;
}
}
if(k==word.length())
return true;
else
return false; //this will return false even when word length is 0
}
its more simple now provided if you have done other things right this would run.
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
string str;
cin >> str;
bool flag = false;
int i = 0;
while(str[i])
{
if(isupper(str[i]))
{
flag = true;
}
if(!(isupper(str[i])))
{
flag = false;
break;
}
i++;
}
if(flag == false)
cout << "false" << endl;
else
cout << "true" << endl;
}
#include <iostream>
#include <string>
#include <boost/algorithm/string.hpp>
bool IsAllUpperString(string str)
{
if(boost::to_upper_copy(str)== str) return true;
return false;
}

How can I read input while it exists?

#define _CRT_SECURE_NO_WARNINGS
#include <cmath>
#include <cstdio>
#include <string>
int main(){
char s = ' ';
while (s != NULL)
{
scanf ("%c", &s);
int a = 0;
if (s == '"')
{
if (a == 0) printf("``");
else printf("''");
a = 1- a;
}
else
printf("%c", s);
}
return 0;
}
this is my code, I'm new in C++, I'm writing this for uva.onlinejudge.org. the input is some text that we don't know it's size. I wanted to know how to get input while it exists ( I tried s != NULL but the program doesn't stop and gets the last char for ever)
#include <iostream>
// ...
while ( std::cin.get(s) )
{
// your code goes here
}
BTW in your existing code, scanf should be std::scanf, etc. The standard functions are all in the std:: namespace, and may or may not also be found in the global namespace.

C++ How do I read in a file, convert each word to lower case and then cout each word?

I am having trouble getting started with a program. I need to read in each word from a file, then convert it to lower case. I would like to std::cout each word after I find it. I assume I need to use Cstr() some how. I am guessing I should use something like
ofs.open(infile.c_str());
but how to lower case?
string[i] = tolower(string[i]);
then,
std::cout << string[i];
Thanks for the help.
Here is a complete solution:
#include <ctype.h>
#include <iterator>
#include <algorithm>
#include <fstream>
#include <iostream>
char my_tolower(unsigned char c)
{
return tolower(c);
}
int main(int ac, char* av[]) {
std::transform(std::istreambuf_iterator<char>(
ac == 1? std::cin.rdbuf(): std::ifstream(av[1]).rdbuf()),
std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(std::cout), &my_tolower);
}
I found the answer to my own question. I really didn't want to use transform, but that does work as well. If anyone else stumbles across this here is how I figured it out...
#include <iostream>
#include <string>
#include <fstream>
int main()
{
std::ifstream theFile;
theFile.open("test.txt");
std::string theLine;
while (!theFile.eof())
{
theFile >> theLine;
for (size_t j=0; j< theLine.length(); ++j)
{
theLine[j] = tolower(theLine[j]);
}
std::cout<<theLine<<std::endl;
}
return 0;
}
int main()
{
ofstream of("xyz.txt");
clrscr();
ifstream inf;
char line;
inf.open("abc.txt");
int count=0;
while(!inf.eof())
{
inf.get(line);
if(line>=65 && line<=123)
{
cout<<line;
line=line-32;
of<<line;
count++;
cout<<line;
}
}
cout<<count;
getch();
return 0;
}
First of all, unless this is something like a homework assignment, it's probably easier to process one character at a time rather than one word at a time.
Yes, you have pretty much the right idea for converting to lower case, with the minor detail that you normally want to cast the input to unsigned char before passing it to tolower.
Personally, I'd avoid doing explicit input and output, and instead do a std::transform with a pair of istream_iterators and an ostream_iterator for the result.