C ++ Сравнить массив символов со строкой - PullRequest
35 голосов
/ 25 августа 2009

Я пытаюсь сравнить массив символов со строкой примерно так:

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

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

Это выражение if никогда не проверяется как истинное ... когда я вывожу var1, это "dev", я подумал, может быть, это как-то связано со строкой с нулевым символом в конце, но strlen из "dev" и var1 равны. .. Я также подумал, что, возможно, var1 == «dev» сравнивал «dev» с местом в памяти var1 вместо значения. * var1 == "dev" приводит к ошибке .... пробовал много вещей, возможно, простое решение для разработчика saavy c ++ (я не кодировал c ++ за долгое время).

редактировать: мы пробовали

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

и

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

Спасибо

edit: После тестирования дома я просто собираюсь предложить моему коллеге изменить тип данных на строку. Я полагаю, он сравнивал массив символов большого размера со строкой. Я собрал программу, которая выводит sizeof, strlen и т. Д., Чтобы помочь нам в этом. Спасибо всем за помощь.

Ответы [ 6 ]

64 голосов
/ 25 августа 2009

Используйте strcmp() для сравнения содержимого строк:

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

Объяснение: в C строка - это указатель на ячейку памяти, которая содержит байты. Сравнение char* с char* с использованием оператора равенства не будет работать должным образом, поскольку вы сравниваете ячейки памяти строк, а не их байтовое содержимое. Функция, такая как strcmp(), будет перебирать обе строки, проверяя их байты, чтобы увидеть, равны ли они. strcmp() вернет 0, если они равны, и ненулевое значение, если они различаются. Для получения дополнительной информации см. Справочную страницу .

18 голосов
/ 26 августа 2009

Ты не работаешь со строками. Вы работаете с указателями. var1 - это указатель на символ (const char*). Это не строка. Если он завершается нулем, то некоторые функции C будут обрабатывать как строку, но в основном это просто указатель.

Таким образом, когда вы сравниваете его с массивом char, массив также распадается на указатель, и компилятор затем пытается найти operator == (const char*, const char*).

Такой оператор существует. Он принимает два указателя и возвращает true, если они указывают на один и тот же адрес. Таким образом, компилятор вызывает это, и ваш код ломается.

Если вы хотите сравнивать строки, вы должны указать компилятору, что вы хотите иметь дело с строками , а не указателями .

C способ сделать это - использовать функцию strcmp:

strcmp(var1, "dev");

Возвращает ноль, если две строки равны . (Будет возвращено значение больше нуля, если левая сторона лексикографически больше правой части, а значение меньше нуля в противном случае.)

Итак, для сравнения на равенство вам нужно сделать одно из них:

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

Однако в C ++ есть очень полезный класс string. Если мы используем это, ваш код становится немного проще. Конечно, мы можем создавать строки из обоих аргументов, но нам нужно сделать это только с одним из них:

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

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

Теперь компилятор встречает сравнение между строкой и указателем на символ. Он может справиться с этим, потому что указатель на символ может быть неявно преобразован в строку, что дает сравнение строк / строк. И они ведут себя точно так, как вы ожидаете.

1 голос
/ 25 августа 2009

В этом коде вы не сравниваете строковые значения, вы сравниваете значения указателей. Если вы хотите сравнить строковые значения, вам нужно использовать функцию сравнения строк, например strcmp.

if ( 0 == strcmp(var1, "dev")) {
  ..
}
0 голосов
/ 01 октября 2016

Ваше мнение об этой программе ниже

#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

когда вы должны подумать о вводе чего-либо в массив, а затем использовать функции strcmp, как в приведенной выше программе ... посмотрите модифицированную программу ниже

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

изменить на строку, за исключением того, что он читает только 1 ввод и выбрасывает остальные может понадобиться два для циклов и два указателя

#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";
}
0 голосов
/ 04 сентября 2015

Есть более стабильная функция, также избавляет от сворачивания строки.

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

И добавить объявление в заголовок

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

Для использования просто поместите вызов 'string_equal' как условие оператора if (или троичного) / блока.

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

Источник: sinatramultimedia / fl32 codec (написано мной)

0 голосов
/ 26 августа 2009

«dev» - это не string, это const char *, как var1. Таким образом, вы действительно сравниваете адреса памяти. Поскольку var1 является указателем символа, *var1 является одиночным символом (первый символ последовательности указанных символов должен быть точным). Вы не можете сравнить char с указателем char, поэтому это не сработало.

Учитывая, что это помечено как c ++, было бы разумно использовать std::string вместо указателей на символы, что заставило бы == работать как ожидалось (Вам просто нужно сделать const std::string var1 вместо const char *var1.

...