C ++ будет игнорировать оператор if при использовании system () и while [duplicate]

Проблема, с которой вы сталкиваетесь, заключается в том, что вы пытаетесь ссылаться на факты / переменные одного хоста на другие хосты. Вы должны иметь в виду, что в Ansible переменная app_git_sha1, назначенная хосту localhost, отличается от переменной app_git_sha1, назначенной хосту main или любому другому хосту. Если вы хотите получить доступ к фактам / переменным хостов с другого хоста, вам необходимо явно ссылаться на него с помощью переменной hostvars. .

Предположим, что у вас есть подобная пьеса:

- hosts: localhost
  tasks:   
    - command: /bin/echo "this is a test"
      register: foo


- hosts: localhost
  tasks:
    - debug: var=foo

Это будет работать, потому что вы 'ссылается на экземпляр хоста localhost и localhosts переменной foo в обеих играх. Вывод этой пьесы выглядит примерно так:

PLAY [localhost] **************************************************************

GATHERING FACTS ***************************************************************
ok: [localhost]

TASK: [command /bin/echo "this is a test"] ************************************
changed: [localhost]

PLAY [localhost] **************************************************************

GATHERING FACTS ***************************************************************
ok: [localhost]

TASK: [debug var=foo] *********************************************************
ok: [localhost] => {
    "var": {
        "foo": {
            "changed": true,
            "cmd": [
                "/bin/echo",
                "this is a test"
            ],
            "delta": "0:00:00.004585",
            "end": "2015-11-24 20:49:27.462609",
            "invocation": {
                "module_args": "/bin/echo \"this is a test\"",
                "module_complex_args": {},
                "module_name": "command"
            },
            "rc": 0,
            "start": "2015-11-24 20:49:27.458024",
            "stderr": "",
            "stdout": "this is a test",
            "stdout_lines": [
                "this is a test"
            ],
            "warnings": []
        }
    }
}

Если вы немного измените эту игру, чтобы запустить первое воспроизведение на одном хосте, а второе воспроизведение на другом хосте, вы получите сообщение об ошибке вы столкнулись. Решение состоит в том, чтобы использовать встроенную переменную hostvars Ansible, чтобы второй узел явно ссылался на первую переменную хоста. Поэтому измените первый пример следующим образом:

- hosts: localhost
  tasks:

    - command: /bin/echo "this is a test"
      register: foo


- hosts: anotherhost
  tasks:
    - debug: var=foo
      when: foo is defined

    - debug: var=hostvars['localhost']['foo']
      when: hostvars['localhost']['foo'] is defined

. Вывод этой пьесы показывает, что первая задача пропущена, потому что foo не определяется хостом anotherhost. Но вторая задача выполняется успешно, потому что она явно ссылается на экземпляр localhosts переменной foo:

TASK: [debug var=foo] *********************************************************
skipping: [anotherhost]

TASK: [debug var=hostvars['localhost']['foo']] **************************
ok: ['anotherhost'] => {
    "var": {
        "hostvars['localhost']['foo']": {
            "changed": true,
            "cmd": [
                "/bin/echo",
                "this is a test"
            ],
            "delta": "0:00:00.005950",
            "end": "2015-11-24 20:54:04.319147",
            "invocation": {
                "module_args": "/bin/echo \"this is a test\"",
                "module_complex_args": {},
                "module_name": "command"
            },
            "rc": 0,
            "start": "2015-11-24 20:54:04.313197",
            "stderr": "",
            "stdout": "this is a test",
            "stdout_lines": [
                "this is a test"
            ],
            "warnings": []
        }
    }
}

Итак, в двух словах вы хотите изменить ссылки на переменные в main playbook для ссылки на переменные localhost следующим образом:

{{ hostvars['localhost']['app_git_sha1'] }}

29
задан Chris Klepeis 26 August 2009 в 00:19
поделиться

6 ответов

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

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

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

57
ответ дан John Millikin 18 August 2018 в 19:16
поделиться
  • 1
    Мы также пробовали это, но он не работал, к сожалению – Chris Klepeis 25 August 2009 в 20:53
  • 2
    @Chris: можете ли вы опубликовать пример того, как вы используете strcmp()? В противном случае мы не будем знать, как это «не работает». – John Millikin 25 August 2009 в 20:56
  • 3
    Вы уверены, что не сделали, если (strcmp (var1, & quot; dev & quot;))? Легкая ловушка, чтобы попасть в strcmp ... – Martin B 25 August 2009 в 20:59
  • 4
    @chris дополнительно, var1 null-terminated? (т. е. является ли пример кода 100% точным, или вы используете строки с нулевыми терминами для быстрого объяснения) – San Jacinto 25 August 2009 в 21:11
  • 5
    Я смотрю на этот проект, у меня нет c ++ на моей рабочей системе, чтобы проверить, чтобы я проверил, когда вернусь домой и опубликую то, что узнаю. – Chris Klepeis 25 August 2009 в 21:34

ваше мышление об этой программе ниже

#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

, когда вы должны думать о вводе чего-то в массив & amp; затем используйте функции 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
ответ дан 101dolmations 18 August 2018 в 19:16
поделиться

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

// 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 (он написан сам)

0
ответ дан AraneaSerket6848 18 August 2018 в 19:16
поделиться

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

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

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

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

Для этого нужно использовать функцию 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
}

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

16
ответ дан jalf 18 August 2018 в 19:16
поделиться
  • 1
    Это объяснение rock, и также сообщает std :: string! Я прочитал это в первый раз :) – xtofl 26 August 2009 в 06:08
  • 2
    Увлекательная ловушка с этим является сгибанием строк, при тестировании сборки релиза с "foo" == & quot; foo & quot; вероятно, будет правдой, поскольку они станут указателями на одну и ту же строку, но отладка имеет отключение строки, и она не удастся – paulm 25 August 2014 в 12:20

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

if ( 0 == strcmp(var1, "dev")) {
  ..
}
1
ответ дан JaredPar 18 August 2018 в 19:16
поделиться
  • 1
    Оооо. Я ненавижу поставить 0 слева (личное мнение очевидно). Я думаю, что он более интуитивный справа, и поскольку вы тестируете результат против функции, нет шансов на назначение. – Martin York 25 August 2009 в 21:54
  • 2
    Я называю это «кодирование Йоды». (назад - выражение, хммм?). Я бы предпочел использовать параметры компиляции, чтобы поймать случайные задания. – Fred Larson 25 August 2009 в 22:12
  • 3
    @Fred согласен с тобой, я этого не делаю. :) – JaredPar 25 August 2009 в 22:13
  • 4
    Максимальный уровень предупреждения компилятора, предупреждения как ошибки, yoda не требуется :) – paulm 25 August 2014 в 12:22

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

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

0
ответ дан sepp2k 18 August 2018 в 19:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: