comparaison entre chaîne littérale
-
20-09-2019 - |
Question
Ce code très simple:
#include <iostream>
using namespace std;
void exec(char* option)
{
cout << "option is " << option << endl;
if (option == "foo")
cout << "option foo";
else if (option == "bar")
cout << "opzion bar";
else
cout << "???";
cout << endl;
}
int main()
{
char opt[] = "foo";
exec(opt);
return 0;
}
générer deux avertissement:. Comparaison avec les résultats chaîne littérale dans un comportement non spécifié
Pouvez-vous expliquer exactement pourquoi ce code ne fonctionne pas, mais si je change
char opt[]
à
char *opt
il fonctionne, mais génère l'avertissement? Est-il lié à la \ 0 cessation d'emploi? Quelle est la différence entre les deux déclaration d'opt? Et si j'utilise qualificatif const? La solution est d'utiliser std :: string?
La solution
tableaux de char ou pointeurs char ne sont pas vraiment la même chose que des objets de classe de chaîne en C ++, donc ce
if (option == "foo")
ne se compare pas à la chaîne option
à la chaîne « foo » il compare le adresse de option
avec l'adresse de la chaîne « foo ». Vous devez utiliser l'une des nombreuses fonctions de comparaison de chaîne si vous voulez savoir si l'option est le même que « foo ». strcmp
est la manière évidente pour ce faire, ou vous pouvez utiliser std::string
au lieu de char*
Autres conseils
Vous pouvez utiliser l'opérateur de ==
pour comparer des chaînes uniquement si vous utilisez std::string
(ce qui est une bonne pratique). Si vous utilisez de type C char * / char [] chaînes, vous devez utiliser les fonctions C strcmp
ou strncmp
.
Vous pouvez également utiliser la std::string::operator ==
pour comparer std::string
avec une chaîne C:
std string foo = "foo";
const char *bar = "bar";
if (foo == bar)
...
La raison pour laquelle cela ne fonctionne pas parce que la comparaison ne se compare pas les chaînes, mais des pointeurs de caractères.
La raison pour laquelle il peut travail lorsque vous utilisez char * est parce que le compilateur peut décider de stocker la chaîne « opt » une fois et le réutiliser pour les deux références (je suis sûr que je l'ai vu la mise en compilateur quelque part qui indique si le compilateur le fait).
Dans le cas de l'omble opt [], les copies du compilateur La chaîne littérale dans la zone de stockage réservée au réseau d'opt (probablement sur la pile), ce qui provoque les pointeurs être différent.
Renze
On dirait que vous êtes venu de Java / C # :) Dans une chaîne de C est juste un pointeur vers la mémoire où les personnages sont stockés et ombles nul à la fin. Si les chaînes « look » égal qu'ils pointent vers différentes zones en mémoire et ne seront pas égaux. pour vérifier l'égalité soit utiliser la classe de C ++ std :: string ou la fonction C strcmp.
Pour C ++ je voudrais utiliser le std :: string solution :
#include <iostream>
#include <string>
using namespace std;
void exec(string option)
{
cout << "option is " << option << endl;
if (option == "foo")
cout << "option foo";
else if (option == "bar")
cout << "option bar";
else
cout << "???";
cout << endl;
}
int main()
{
string opt = "foo";
exec(opt);
exec("bar");
char array[] = "other";
exec(array);
return 0;
}
std :: string sait se créer à partir de char [], char *, etc., de sorte que vous pouvez toujours appeler la fonction de cette façon aussi.