1

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.

Wolf
  • 9,679
  • 7
  • 62
  • 108
andy zhang
  • 21
  • 6
  • 8
    Never *ever* use `gets`! It's a [dangerous](https://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used) function that have been removed from both C and C++. If you want to read a line from the standard input, use [`std::getline`](https://en.cppreference.com/w/cpp/string/basic_string/getline) to read into a [`std::string`](https://en.cppreference.com/w/cpp/string/basic_string). – Some programmer dude Apr 05 '19 at 10:14
  • 3
    As for your problem, I suggest you take a couple of steps back, and go back to your book, tutorial or class-notes and think about the difference between strings (delimited by double-quote `"`) and characters (delimited by single-quote `'`). – Some programmer dude Apr 05 '19 at 10:16
  • 1
    I understand that you’re mystified – the message makes no sense at all until you’re very familiar with the implicit type conversions in C++. – molbdnilo Apr 05 '19 at 10:19
  • 1
    Possible duplicate of [c++ compile error: ISO C++ forbids comparison between pointer and integer](https://stackoverflow.com/questions/2263681/c-compile-error-iso-c-forbids-comparison-between-pointer-and-integer) – Wolf Apr 05 '19 at 10:51
  • @Some programmer dude Won't `std::getline` give a \n if you input more than a line? – andy zhang Apr 05 '19 at 10:55
  • look at the [examples](https://en.cppreference.com/w/cpp/string/basic_string/getline#Example), you use a `std::string` for getting input into it `std::getline(std::cin, name);` – Wolf Apr 05 '19 at 11:06
  • The newline will be read but not put into the string (perhaps you're thinking about the C function [`fgets`](https://en.cppreference.com/w/c/io/fgets)?). – Some programmer dude Apr 05 '19 at 11:48

4 Answers4

4

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).

Useless
  • 64,155
  • 6
  • 88
  • 132
  • :) I was not only too late, but also forgot about the promotion thing. Interestingly, error messages have always too few informations for beginners and too much of it for the experienced programmer. Good explanation! – Wolf Apr 05 '19 at 10:55
  • Yeah, it took me a couple of attempts to write it out correctly. I feel like the compiler should really describe the overload resolution sequence instead of just showing the promoted types at the end. – Useless Apr 05 '19 at 12:21
3

Change the if statement

if (s.at(i) == ' ') {
    count += 1;
}

since s.at(i) returns char&, " " is a string, and ' ' is a char.

Tetix
  • 317
  • 2
  • 10
  • 8
    This answer, while technically correct, would be improved if you'd explain exactly _why_ changing the loop as described solves the issue, and what the underlying issue actually is. – You Apr 05 '19 at 10:17
0

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*.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • *" " is acutally a `const char*`* ... which *is* a pointer whereas the char involved gets [promoted to `int`](https://stackoverflow.com/a/55533498/2932052). C++ error messages are always confusing for beginners. – Wolf Apr 05 '19 at 11:02
0

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;
}
Wolf
  • 9,679
  • 7
  • 62
  • 108