C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
AnsiSting и Null
VovaN
Отправлено: 30.05.2005, 10:47


Дежурный стрелочник

Группа: Участник
Сообщений: 72



Как определить, что переменная типа AnsiSting равна Null а не пустой строке?
Guest
Отправлено: 30.05.2005, 11:00


Не зарегистрирован







Так и проверяйте:


CODE

AnsiString s = NULL;
if( s == NULL ) ...


CODE

Запустите пример и посмотрите что он выдаст в каждом случае:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   AnsiString s1 = "dsfdsf";
   AnsiString s2 = "";
   AnsiString s3 = NULL;

   if(s1 == "") ShowMessage("s1 == \"\" ");
   if(s1 == NULL)  ShowMessage("s1 == NULL ");
   if(s1 != "") ShowMessage("s1 != \"\" ");

   if(s2 == "") ShowMessage("s2 == \"\" ");
   if(s2 == NULL)  ShowMessage("s2 == NULL ");
   if(s2 != "") ShowMessage("s2 != \"\" ");

   if(s3 == "") ShowMessage("s3 == \"\" ");
   if(s3 == NULL)  ShowMessage("s3 == NULL ");
   if(s3 != "") ShowMessage("s3 != \"\" ");
}
VovaN
Отправлено: 30.05.2005, 11:07


Дежурный стрелочник

Группа: Участник
Сообщений: 72



Я пишу
CODE

if (previous_str==NULL)
{}
else
 {
}

При этом watch list показывает, что previous_str:{NULL}
но всегда идет ветвление на else.

Отредактировано VovaN — 30/05/2005, 11:08
Gedeon
Отправлено: 30.05.2005, 11:28


Ветеран

Группа: Модератор
Сообщений: 1742



Вот так попробуйте
CODE

if(str.data()==NULL);
olegenty
Отправлено: 30.05.2005, 11:44


Ветеран

Группа: Модератор
Сообщений: 2412



а я делаю так:
CODE

if (str.Trim() == "")
{
   ...
} else
{
   ...
}


правда, такая проверка более общая: и на пустые строки, и на строки только из переносов кареток, пробелов и табуляции (т.е. — обобщённые пробелы), ну и на NULL, до кучи
VovaN
Отправлено: 30.05.2005, 12:46


Дежурный стрелочник

Группа: Участник
Сообщений: 72



В том то и проблемма, что надо отличать, где строка Null, а где "".
А все эти методы это не различают.
Gedeon
Отправлено: 30.05.2005, 13:37


Ветеран

Группа: Модератор
Сообщений: 1742



Тот способ, который я привел правильно работает, создайте консольное вслное приложение и скопируйте туда следующий код, посмотрите на результат
CODE

//---------------------------------------------------------------------------

#include <vcl.h>
#include <stdio>
#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused
int main(int argc, char* argv[])
{
AnsiString tstNULL, tstNOTNULL;

tstNOTNULL = NULL;
if(tstNULL.data()==NULL)
{
printf("%s\n",tstNULL.data());
printf("AnsiString IS NULL\n");
      printf("%s\n",tstNOTNULL.data());
printf("AnsiString IS NOT NULL\n");
}
else{
      printf("tstNULL IS NOT NULL\n");
}
system("PAUSE");
   return 0;
}
//---------------------------------------------------------------------------


Отредактировано Gedeon — 30/05/2005, 13:38
Gedeon
Отправлено: 30.05.2005, 14:15


Ветеран

Группа: Модератор
Сообщений: 1742



Я тут еще маленько покопался и вот что получается
AnsiString.data() вернет NULL если строка просто пустая, т.е. если она будет = "" это уже будет NULL, чем собственно она и отличается от c_str(). Т.е. когда Вы пишите
AnsiString tst = NULL; это то же самое, что написать tst = 0; или tst = "0"; соответственно и проверять можно
CODE

if(tst=="0")
   {
       printf("IF Work\n");
   }
** avtoritet
Отправлено: 30.05.2005, 15:07


Не зарегистрирован







Солидарен с гедеоном.
Я думаю так:
NULL — константа, скрывающая за собой 0;
IsEmpty вернет труе, если str == "";
String str;// тоже что String str ="";
if(str.IsEmpty)
ShowMessage("Empty");
olegenty
Отправлено: 30.05.2005, 15:45


Ветеран

Группа: Модератор
Сообщений: 2412



ну, если что, то писать можно и
CODE

AnsiString as = (char*)NULL;

тут "0" и пахнуть не будет, поскольку лупень BCB просто NULL считает за int

это раз. и, в цикле так делать нельзя — это 2. сто раз обсуждалось на xportal.
найдите n отличий:
CODE

AnsiString((char*)NULL);


разница в том, что в первом случае конструктор вызывается 2 раза: непосредственно для экземпляра правой части присваивания, потом конструктор копирования, потом деструктор для экземпляра правой части, а во втором всего один раз для экземпляра слева, и всё.

поиграл с функцией IsEmpty() — она идиотка. или, нужна ещё одна функция — IsNull(), которой нет.

IsEmpty идиотка, потому что для неё и (char*)NULL, и "" — означает Empty, в то время как я, например, "" — не считаю Empty, а считаю пустой строкой.
olegenty
Отправлено: 30.05.2005, 15:54


Ветеран

Группа: Модератор
Сообщений: 2412



фу, глупость получилась: "Empty" и есть "Пустая". я имел в виду, что для меня (особенно как следствие работы с БД), пустая строка и NULL далеко не эквивалентны. а вот AnsiString наивно полагает, что эквивалентны.
** avtoritet
Отправлено: 30.05.2005, 16:16


Не зарегистрирован







Тут рыть можно до посинения!
String str; string str = "";- это эквивалентно? Я думаю да!
Насчет пустой строки и нул полностью с тобой согласен.
Насчет БСБ и НУЛ думаю всеже считает за Variant. Так как:
String str = "0";
if(str == NULL)
ShowMessage("0 — NULL");
А вообще поступать можно всяко, в зависимости от задачи. Хотелось бы знать, а какую задачю хотел решить влад?

Admin
Отправлено: 30.05.2005, 17:59


Владимир

Группа: Администратор
Сообщений: 1190



Так чем вам не нравиться прямой вариант,
о котором я уже писал (под Guest): ?????????????????

if(s == NULL) ...
все ведь работает в нижеприведенном примере !?

Наверное где то не в том месте стоит else {}
вот такие проблемы и возникают !


CODE

   AnsiString s3 = NULL;


  if(s3 == NULL)  {
                 ShowMessage("s3 == NULL ");
                     }
             else {
                 ShowMessage("s3 != NULL "); // сюда не попадете если NULL
                     }


проверьте этот код — он абсолютно корректо работает
и различает NULL и не NULL и ""
VovaN
Отправлено: 30.05.2005, 19:20


Дежурный стрелочник

Группа: Участник
Сообщений: 72



Да, я не спорю, что если писать
AnsiString s=Null, то оно конечно работает.
Но вот если писать просто
AnsiString s;
AnsiString s1="";
то отличить нельзя.
Проблемма именно в этом.

Guest
Отправлено: 30.05.2005, 21:45


Не зарегистрирован







Так и пишите при инициализации переменной s:
AnsiString s = NULL; вот и будете отличать от ""
dvv
Отправлено: 30.05.2005, 23:21


Дежурный стрелочник

Группа: Участник
Сообщений: 43



QUOTE (VovaN @ 30/05/2005, 19:20)
Да, я не спорю, что если писать
AnsiString s=Null, то оно конечно работает.
Но вот если писать просто
AnsiString s;
AnsiString s1="";
то отличить нельзя.
Проблемма именно в этом.

Когда мы пишем: AnsiString s; то s инициализируется в runtime посредствам конструктора AnsiString(), который устанавливает пустую строку.

Когда мы пишем: AnsiString s=""; то s инициализируется во время компиляции так же пустой строкой.
Нельзя отличить пустую строку от точно такой же пустой строки. Оба объекта в памяти занимают 4 байта, у обоих все байты равны '\0' и в памямяти адреса могут находится рядом. Ну кто оличит корейца от корейца?

А вот когда мы пишем AnsiString s=NULL; то s инициализируется во время компиляции значением NULL. Ведь NULL это не строка, NULL это то чего нет. Вот его то и можно отличать от первых двух случаев.

Как отличать — уже описано выше.

Отредактировано dvv — 30/05/2005, 23:34

Вернуться в Вопросы программирования в C++Builder