1
votes

Problème de comparaison entre pointeur et entier C ++

J'ai reçu des messages d'erreur disant

[Erreur] ISO C ++ interdit la comparaison entre le pointeur et l'entier [-fpermissive]

et je ne sais pas comment le résoudre.

J'ai recherché dans stackoverflow des personnes ayant les mêmes problèmes, mais je n'ai trouvé que ceci: c++ erreur de compilation: ISO C ++ interdit la comparaison entre le pointeur et l'entier , ce qui n'a pas été le cas ne réponds pas à ma question. Ce qui m'a également dérouté, c'est que l'erreur est sur la ligne indiquée par le commentaire HERE, qui est l'instruction if, mais je ne vois aucun entier dans la partie condition.

#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;
}

Disons que l'entrée est Hello World, je m'attends à ce que la sortie soit 1 , mais je n'ai obtenu aucune sortie.


7 commentaires

Jamais jamais utiliser gets ! C'est un dangereux fonction qui ont été supprimées à la fois de C et C ++. Si vous souhaitez lire une ligne à partir de l'entrée standard, utilisez std: : getline pour lire dans un std :: chaîne .


En ce qui concerne votre problème, je vous suggère de revenir en arrière, de revenir à votre livre, tutoriel ou notes de cours et de réfléchir à la différence entre les chaînes (délimitées par des guillemets ") caractères (délimités par des guillemets simples ').


Je comprends que vous êtes mystifié - le message n'a aucun sens tant que vous n'êtes pas très familier avec les conversions de types implicites en C ++.


Copie possible de erreur de compilation C ++: ISO C ++ interdit comparaison entre pointeur et entier


@Quelque programmeur mec std :: getline ne donnera-t-il pas un \ n si vous entrez plus d'une ligne?


regardez les exemples , vous utilisez un std :: string pour y entrer std :: getline (std :: cin, name);


La nouvelle ligne sera lue mais pas insérée dans la chaîne (peut-être pensez-vous à la fonction C fgets ?).


4 Réponses :


2
votes

Modifiez l'instruction if

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

car s.at (i) renvoie le caractère &, "" est une chaîne et '' est un caractère.


1 commentaires

Cette réponse, bien que techniquement correcte, serait améliorée si vous expliquiez exactement pourquoi changer la boucle comme décrit résout le problème, et quel est réellement le problème sous-jacent.



0
votes

Le problème est que "" est une chaîne littérale et non un caractère! Un caractère littéral serait '' .

L'erreur est un peu trompeuse, car "" est en fait un const char * .


1 commentaires

"" est en fait un const char * ... qui est un pointeur alors que le caractère impliqué obtient promu à int . Les messages d'erreur C ++ sont toujours déroutants pour les débutants.



4
votes

L'expression "" est une chaîne littéral avec le type const char [2] .

L'expression s.at (i) renvoie un caractère & .

Donc, s.at (i) == "" essaie de trouver un opérateur d'égalité prenant char & à gauche et une référence au tableau littéral const char (&) [4] à droite.

Il trouve un ou plusieurs candidats pour operator == , mais les types d'arguments ne correspondent pas exactement, alors il essaie ensuite la promotion intégrale vers int , et le tableau se désintègre en const char * < / code>.

Il ne trouve toujours pas de correspondance avec ceux-ci, et abandonne, mais cela explique pourquoi il a des arguments int et const char * lorsque l'erreur est émise.

Tout cela est une longue façon de dire que vous écrivez des littéraux de caractères comme '' en C ++. Il ne s'agit pas simplement d'une chaîne de longueur 1 comme dans d'autres langues (et vous ne pouvez pas du tout écrire des chaînes avec des guillemets simples).


2 commentaires

:) Je n'étais pas seulement trop tard, mais j'ai aussi oublié la promotion. Fait intéressant, les messages d'erreur ont toujours trop peu d'informations pour les débutants et trop pour le programmeur expérimenté. Bonne explication!


Ouais, il m'a fallu quelques tentatives pour l'écrire correctement. Je pense que le compilateur devrait vraiment décrire la séquence de résolution de surcharge au lieu de simplement montrer les types promus à la fin.



0
votes

C ++ différencie les chaînes de caractères et les caractères simples dans les littéraux par différents symboles de guillemet ( " vs '). Le " " dans votre code est la chaîne littérale qui contient un espace , un seul caractère d'espace serait écrit comme '' . La fonction std :: string :: at renvoie un seul caractère. Un petit exemple vous montrera à quoi ressemble le compilateur à ce sujet

#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;
}

voir démo en ligne du code ci-dessus .

Mais, pour être précis, des types identiques ne sont pas nécessaires pour les comparaisons en C ++, mais les types doivent être compatible . Pointeurs (les littéraux de chaîne sont considérés comme des pointeurs constants vers des caractères, pointant en fait vers le premier caractère du littéral) et des entiers (vers lesquels char est promu dans votre ca se) ne sont pas compatibles . Pour "résoudre" votre problème rapidement, remplacez s.at (i) == "" par s.at (i) == '' , mais votre programme restera problématique: il contient encore beaucoup de code C qui est également problématique en lui-même. Une possible version C ++ pourrait être la suivante:

#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;
}


0 commentaires