Comparing element in string with length-1 string in C++ - c++

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.

Related

how adding string and numbers in cpp works using + operator?

I've used cpp for quite a while, I was known that we cannot add string and numbers(as + operator is not overloaded for that). But , I saw a code like this.
#include <iostream>
using namespace std;
int main() {
string a = "";
a += 97;
cout << a;
}
this outputs 'a' and I also tried this.
string a ="";
a=a+97;
The second code gives a compilation error(as invalid args to + operator, std::string and int).
I don't want to concatenate the string and number.
What is the difference? Why does one work but not the other?
I was expecting that a+=97 is the same as a=a+97 but it appears to be different.
The first snippet works because std::string overrides operator+= to append a character to a string. 97 is the ASCII code for 'a', so the result is "a".
The second snippet does not work because there is no + operator defined that accepts a std::string and an int, and no conversion constructor to make a std::string out of an int or char. There two overloads of the + operator that take a char, but the compiler cannot tell which one to use. The match is ambiguous, so an error is reported.

Can't find toupper and erase

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!

How to compare boost::string_ref to std::string

I'm trying to make boost::string_ref working as I want to, but I'm facing a problem right now - following code does not compile:
#include <boost/utility/string_ref.hpp>
#include <iostream>
#include <string>
using namespace std;
int main() {
string test = "test";
boost::string_ref rtest(test);
cout << (rtest == "test")<<endl;
}
and the gcc throws 30kB error log, starting with
source.cpp: In function 'int main()':
source.cpp:10:19: error: no match for 'operator==' (operand types are 'boost::string_ref {aka boost::basic_string_ref<char, std::char_traits<char> >}' and 'const char [5]')
cout << (rtest == "test")<<endl;
^
How to compare boost::string_ref to std::string?
Honestly, I'd just avoid using string_ref entirely until it matures. The fact that you can't compare a string_ref to a std::string or a const char * out of the box should set alarm bells ringing (looks like they forgot to write a bunch of comparison operators), and worse, it doesn't look like the library received sufficient testing (e.g. bug 8067!).
Just make a string_ref out of the string. They are very cheap to construct. Though against a string literal, you may want to include the length. Otherwise it's going to iterate once to find the end of the string, and then iterate again to compare them. Just make sure that if you change the string, you keep the count up to date.
cout << (rtest == boost::string_ref("test",4)) << endl;
With a std::string, you don't need to worry about the count, because string_ref will just call the size() member function, which is also very cheap.

C++ comparing a char to a string literal [duplicate]

This question already has answers here:
c++ compile error: ISO C++ forbids comparison between pointer and integer
(5 answers)
Closed 5 years ago.
Beginning programmer here...
I'm writing a very simply program for my computer science class and I ran into an issue that I'd like to know more about. Here is my code:
#include <iostream>
using namespace std;
int main(int argc, const char * argv[])
{
char courseLevel;
cout << "Will you be taking graduate or undergraduate level courses (enter 'U'"
" for undergraduate,'G' for graduate.";
cin >> courseLevel;
if (courseLevel == "U")
{
cout << "You selected undergraduate level courses.";
}
return 0;
}
I'm getting two error messages for my if statement:
1) Result of comparison against a string literal is unspecified (use strncmp instead).
2) Comparison between pointer and integer ('int' and 'const char*').
I seem to have resolved the issue by enclosing my U in single quotes, or the program at least works anyway. But, as I stated, I'd simply like to understand why I was getting the error so I can get a better understanding of what I'm doing.
You need to use single quotes instead.
In C, (and many other languages) a character constant is a single character1 contained in single quotes:
'U'
While a string literal is any number of characters contained in double quotes:
"U"
You declared courseLevel as a single character: char courseLevel; So you can only compare that to another single char.
When you do if (courseLevel == "U"), the left side is a char, while the right side is a const char* -- a pointer to the first char in that string literal. Your compiler is telling you this:
Comparison between pointer and integer ('int' and 'const char*')
So your options are:
if (courseLevel == 'U') // compare char to char
Or, for sake of example:
if (courseLevel == "U"[0]) // compare char to first char in string
Note for completeness: You can have mulit-character constants:
int a = 'abcd'; // 0x61626364 in GCC
But this is certainly not what you're looking for.
Rapptz is right, but I think some more elaboration should help...
courseLevel == "U"
In C and C++, double-quotes create string literals - which are arrays of characters finishing with a numerical-0 ASCII-NUL terminating sentinel character so programs can work out where the text ends. So, you basically are asking if a character is equal to an array of characters... they just can't be compared. Similar questions that are valid are:
does this character variable hold a specific character value: courseLevel == 'U'
does this character variable appear in a specific array: strchr(courseLevel, "U")
does this character variable match the first element in a specific array: courseLevel == "U"[0]
Of course, the first one of these is the one that makes intuitive sense in your program.
The reason why you get an error is because string literals in C and C++ end with a null terminated character \0 while single characters don't. So when you compare to a char to a string literal you're comparing the character literal to a char array {'U','\0'}.

In C++, I thought you could do "string times 2" = stringstring?

I'm trying to figure out how to print a string several times. I'm getting errors. I just tried the line:
cout<<"This is a string. "*2;
I expected the output: "This is a string. This is a string.", but I didn't get that. Is there anything wrong with this line? If not, here's the entire program:
#include <iostream>
using namespace std;
int main()
{
cout<<"This is a string. "*2;
cin.get();
return 0;
}
My compiler isn't open because I am doing virus scans, so I can't give the error message. But given the relative simplicity of this code for this website, I'm hoping someone will know if I am doing anything wrong by simply looking.
Thank you for your feedback.
If you switch to std::string, you can define this operation yourself:
std::string operator*(std::string const &s, size_t n)
{
std::string r; // empty string
r.reserve(n * s.size());
for (size_t i=0; i<n; i++)
r += s;
return r;
}
If you try
std::cout << (std::string("foo") * 3) << std::endl
you'll find it prints foofoofoo. (But "foo" * 3 is still not permitted.)
There is an operator+() defined for std::string, so that string + string gives stringstring, but there is no operator*().
You could do:
#include <iostream>
#include <string>
using namespace std;
int main()
{
std::string str = "This is a string. ";
cout << str+str;
cin.get();
return 0;
}
As the other answers pointed there's no multiplication operation defined for strings in C++ regardless of their 'flavor' (char arrays or std::string). So you're left with implementing it yourself.
One of the simplest solutions available is to use the std::fill_n algorithm:
#include <iostream> // for std::cout & std::endl
#include <sstream> // for std::stringstream
#include <algorithm> // for std::fill_n
#include <iterator> // for std::ostream_iterator
// if you just need to write it to std::cout
std::fill_n( std::ostream_iterator< const char* >( std::cout ), 2, "This is a string. " );
std::cout << std::endl;
// if you need the result as a std::string (directly)
// or a const char* (via std::string' c_str())
std::stringstream ss;
std::fill_n( std::ostream_iterator< const char* >( ss ), 2, "This is a string. " );
std::cout << ss.str();
std::cout << std::endl;
Indeed, your code is wrong.
C++ compilers treat a sequence of characters enclosed in " as a array of characters (which can be multibyte or singlebyte, depending on your compiler and configuration).
So, your code is the same as:
char str[19] = "This is a string. ";
cout<<str * 2;
Now, if you check the second line of the above snippet, you'll clearly spot something wrong. Is this code multiplying an array by two? should pop in your mind. What is the definition of multiplying an array by two? None good.
Furthermore, usually when dealing with arrays, C++ compilers treat the array variable as a pointer to the first address of the array. So:
char str[19] = "This is a string. ";
cout<<0xFF001234 * 2;
Which may or may not compile. If it does, you code will output a number which is the double of the address of your array in memory.
That's not to say you simply can't multiply a string. You can't multiply C++ strings, but you can, with OOP, create your own string that support multiplication. The reason you will need to do that yourself is that even std strings (std::string) doesn't have a definition for multiplication. After all, we could argue that a string multiplication could do different things than your expected behavior.
In fact, if need be, I'd write a member function that duplicated my string, which would have a more friendly name that would inform and reader of its purpose. Using non-standard ways to do a certain thing will ultimately lead to unreadable code.
Well, ideally, you would use a loop to do that in C++. Check for/while/do-while methods.
#include <iostream>
#include <string>
using namespace std;
int main()
{
int count;
for (count = 0; count < 5; count++)
{
//repeating this 5 times
cout << "This is a string. ";
}
return 0;
}
Outputs:
This is a string. This is a string. This is a string. This is a string. This is a string.
Hey there, I'm not sure that that would compile. (I know that would not be valid in c# without a cast, and even then you still would not receive the desired output.)
Here would be a good example of what you are trying to accomplish. The OP is using a char instead of a string, but will essentially function the same with a string.
Give this a whirl:
Multiply char by integer (c++)
cout<<"This is a string. "*2;
you want to twice your output. Compiler is machine not a human. It understanding like expression and your expression is wrong and generate an error .
error: invalid operands of types
'const char [20]' and 'int' to binary
'operator*'