Не работает условие if после разбиения строки

rene
Offline
Зарегистрирован: 21.01.2014
char* str = "GET file";
str = strtok(str, " ");
Serial.println(str);
if (str == "GET") Serial.println("!");

Не работает условие if после разбиения строки, хотя на указателе str лежит "GET"

NeiroN
NeiroN аватар
Offline
Зарегистрирован: 15.06.2013
char * str = "GET file";
if (strncmp(str,"GET",3) != -1) Serial.println("!");

а вы сравниваете 2 указателя: адрес переменной str с адресом временной переменной  по которому лежит"GET". Адреса то разные всегда будут.

axill
Offline
Зарегистрирован: 05.09.2011

в этом условии (str == "GET") у вас происходит неявное преобразование типов, тип char* преобразуется в int после чего идет сравнение чисел

в языке Си/С++ оператор == применяется только для численных типов. Для строк нужно использовать функции типа strcmp

Datak
Offline
Зарегистрирован: 09.10.2014

axill пишет:

в этом условии (str == "GET") у вас происходит неявное преобразование типов, тип char* преобразуется в int после чего идет сравнение чисел

Строго говоря, не происходит. Указатель на char (по-другому - char*) - вполне стандартный сишный тип, и операции ==, <, > для него определены. И операции сложения/вычитания ( +, - ) тоже, только не со вторым указателем, а с целым числом.

Но по смыслу - да, указатель, физически, это просто адрес в памяти. И в этом случае адреса действительно не равны.

axill пишет:

в языке Си/С++ оператор == применяется только для численных типов.

Опять же, зачем так категорично! :)
Язык  C++  хорош тем, что его можно "на ходу" обучать операторам, которых он ещё не знает.

Тот же тип String, для примера. Для него операция сравнения будет выполняться вполне корректно.











String str = "GET";
if (str == "GET") Serial.println("!");

Правда, опять не проверял, но надеюсь не ошибся.

-------

Upd: Наврал немного. Операция вычитания ( - ) для двух указателей тоже определена.

 
Datak
Offline
Зарегистрирован: 09.10.2014

NeiroN пишет:


char * str = "GET file";
if (strncmp(str,"GET",3) != -1) Serial.println("!");

А попробуйте так - сравнится или нет? :)

char * str = "SET file";
if (strncmp(str,"GET",3) != -1) Serial.println("!");

 

axill
Offline
Зарегистрирован: 05.09.2011

Datak пишет:

Строго говоря, не происходит.

строго говоря происходит. адрес не является примитивным типом, а сводится к двухбайтовому целому

Datak пишет:
Язык  C++  хорош тем, что его можно "на ходу" обучать операторам, которых он ещё не знает.

Тот же тип String, для примера. Для него операция сравнения будет выполняться вполне корректно.

любые слова вырванные из контекста можно оспорить. При чем здесь String? Выше речь исключительно о char* и в коде выше нет перегрузки опрераторов, на которые вы ссылаетесь

Datak
Offline
Зарегистрирован: 09.10.2014

axill пишет:

адрес не является примитивным типом, а сводится к двухбайтовому целому

Ну так и попробуйте, например, какому-нибудь целому присвоить значение указателя.
Или каким-нибудь if-ом сравнить указатель с int-ом.

Думаете, выполнит за вас компилятор такое же неявное преобразование типов?

Цитата:

При чем здесь String? Выше речь исключительно о char*

Речь шла о языке C/C++ - "в языке Си/С++ оператор == применяется только для численных типов" - 
поэтому я и решил уточнить, чтобы не вводить в заблуждение начинающих программистов.
И уж никак не для дого чтоб с кем-то "посраццо". Извините, если что не так.

axill
Offline
Зарегистрирован: 05.09.2011

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

мне стоило указать, что приведенное правило действительно именно для типа char*, тогда наверно не было бы повода спорить) я приводил его именно в контексте, но это видимо не очевидно

Datak
Offline
Зарегистрирован: 09.10.2014

Да говорю же - я тоже спорить особо не собирался.
Так, тянет что-то иногда поумничать - не могу с собой бороться. :)

rene
Offline
Зарегистрирован: 21.01.2014
  char* str = "Get file";
  str = strtok(str, " ");
  Serial.println(str);
  if (str == "Get file") Serial.println("!");

Скажите, а почему тогда отрабатывает данное условие?

rene
Offline
Зарегистрирован: 21.01.2014

Вот что лежит по адресу str после char* str = "Get file";

0 G 71
1 e 101
2 t 116
3   32
4 f 102
5 i 105
6 l 108
7 e 101
8   0

А после str = strtok(str, " ");

0 G 71
1 e 101
2 t 116
3   0
4 f 102
5 i 105
6 l 108
7 e 101
8   0

Т.е. код 32 (пробел) в строке 3 был заменен на 0, указатель остался на строке 0

Тогда фактически мы имеем аналог команды char* str = "Get";

Но, как я писал выше, данный указатель продолжает считать что у него в памяти лежит "Get file"

срабатывание условия if (str == "Get file") Serial.println("!"); тому подтверждение

зы.str = strtok(str, " "); можно было написать наверное просто strtok(str, " ");, результат тот же

rene
Offline
Зарегистрирован: 21.01.2014

За strncmp спасибо, работает

axill
Offline
Зарегистрирован: 05.09.2011

вам больше подходит strcmp, версия с буквой n - strncmp проверяет не полную строку, а указанное число символов. Если проверяется вся строка, то нет смысла указывать число символов

(str == "Get file") возможно срабаывает по тому, что компилятор сделал оптимизацию и на строек 1 и 4 присвоил адрес одной и той же строки, отсюда равенство адресов и срабатывание условия

rene
Offline
Зарегистрирован: 21.01.2014

axill пишет:

вам больше подходит strcmp, версия с буквой n - strncmp проверяет не полную строку, а указанное число символов. Если проверяется вся строка, то нет смысла указывать число символов

(str == "Get file") возможно срабаывает по тому, что компилятор сделал оптимизацию и на строек 1 и 4 присвоил адрес одной и той же строки, отсюда равенство адресов и срабатывание условия

Да, я разобрался с strncmp, единственное не пойму предложенный выше пример

if (strncmp(str,"GET",3) != -1) Serial.println("!");

Почему -1? Сревнение значений 00 и 30 дает результат -3, это же разность кодов в памяти и любое значение отличное от 0 говорит о не совпадении (в моем случае сравнивается 0 и 3, т.е. 48-51=-3). Наверное так правильно:

if (strncmp(str,"GET",3) == 0) Serial.println("!");

А по поводу компиляции (str == "Get file"), приму как есть и не буду больше использовать. Спасибо

sva1509
Offline
Зарегистрирован: 07.12.2012

Я так понима, вы хотите чего то там парсить. Попробуйте так:

char *keys[]={"GET","POST","HTTP","RECV","\0"}; //ключевые слова, последняя содержит первым символом 0

int strKeys(char *str)  // str строка образец, где мы ищем ключевое слово
{
int i=0;

       while(keys[i][0]) {
               if (!strcmp(str,keys[i])) return(i); //если строки совпали, то выходим из функции с номером совпавшего ключа
       }
       return(-1);  // если цикл закончился то выходим с -1 это значит ни одно ключевое слово не совпало
}

switch(strKeys(mister)) {
      case 0: ........ break; // здесь обрабатываем GET
      case 1: ........ break; // здесь обрабатываем POST
      case 2: ........ break; // здесь обрабатываем HTTP
      case 3: ........ break; // здесь обрабатываем RECV
      case -1: ......... break; //// здесь вызов если ниодно не совпало
}

 

rene
Offline
Зарегистрирован: 21.01.2014

У вас тут i++ наверное в цикле должно быть, но суть понятна. Пример хороший, возмем на вооружение. Спасибо

sva1509
Offline
Зарегистрирован: 07.12.2012

Да писал на скорую руку, в строке 9 должно быть i++