I've been getting error messages saying
[Error] ISO C++ forbids comparison between pointer and integer [-fpermissive]
and don't know how to fix it.
I've searched stackoverflow for people with same issues, but only came up with this: c++ compile error: ISO C++ forbids comparison between pointer and integer which didn't answer my question. What also confused me is that the error is on line indicated by the HERE comment, which is the if statement, but I don't see any integers in the condition part.
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
using namespace std;
int main() {
char in[100];
gets(in);
int len = strlen(in);
std::string s(in);
int count = 0;
for (int i = 0; i < len; i++) {
if (s.at(i) == " ") { // <-- HERE
count += 1;
}
}
cout << count;
}
Say the input is Hello World, I am expecting output to be 1, but I didn't get any output.
The expression " " is a string literal with type const char [2].
The expression s.at(i) returns a char&.
So, s.at(i) == " " is trying to find an equality operator taking
char& on the left and a reference to the literal array const char(&)[4] on the right.
It finds one or more candidates for operator==, but the argument types don't match any exactly, so next it tries the implicit conversion sequences - this is where the char& undergoes integral promotion to int, and the array decays to const char*.
It still doesn't find a match with these, and gives up, but that explains why it has int and const char * arguments when the error is emitted.
All that is a long way of saying that you write character literals like ' ' in C++. They're not just a string of length 1 as in some other languages (and you can't write strings with single quotes at all).
Change the if statement
if (s.at(i) == ' ') {
count += 1;
}
since s.at(i) returns char&, " " is a string, and ' ' is a char.
The problem is that " " is a string literal not a character! A character literal would be ' '.
The error is a bit misleading, because " " is acutally a const char*.
C++ differentiates between character strings and single characters in the literals by different quoting symbols (" vs '). The " " in your code is the string literal that contains one space, a single space character would be written as ' '. The function std::string::at returns a single character.
A small example will show you how the compiler looks on that
#include <iostream>
#include <string>
#include <typeinfo> // for typeid
using namespace std;
int main() {
string s = "Hello, world!";
cout << typeid(" ").name() << endl;
cout << typeid(' ').name() << endl;
cout << typeid(s.at(0)).name() << endl;
return 0;
}
see online demo of above code.
But, to be precise, identical types aren't required for comparisons in C++, but the types need to be compatible. Pointers (string literals are considered constant pointers to characters, in fact pointing to the first character in the literal) and integers (to which char is promoted in your case) are not compatible. To "fix" your problem quickly, change s.at(i) == " " to s.at(i) == ' ', but your program will remain problematic: it still contains a lot of C code that's problematic in it self, too. A possible C++ version could be this:
#include <iostream>
#include <string>
using namespace std;
int main() {
int count = 0;
string line;
std::getline(cin, line);
for (const auto c: line) {
if (c == ' ') {
count++;
}
}
cout << "Your input \""<< line << "\" contains " << count << " space(s)." << endl;
return 0;
}
Related
When i try to add text to string i get random values.
Code:
#include <iostream>
using namespace std;
int main()
{
cout << "333" + 4;
}
I get some random text like:↑←#
"333" is a const char [4] not std::string as you might expect(which by the way still doesn't have operator+ for int). Adding 4, you're converting it to const char * and then moving the pointer by 4 * sizeof(char) bytes, making it point to memory with garbage in it.
It happens because those are two different types and the adding operator does not work as you may expect.
If you intend to concatenate the string literals "333" with the int value of 4 than you should simply use count like:
cout << "333" << 4; // outputs: 3334
If you want to display the sum, than use string to int conversion with the stoi() function.
cout << stoi("333") + 4; // outputs: 337
Note: When using stoi(): If the string also contains literals, than the conversion will take the integer value from the beginning of the string or will raise an error in case the string begins with literals:
cout << stoi("333ab3") + 4; // same as 333 + 4, ignoring the rest, starting a
cout << stoi("aa333aa3") + 4; // raise error as "aa" can't be casted to int
As you want to add text to text, solution would be to use proper types:
cout << std::string( "333" ) + "4";
or for c++14 or later:
using namespace std::string_literals;
cout << "333"s + "4"s;
I honestly do not know what you are trying to achieve by adding int to string. In case you want to add 333+4, you need to Parse string in to int like this :
edit:Typo
#include
using namespace std;
int main()
{
cout << std::stoi("333") + 4;
}
int main()
{
char hmm[1000];
cin.getline(hmm, 1000);
cout << hmm << endl; //this was to test if I could assign my input to the array properly
for (int sayac = 0; hmm[sayac] != '#'; sayac++) {
if (!isdigit(hmm[sayac])) {
if (islower(hmm[sayac]))
cout << toupper(hmm[sayac]);
else if (isupper(hmm[sayac]))
cout << tolower(hmm[sayac]);
else
cout << hmm[sayac];
}
}
"Write a program that reads keyboard input to the # symbol and that echoes the input
except for digits, converting each uppercase character to lowercase, and vice versa.
(Don’t forget the cctype family.) "
I'm doing this exercise from the primer book. But when I run it, it returns the ascii order of the char, not the uppercase/lowercase version of the character. Couldn't figure out the problem. Can someone tell my why please?
(I may have other problems about the exercise, please don't correct them if I have. I want to fix it on my own (except the problem I explained), but I can't check the other ones as I have this problem.
When writing
std::cout << toupper('a');
the following happen:
int toupper(int ch) is called, and returns an integer whose value is 'A' (0x41).
std::basic_ostream::operator<<(std::cout, 0x41) is called, that is the int (2) overload since an int was provided.
Overall, it prints "65".
As a solution, you can cast back your upper case to a char:
std::cout << static_cast<char>(toupper('a'));
It's a question of representation. There is no difference between a character and that character's numeric value. It's all in how you choose to display it. For example, the character 'a' is just a constant with a value equal to the character's numeric value.
The problem you are having is that std::toupper and std::tolower return an int rather than a char. One reason for that is that they handle EOF values, which are not necessarily representable by char. As a consequence, std::cout see you are trying to print an int and not a char. The standard behavior for streaming an int is to print the number. The solution is then to cast your result to char to force the value to be interpreted as a character. You can use something like std::cout << static_cast<char>(std::toupper(hmm[sayac]));.
Try the following :
#include <cctype>
#include <iostream>
int main()
{
char hmm[1000];
std::cin.getline(hmm, 1000);
std::cout << hmm << std::endl; //this was to test if I could assign my input to the array properly
for (int sayac = 0; hmm[sayac] != '#'; sayac++) {
if (!std::isdigit(hmm[sayac])) {
if (std::islower(hmm[sayac]))
std::cout << static_cast<char>(std::toupper(hmm[sayac]));
else if (isupper(hmm[sayac]))
std::cout << static_cast<char>(std::tolower(hmm[sayac]));
else
std::cout << hmm[sayac];
}
}
}
You should also consider using an std::string instead of an array of char of arbitrary length. Also, take note that you have undefined behavior if the input string does not contain #.
I tried making a small program using the libraries "iostream" and "String" to display a given string backwardly as the output on the command prompt. I used a recursive returning-value (string) function to perform the whole process of getting the given string in backward and returning it to the main function to be displayed on screen, as you can see below:
#include <iostream>
#include <string>
using namespace std;
string rev(string, int);
int main() {
string let;
cout << "Enter your string: ";
cin >> let;
cout << "The string in reverse is: " << rev(let, let.length());
cout << endl;
return 0;
}
string rev(string x, int y) {
if (y != 0 )
return x[y - 1] + rev(x, y - 1);
else
return "\0";
}
What I don't get about the process, is that while the concatenation performed on the rev function, recursively, and with the char variables works correctly and returns the string in backward to the main function, trying to concatenate the char variables normally like this gives rubbish as the output:
#include <iostream>
#include <string>
using namespace std;
int main() {
string hd;
string ah = "foo";
hd = ah[2] + ah[1] + ah[0];
cout << hd << endl;
return 0;
}
And even if I add to the "hd" chain "\0", it still gives rubbish.
Your first example implicitly converts characters to strings and uses appropriate operator +
While your second example is adding up characters
https://en.cppreference.com/w/cpp/string/basic_string/operator_at
returns reference to character at position
Writing instead
hd = ""s + ah[2] + ah[1] + ah[0];
will, informally speaking, put + into a "concatenation mode", achieving what you want. ""s is a C++14 user-defined literal of type std::string, and that tells the compiler to use the overloaded + operator on the std::string class on subsequent terms in the expression. (An overloaded + operator is also called in the first example you present.)
Otherwise, ah[2] + ah[1] + ah[0] is an arithmetic sum over char values (each one converted to an int due to implicit conversion rules), with the potential hazard of signed overflow on assignment to hd.
How about making use of everything that's already available?
string rev(const string &x) { return string{x.rbegin(), x.rend()}; }
Reverse iterators allow you to reverse the string, and the constructor of string with 2 iterators, constructs an element by iterati from begin to end.
int main()
{
char hmm[1000];
cin.getline(hmm, 1000);
cout << hmm << endl; //this was to test if I could assign my input to the array properly
for (int sayac = 0; hmm[sayac] != '#'; sayac++) {
if (!isdigit(hmm[sayac])) {
if (islower(hmm[sayac]))
cout << toupper(hmm[sayac]);
else if (isupper(hmm[sayac]))
cout << tolower(hmm[sayac]);
else
cout << hmm[sayac];
}
}
"Write a program that reads keyboard input to the # symbol and that echoes the input
except for digits, converting each uppercase character to lowercase, and vice versa.
(Don’t forget the cctype family.) "
I'm doing this exercise from the primer book. But when I run it, it returns the ascii order of the char, not the uppercase/lowercase version of the character. Couldn't figure out the problem. Can someone tell my why please?
(I may have other problems about the exercise, please don't correct them if I have. I want to fix it on my own (except the problem I explained), but I can't check the other ones as I have this problem.
When writing
std::cout << toupper('a');
the following happen:
int toupper(int ch) is called, and returns an integer whose value is 'A' (0x41).
std::basic_ostream::operator<<(std::cout, 0x41) is called, that is the int (2) overload since an int was provided.
Overall, it prints "65".
As a solution, you can cast back your upper case to a char:
std::cout << static_cast<char>(toupper('a'));
It's a question of representation. There is no difference between a character and that character's numeric value. It's all in how you choose to display it. For example, the character 'a' is just a constant with a value equal to the character's numeric value.
The problem you are having is that std::toupper and std::tolower return an int rather than a char. One reason for that is that they handle EOF values, which are not necessarily representable by char. As a consequence, std::cout see you are trying to print an int and not a char. The standard behavior for streaming an int is to print the number. The solution is then to cast your result to char to force the value to be interpreted as a character. You can use something like std::cout << static_cast<char>(std::toupper(hmm[sayac]));.
Try the following :
#include <cctype>
#include <iostream>
int main()
{
char hmm[1000];
std::cin.getline(hmm, 1000);
std::cout << hmm << std::endl; //this was to test if I could assign my input to the array properly
for (int sayac = 0; hmm[sayac] != '#'; sayac++) {
if (!std::isdigit(hmm[sayac])) {
if (std::islower(hmm[sayac]))
std::cout << static_cast<char>(std::toupper(hmm[sayac]));
else if (isupper(hmm[sayac]))
std::cout << static_cast<char>(std::tolower(hmm[sayac]));
else
std::cout << hmm[sayac];
}
}
}
You should also consider using an std::string instead of an array of char of arbitrary length. Also, take note that you have undefined behavior if the input string does not contain #.
I'm a beginner in C++ Programming language. I wanted to write a program that take the alphabets in a string array called str, and copy it in a new array called str_alpha.
And the same goes to numbers, the program copies it from str array to str_digit array.
There's my humble code, it might be full of errors and stuff. But this is what I could do now with my very little experience.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
using namespace std;
char str[100], str_alpha[100], str_digit[100];
int main()
{
gets(str);
for (int i=0 ; str[i] ; i++)
{
if (isalpha(str[i]))
{
strcpy (str_alpha[i] , str[i]);
}
else if (isdigit(str[i]))
{
strcpy (str_digit[i] , str[i]);
}
}
cout << "Alpha is " << str_alpha << endl ;
cout << "Number is : " << str_digit << endl ;
return 0;
}
And it gives my those errors :
F:\C++Progs\string\main.cpp||In function `int main()':|
F:\C++Progs\string\main.cpp|18|error: invalid conversion from `char' to `char*'|
F:\C++Progs\string\main.cpp|18|error: initializing argument 1 of `char* strcpy(char*, const char*)'|
F:\C++Progs\string\main.cpp|18|error: invalid conversion from `char' to `const char*'|
F:\C++Progs\string\main.cpp|18|error: initializing argument 2 of `char* strcpy(char*, const char*)'|
F:\C++Progs\string\main.cpp|22|error: invalid conversion from `char' to `char*'|
F:\C++Progs\string\main.cpp|22|error: initializing argument 1 of `char* strcpy(char*, const char*)'|
F:\C++Progs\string\main.cpp|22|error: invalid conversion from `char' to `const char*'|
F:\C++Progs\string\main.cpp|22|error: initializing argument 2 of `char* strcpy(char*, const char*)'|
||=== Build finished: 8 errors, 0 warnings ===|
Help me please.
Thanks in advance.
First of all, strcpy copies C strings (character arrays) not chars. Additionally, the lines strcpy(str_digit[i],str[i]) and strcpy(str_alpha[i], str[i]) would still probably be wrong even if this wasn't the case. Since you haven't initialised the arrays str_digit and str_alpha, you'll get a lot of garbage values while printing them and if any of those garbage values happen to be 0x00, the cout statements will fail to print the whole string. As already mentioned, you really should be using std::string rather than char[] or char*. Having said that, here are corrected versions of your code for both char[] and std::string.
Using gets is bad practice and you might consider using std::cin instead. And you might want to use an iterator rather than a simple for loop.
//using char[]
#include <iostream>
using namespace std;
int main()
{
char str[100] , str_alpha[100] , str_digit[100] ;
int alpha_counter=0, digit_counter=0;
cin.get(str, 99);
for (int i=0 ; str[i] ; i++)
{
if(isalpha(str[i]))
{
str_alpha[alpha_counter] = str[i];
alpha_counter++;
}
else if (isdigit(str[i]))
{
str_digit[digit_counter] = str[i];
digit_counter++;
}
}
str_alpha[alpha_counter] = 0;
str_digit[digit_counter] = 0;
cout << "Alpha is " << str_alpha << endl ;
cout << "Number is : " << str_digit << endl ;
return 0;
}
And the version using std::string:
//using std::string
#include <iostream>
using namespace std;
int main()
{
string str, str_alpha , str_digit;
cin >> str ;
for (string::iterator it = str.begin();it<str.end();it++)
{
if(isalpha(*it))
{
str_alpha += *it;
}
else if (isdigit(*it))
{
str_digit += *it;
}
}
cout << "Alpha is " << str_alpha << endl ;
cout << "Number is : " << str_digit << endl ;
return 0;
}
Both versions compile without warnings on g++ 4.2.1 with -Wall and -pedantic.
I'm a beginner in C++ Programming language.
The do not use char* and the likes; use C++ predefined types for this, in your case string:
string str;
cin >> str;
string alpha;
string digit;
for (unsigned int i = 0; i < str.length(); ++i) {
char chr = str[i];
if (isalpha(chr))
alpha.push_back(chr);
else if (isdigit(chr))
digit.push_back(chr);
}
Furthermore, strcpy is, as the name says, used to copy strings, not individual chars. You can copy those directly by assigning them. No function call needed.
The problem is that strcpy is intended to copy a whole string. In this case, you're copying individual characters, not entire strings. For individual characters, you can use a simple assignment.
There are a few other things to deal with though. First of all, you have:
char str[100];
outside any function. That defines an array of 100 char's, and initializes all of them to 0. You then loop through that, trying to find characters that are classified as alphabetical or digits -- which will never happen, because a zero byte ('\0', not '0') is never either one.
In fact, as far as a I can tell, you don't need str at all. What you (apparently) want is roughly like:
for (i in 0 to 127)
if (alpha(i))
add i to str_alpha
else if (digit(i))
add i to str_digit
As Konrad Rudolph already pointed out, you'd probably be much better off making str_digit and str_alpha into std::string's than arrays of char. Arrays can do the job, but they'll be more work to get really correct.
strcpy copies a whole string. Use plain assignment (= operator) for copying characters.
You're copying characters over, even though strcpy is designed to copy over strings (arrays of characters). The compiler is therefore complaining because you're supplying 'char' rather than 'char *'. If you're copying characters over then just do:
str_alpha[i] = str[i];