2009-08-25 6 views
28

Je suis en train de comparer un tableau de caractères à une chaîne comme ceci:C++ Comparer tableau de caractères avec la chaîne

const char *var1 = " "; 
var1 = getenv("myEnvVar"); 

if(var1 == "dev") 
{ 
    // do stuff 
} 

Cette instruction if valide jamais été aussi vrai ... quand je sortie var1 est « dev » , Je pensais peut-être qu'il a quelque chose à voir avec une chaîne terminée par zéro, mais les strlen de "dev" et var1 sont égaux ... Je pensais aussi que peut-être var1 == "dev" comparait "dev" contre l'emplacement mémoire de var1 au lieu de la valeur. * var1 == "dev" aboutit à une erreur .... essayé beaucoup de choses, probablement une solution simple pour le développeur saavy C++ (je n'ai pas codé C++ dans un temps looong).

modifier: nous avons essayé

if(strcmp(var1, "dev") == 0) 

et

if(strncmp(var1, "dev", 3) == 0) 

Merci

modifier: Après avoir testé à la maison, je vais juste suggérer mon collègue modifie la type de données à une chaîne. Je crois qu'il comparait un tableau de caractères de grande taille à une chaîne. J'ai mis en place un programme qui produit sizeof, strlen, etc pour nous aider à y travailler. Merci à tous pour votre aide.

+1

On dirait que vous utilisez des chaînes C brutes et non le C++ classe String. – tchen

+2

essayez d'utiliser un débogueur pour voir si var1 est réellement rempli avec "dev1". De plus, si var1 est réellement une chaîne de style C++, utilisez la fonction c_str() pour obtenir une chaîne de style c qui peut être comparée à votre char * en utilisant strcmp(); – NomeN

+0

Vous avez essayé strcmp; génial - quel est le résultat?(Comme c'est un bon moyen d'y aller) – xtofl

Répondre

56

Utilisation strcmp() pour comparer le contenu de chaînes:

if (strcmp(var1, "dev") == 0) { 
} 

Explication: en C, une chaîne de caractères est un pointeur vers un emplacement de mémoire qui contient des octets. La comparaison d'un char* à un char* à l'aide de l'opérateur d'égalité ne fonctionnera pas comme prévu, car vous comparez les emplacements de mémoire des chaînes plutôt que leur contenu d'octets. Une fonction telle que strcmp() va parcourir les deux chaînes, en vérifiant leurs octets pour voir s'ils sont égaux. strcmp() retournera 0 s'ils sont égaux, et une valeur non nulle s'ils diffèrent. Pour plus de détails, voir le manpage.

+0

Nous avons essayé cela aussi et cela n'a pas fonctionné malheureusement –

+3

@Chris: pourriez-vous poster un exemple de la façon dont vous utilisez 'strcmp()'? Sinon, nous ne saurons pas comment cela "n'a pas fonctionné". –

+0

Etes-vous sûr de ne pas avoir fait si (strcmp (var1, "dev"))? Un piège facile à tomber avec strcmp ... –

1

Dans ce code, vous ne comparez pas des valeurs de chaîne, vous comparez des valeurs de pointeur. Si vous voulez comparer des valeurs de chaîne, vous devez utiliser une fonction de comparaison de chaînes telle que strcmp.

if (0 == strcmp(var1, "dev")) { 
    .. 
} 
+3

Ohhh. Je déteste mettre le 0 sur la gauche (opinion personnelle évidemment). Je pense que c'est plus intuatif sur la droite et puisque vous testez le résultat contre une fonction aucune chance d'affectation. –

+5

J'appelle cela "codage Yoda" (en arrière est l'expression, hmmm?). Je préférerais utiliser des options de compilation pour attraper des affectations accidentelles. –

+0

@Fred d'accord avec vous, je ne le fais pas. :) – JaredPar

0

"dev" est pas un string est un const char * comme var1. Ainsi, vous comparez bien les adresses mémoire. Etant donné que var1 est un pointeur char, *var1 est un seul caractère (le premier caractère de la séquence de caractère pointé pour être précis). Vous ne pouvez pas comparer un char à un pointeur char, ce qui explique pourquoi cela n'a pas fonctionné. Étant donné que cela est marqué comme C++, il serait judicieux d'utiliser std::string au lieu de pointeurs de char, ce qui ferait travailler == comme prévu. (Vous avez juste besoin de faire const std::string var1 au lieu de const char *var1.

16

Vous ne travaillez pas avec des chaînes. Vous travaillez avec des pointeurs. var1 est un pointeur char (const char*). Il est pas une chaîne Si elle est. null terminé, alors certaines fonctions C seront traitent comme une chaîne, mais il est fondamentalement juste un pointeur.

alors, quand on le compare à un tableau de caractères, le tableau désintègre à un pointeur aussi bien, et le compilateur essaie alors de trouver un operator == (const char*, const char*).

Un tel opérateur existe. Il prend deux pointeurs et renvoie true s'ils pointent vers la même adresse. Le compilateur appelle cela, et votre code se brise.

SI vous voulez faire des comparaisons de chaînes, vous devez dire au compilateur que vous voulez traiter avec des chaînes , pas pointeurs.

La façon C de faire est d'utiliser la fonction strcmp:

strcmp(var1, "dev"); 

Ceci renvoie zéro si les deux chaînes sont égales . (Il retournera une valeur supérieure à zéro si le côté gauche est lexicographiquement supérieur au côté droit, et une valeur inférieure à zéro sinon.)

Pour comparer l'égalité, vous devez effectuer l'une des opérations suivantes: Cependant, C++ possède une classe string très utile. Si nous utilisons que votre code devient un peu plus simple. Bien sûr, nous pourrions créer des chaînes des deux arguments, mais il suffit de le faire avec l'un d'entre eux:

std::string var1 = getenv("myEnvVar"); 

if(var1 == "dev") 
{ 
    // do stuff 
} 

Maintenant, le compilateur rencontre une comparaison entre la chaîne et le pointeur char. Il peut gérer cela, car un pointeur char peut être implicitement converti en une chaîne, ce qui donne une comparaison chaîne/chaîne. Et ceux qui se comportent exactement comme vous vous y attendriez.

+1

Cette explication rock, _and_ conseille aussi std :: string! J'ai lu sur ce que la première fois :) – xtofl

+0

Un piège amusant avec ceci est le pliage de chaîne, dans un test de construction de version avec "foo" == "foo" sera probablement vrai car ils deviennent des pointeurs vers la même chaîne, mais le débogage a une chaîne se replier et il échouera – paulm

0

Il y a une fonction plus stable, aussi se débarrasse du pliage des cordes.

// Add to C++ source 
bool string_equal (const char* arg0, const char* arg1) 
{ 
    /* 
    * This function wraps string comparison with string pointers 
    * (and also works around 'string folding', as I said). 
    * Converts pointers to std::string 
    * for make use of string equality operator (==). 
    * Parameters use 'const' for prevent possible object corruption. 
    */ 
    std::string var0 = (std::string) arg0; 
    std::string var1 = (std::string) arg1; 
    if (var0 == var1) 
    { 
     return true; 
    } 
    else 
    { 
     return false; 
    } 
} 

Et ajouter déclaration à-tête

// Parameters use 'const' for prevent possible object corruption. 
bool string_equal (const char* arg0, const char* arg1); 

Pour l'utilisation, il suffit de placer un appel 'string_equal' comme condition de si (ou ternaire) déclaration/bloc.

if (string_equal (var1, "dev")) 
{ 
    // It is equal, do what needed here. 
} 
else 
{ 
    // It is not equal, do what needed here (optional). 
} 

Source: sinatramultimedia/FL32 codec (il est écrit par moi-même)

0

votre réflexion sur ce programme ci-dessous

#include <stdio.h> 
#include <string.h> 

int main() 
{ 
char str[][5] = { "R2D2" , "C3PO" , "R2A6" }; 
int n; 
puts ("Looking for R2 astromech droids..."); 
for (n=0 ; n<3 ; n++) 
if (strncmp (str[n],"R2xx",2) == 0) 
{ 
    printf ("found %s\n",str[n]); 
} 
return 0; 
} 
//outputs: 
// 
//Looking for R2 astromech droids... 
//found R2D2 
//found R2A6 

quand vous devriez penser à entrer quelque chose dans un tableau & puis utilisez fonctions strcmp comme le programme ci-dessus ... Découvrez un programme modifié ci-dessous

#include <iostream> 
#include<cctype> 
#include <string.h> 
#include <string> 
using namespace std; 

int main() 
{ 
int Students=2; 
int Projects=3, Avg2=0, Sum2=0, SumT2=0, AvgT2=0, i=0, j=0; 
int Grades[Students][Projects]; 

for(int j=0; j<=Projects-1; j++){ 
    for(int i=0; i<=Students; i++) { 
cout <<"Please give grade of student "<< j <<"in project "<< i << ":"; 
    cin >> Grades[j][i]; 

    } 
    Sum2 = Sum2 + Grades[i][j]; 
    Avg2 = Sum2/Students; 
} 
SumT2 = SumT2 + Avg2; 
AvgT2 = SumT2/Projects; 
cout << "avg is : " << AvgT2 << " and sum : " << SumT2 << ":"; 
return 0; 
} 

changement de chaîne, sauf qu'il ne lit que 1 entrée et jette le reste sur peut-être besoin de deux pour les boucles et deux pointeurs

#include <cstring> 
#include <iostream> 
#include <string> 
#include <stdio.h> 
using namespace std; 
int main() 
{ 
char name[100]; 
//string userInput[26]; 
int i=0, n=0, m=0; 
cout<<"your name? "; 
cin>>name; 
cout<<"Hello "<<name<< endl; 

char *ptr=name; 
for (i = 0; i < 20; i++) 
{ 
cout<<i<<" "<<ptr[i]<<" "<<(int)ptr[i]<<endl; 
} 
int length = 0; 
while(name[length] != '\0') 
{ 
length++; 
} 
        for(n=0; n<4; n++) 
       { 
          if (strncmp(ptr, "snit", 4) == 0) 
          { 
      cout << "you found the snitch " <<  ptr[i]; 
          } 
       } 
cout<<name <<"is"<<length<<"chars long"; 
} 
Questions connexes