So, I've been doing Reddit's daily programmer #140 and can't use std::toupper and std::erase.
Includes:
#include <iostream>
#include <string>
#include <cctype>
Part with toupper and erase (used to transform words to 'CamelCase'):
std::string tekst;
std::cin >> tekst;
tekst[0] = std::touppper(tekst[0]);
for(unsigned int i = 0; i < tekst.size(); i++){
if(tekst[i] == 32){
std::erase(tekst[i], 1);
tekst[i] = std::toupper(tekst[i]);
}
}
And compiler shows errors:
error: 'touppper' is not a member of 'std'
error: 'erase' is not a member of 'std'
What can cause it? Thanks in advance!
Not
std::touppper
but
std::toupper
You need to pass a locale to the function, see for example: http://www.cplusplus.com/reference/locale/toupper/
std::touppper does not exist, as it is spelled with two p's, not with three :). std::erase is not a standard function, check this: Help me understand std::erase
You probaly want to use std::toupper() as the basis of your implementation. Note, however, that std::toupper() takes its argument as int and requires that the argument is a positive value of EOF. Passing negative values to the one argument version of std::toupper() will result in undefined behavior. On platforms where char is signed you will easily get negative values, e.g., when using ISO-Latin-1 encoding with my second name. The canonical approach is to use std::toupper() with the char convert to an unsigned char:
tekstr[0] = std::toupper(static_cast<unsigned char>(tekstr[0]));
With respect to erase() you are probably looking for std::string::erase():
tekstr.erase(i);
Note that if the string ends in a space, you don't want to access the character at index i after blowing the last space away!
Related
top 35/3_palindrome.cpp:18:8: error: no matching function for call to 'isPalindrome'
if(isPalindrome(s)){
^~~~~~~~~~~~
top 35/3_palindrome.cpp:4:5: note: candidate function not viable: no known conversion from 'std::__1::string' (aka 'basic_string<char,
char_traits<char>, allocator<char> >') to 'char *' for 1st argument
int isPalindrome(char* s){
^
1 error generated.
The terminal process "/bin/zsh '-c', ' g++ -g 'top 35/3_palindrome.cpp' -o 3_palindrome.out && clear && ./3_palindrome.out'" terminated with exit code: 1.
My code:
#include <bits/stdc++.h>
using namespace std;
int isPalindrome(char* s){
int n = strlen(s);
for (int i = 0; i < n/2; i++){
if(s[i] != s[n - i - 1]){
return 0;
}
}
return 1;
}
int main(){
string s;
getline(cin,s);
cout << s;
if(isPalindrome(s)){
cout << "Yes";
}
else{
cout << "No";
}
return 0;
}
The Problem
Your isPalindrome function expects char * for its argument. There is no suitable implicit conversion (operator or otherwise) from what you're giving it, a std::string, to that char *. The compiler is dutifully pressing on and attempting to find an alternative overload of isPalindrome that matches what you're actually feeding it. Finding none, the resulting error halts the compile and leaves you with your not-necessarily-crystal-clear error message.
A Solution
There are a multitude of solutions, but the easiest is simply to change isPalindrome to accept a reference to const std::string:
bool isPalindrome(std::string const& s)
{
std::size_t n = s.length();
for (std::size_t i=0; i<n/2; ++i)
{
if(s[i] != s[n - i - 1])
return false;
}
return true;
}
A More-C++ Solution
All you're really doing is comparing two ranges. The standard library provides a function to do this, std::equal , which takes an iterator begin/end, and a secondary iterator starting point (and after C++14, a secondary ending point). Furthermore, the std::string class provides both fore and aft direction iterators (begin() and rbegin(), and the lot of them can be used to do this:
#include <iostream>
#include <string>
#include <algorithm>
bool isPalindrome(std::string const& s)
{
return std::equal(s.begin(), std::next(s.begin(), s.length()/2), s.rbegin());
}
Note that neither this, nor your original C-based approach, will work with mixed-case comparison. I.e. Aba will certainly not compare as a successful palindrome. More work is involved if you want that. Also, the three-argument overload of std::equal is available until, but not including, C++20, after that you need the four argument version (the second range also requires an end-iterator; not just a starting point).
Noteworthy
Neither #include <bits/stdc++.h> or using namespace std are good ideas, and should be avoided. There are woefully inadequate web sites and online "courses" that preach using both almost by reflex; just... don't. If you want know more about why these are terrible practices I urge you to read:
Why should I not #include <bits/stdc++.h>?
Why is “using namespace std;” considered bad practice?
Take a closer look at the error:
if(isPalindrome(s)){
palindrome.cpp:4:5: note: candidate function not viable: no known conversion from 'std::__1::string' (aka 'basic_string<char,
char_traits, allocator >') to 'char *' for 1st argument
So let's break it down:
1- if(isPalindrome(s)){
That's the line that failed compiling. The line has an if statement, a call to the isPalindrome function, and a reference to variable s. It also has some C syntax related to those, ( ( )){. The error could be in any of those. You do have an arrow to the isPalindrome function, so that's our best bet, but not necessarily the root cause yet.
2- palindrome.cpp:4:5:
That's an offending line (or at least, a line related to your issue). What this line does,
int isPalindrome(char* s){
is just declare a function. So now we know the issue is at least related to your function declaration, confirming the suspicion above.
2- candidate function not viable:
this goes a bit more detail into what the problem with that function is.
Each function call has to be matched to a function declaration. C++ accepts (function overloading)[https://en.wikipedia.org/wiki/Function_overloading], so given a function call, the compiler will find all "candidate" functions, that is, those that have a matching name. Between those, the compiler will look at certain hints, such as the types you're passing in, to determine which implementation to use.
The error here declares that there is no viable function. So there was no function that could be matched to the call you're making.
3- *no known conversion from 'std::__1::string' [...] to 'char ' for 1st argument:
Now this is the remaining piece we need. The compiler tells you that in the best candidate function it found, for the first (and only) argument, there is a type mismatch. The function expects a char *, but the argument being used in your call can't be converted to a char *. The argument you're passing is of type std::string, and that can't be converted to a char * automatically.
There are several ways to fix this, but the easiest route is to change your types so that either the variable you pass in is a char *, or the function you're defining expects the type you're passing in, that is, std::string.
As someone mentioned above, one way to achieve this, among several others, is to just add s.c_str() to your function call, instead of purely passing in s. That is a manual conversion from std::string to char *.
In general though, converting types with manual calls isn't a good solution from a performance or maintainability standpoint. You'd be better off just reimplementing either your function or your input reading to use the same type throughout, be it std::string or char *.
There is a problem with strstr function. I have tried to compile password program, but it falls. Any help would be highly appreciated
#include <stdio.h>
#include <string.h>
using namespace std;
int main(){
char s[5], password[]="kuku";
int i,k=0;
for (i=0; !k && i<3;i++){
printf("\ enter password: \n");
gets(s);
if (strstr(s.password[])) k=1;
}
if(k) printf("password accepted");
else printf("password not accepted");
return 0;
}
if (strstr(s.password[])) k=1;
What did you want to accomplish with this? strstr() needs two arguments (haystack and needle, meaning that you want to find the needle in the haystack). You only pass one argument, which is wrong.
The correct code will be something like:
if (strstr(s, password) != NULL) k=1;
In this expression
strstr(s.password[])
there are two errors. The first one is that the separator of arguments is comma while you are using a dot.
The second one is that instead of the construction password[] you have to use the expression password
Take into account that the function strstr is not suitable to check whether two strings are equal each other. It is better to use function strcmp.
And the function gets is not supported by the C standard. Use instead function fgets.
And as you are trying to compile the program as a C++ program then use the standard class std::string instead of raw character arrays.
I am sorry for the simple question, but I cannot understand why this simple program does not work.
What is a[0] supposed to be other than "a"?
#include <iostream>
using namespace std;
int main(){
string a = "abcd";
string b = "a";
if (a[0]==b){//<------problem here
cout << a << endl;
}
return 0;
}
which returns the error
no match for ‘operator==’ (operand types are ‘char’ and ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’)
or simply using string c=a[0]; returns the error:
conversion from ‘char’ to non-scalar type ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’ requested
PS: after trying a few things, I can get it to work if I compare a[0]==b[0] or assign c[0]=a[0] because those are now definitely the same type, but I still would like to know what the standard and/or fastest way to carry out a comparison of a substring with another string in C++ is.
You should use std::string::find to find substrings. Using the subscript operator on string returns a single character (scalar), not a string (vector, non-scalar); therefore, they are not the same type and there is no defined comparison.
You can can also use std::string::substr to select a substring which you can directly compare against another string.
Example
#include <iostream>
#include <string>
int
main() {
std::string a = "abcd";
std::string b = "a";
if (a.find(b) != std::string::npos) {
std::cout << a << "\n";
}
if (a.substr(0, 1) == b) {
std::cout << a << "\n";
}
return 0;
}
References
http://en.cppreference.com/w/cpp/string/basic_string/find
http://en.cppreference.com/w/cpp/string/basic_string/substr
http://en.cppreference.com/w/cpp/string/basic_string
what is a[0] supposed to be other than "a"?
It is an 'a' not "a" and it is a char. You cannot compare a char to a string because they are different types. But what you can do is extract a substring from your string that is the length of 1 character:
if (a.substr(0,1)==b)...
Then you will be comparing "a" to "a" because .substr returns a string not a char, even if the length is 1.
Also don't forget to #include <string> if you are working with std::string.
a[0] is a character, which has the value 'a', whereas b is a string, which has a different type. This will work if an operator ==(char, string) is defined (or some variant with const's and/or ref's) but there isn't, at least in the C++ standard, so the compilation should fail. The clang compiler even gives the helpful message,
invalid operands to binary expression ('int' and 'string'...
which indicates that you're comparing different types.
Try changing it to compare a[0] and b[0]. The bracket operator is defined for strings, and returns a character, so you can compare them that way.
edit: This may look as if it doesn't answer the question. It does answer the original question; the OP changed the entirety of the question after the fact (and someone added a corresponding answer) but the original question is still there in the first paragraph. I'll delete the answer if moderators want.
Hello I am trying to write a function that converts a string to lowercase by using a pointer instead of a return value.
void makeLowerCase(std::string* in){
//for loop tolower(char from *in);}
but I have no idea how to get each char out of my pointer to use tolower() with, or how to get how many chars are in the string as
*in.length()
and
sizeof(*in)/sizeof(char)
don't work for it. The former I get an error on the use of a pointer, the latter I get the same return value for sizeof(*in) so I don't even know how I would end my for loop.
C++ has a shortcut to get the member of an object pointed to by a pointer:
in->length()
For accessing characters, use parentheses:
(*in)[i]
Instead of passing by pointer and dealing with pointer syntax you can pass the string by reference and then you can use it just like a normal std::string. If you have to use a pointer then you can either use
in->length();
or
(*in).length();
The parentheses are required in the second case as . has a higher precedence then *.
As for transforming the string to lower case you can use the built in functions from <algorithm> and and that would give you
void makeLowerCase(std::string& in)
{
std::transform(in.begin(), in.end(), in.begin(), ::tolower);
}
*in.length()
does not work because . has a higher precedence than *. Use parantheses:
(*in).length()
sizeof(*in)/sizeof(char)
is the same as
sizeof(*in) / 1
because sizeof(char) == 1. sizeof(*in) == sizeof(std::string), so this yields the size of the std::string object itsself, not the string of characters, which is implemention-defined.
This information, in combination with iterators, for_each, and lambdas, make for a pretty three-liner without any functions:
#include <cctype>
...
for (char& c : str)
c = std::tolower(c);
Notes:
Use references instead. They look better and are easier usable. Pointers should only be used in C++ for low-level stuff or when there's no way to cut them out.
For pointers you would use the pointer operator. So that would be
in->length();
However a naked loop is not the ideal way (nor is using pointers to be honest).
A better way would be to use iterators to iterate through the string and convert it that way.
for (auto it=in->begin(); it!=in->end(); ++it) {
*it = std::tolower(*it);
}
I've just been introduced to toupper, and I'm a little confused by the syntax; it seems like it's repeating itself. What I've been using it for is for every character of a string, it converts the character into an uppercase character if possible.
for (int i = 0; i < string.length(); i++)
{
if (isalpha(string[i]))
{
if (islower(string[i]))
{
string[i] = toupper(string[i]);
}
}
}
Why do you have to list string[i] twice? Shouldn't this work?
toupper(string[i]); (I tried it, so I know it doesn't.)
toupper is a function that takes its argument by value. It could have been defined to take a reference to character and modify it in-place, but that would have made it more awkward to write code that just examines the upper-case variant of a character, as in this example:
// compare chars case-insensitively without modifying anything
if (std::toupper(*s1++) == std::toupper(*s2++))
...
In other words, toupper(c) doesn't change c for the same reasons that sin(x) doesn't change x.
To avoid repeating expressions like string[i] on the left and right side of the assignment, take a reference to a character and use it to read and write to the string:
for (size_t i = 0; i < string.length(); i++) {
char& c = string[i]; // reference to character inside string
c = std::toupper(c);
}
Using range-based for, the above can be written more briefly (and executed more efficiently) as:
for (auto& c: string)
c = std::toupper(c);
As from the documentation, the character is passed by value.
Because of that, the answer is no, it shouldn't.
The prototype of toupper is:
int toupper( int ch );
As you can see, the character is passed by value, transformed and returned by value.
If you don't assign the returned value to a variable, it will be definitely lost.
That's why in your example it is reassigned so that to replace the original one.
As many of the other answers already say, the argument to std::toupper is passed and the result returned by-value which makes sense because otherwise, you wouldn't be able to call, say std::toupper('a'). You cannot modify the literal 'a' in-place. It is also likely that you have your input in a read-only buffer and want to store the uppercase-output in another buffer. So the by-value approach is much more flexible.
What is redundant, on the other hand, is your checking for isalpha and islower. If the character is not a lower-case alphabetic character, toupper will leave it alone anyway so the logic reduces to this.
#include <cctype>
#include <iostream>
int
main()
{
char text[] = "Please send me 400 $ worth of dark chocolate by Wednesday!";
for (auto s = text; *s != '\0'; ++s)
*s = std::toupper(*s);
std::cout << text << '\n';
}
You could further eliminate the raw loop by using an algorithm, if you find this prettier.
#include <algorithm>
#include <cctype>
#include <iostream>
#include <utility>
int
main()
{
char text[] = "Please send me 400 $ worth of dark chocolate by Wednesday!";
std::transform(std::cbegin(text), std::cend(text), std::begin(text),
[](auto c){ return std::toupper(c); });
std::cout << text << '\n';
}
toupper takes an int by value and returns the int value of the char of that uppercase character. Every time a function doesn't take a pointer or reference as a parameter the parameter will be passed by value which means that there is no possible way to see the changes from outside the function because the parameter will actually be a copy of the variable passed to the function, the way you catch the changes is by saving what the function returns. In this case, the character upper-cased.
Note that there is a nasty gotcha in isalpha(), which is the following: the function only works correctly for inputs in the range 0-255 + EOF.
So what, you think.
Well, if your char type happens to be signed, and you pass a value greater than 127, this is considered a negative value, and thus the int passed to isalpha will also be negative (and thus outside the range of 0-255 + EOF).
In Visual Studio, this will crash your application. I have complained about this to Microsoft, on the grounds that a character classification function that is not safe for all inputs is basically pointless, but received an answer stating that this was entirely standards conforming and I should just write better code. Ok, fair enough, but nowhere else in the standard does anyone care about whether char is signed or unsigned. Only in the isxxx functions does it serve as a landmine that could easily make it through testing without anyone noticing.
The following code crashes Visual Studio 2015 (and, as far as I know, all earlier versions):
int x = toupper ('é');
So not only is the isalpha() in your code redundant, it is in fact actively harmful, as it will cause any strings that contain characters with values greater than 127 to crash your application.
See http://en.cppreference.com/w/cpp/string/byte/isalpha: "The behavior is undefined if the value of ch is not representable as unsigned char and is not equal to EOF."