TIniFile->ReadString возвращает null вместо

У меня есть этот фрагмент кода, который отказывается возвращать «DefaultVal», когда «CurrentFile» пуст:

void __fastcall TForm1::Button2Click(TObject *Sender)
{
      TIniFile *pIni = new TIniFile("c:\\Test\\MyIni.ini");
      try
         {
         int i = pIni->ReadInteger (L"x", L"Level",  0);  //This is ok

         UnicodeString s = pIni->ReadString ("x", "CurrentFile",  "DefaultVal");   //Debugger shows s = NULL
         }
      __finally
         {
         pIni->Free();
         }
}
//---------------------------------------------------------------------------

Это INI-файл:

[x]
CurrentFile=

Если я редактирую файл INI на CurrentFile= "something", тогда код работает, и s правильно содержит «что-то».

Что я делаю не так?

С++ Builder Токио 10.3.2


person Z80    schedule 01.10.2018    source источник
comment
о... Я думаю, что строка unicode, установленная в NULL, означает, что она пуста????   -  person Z80    schedule 01.10.2018
comment
Да, в Delphi пустая строка (UnicodeString, AnsiString) возвращается как NULL (ноль). Не уверен, как это работает в C++Builder. Но поскольку вы вызываете функцию Delphi, вы можете ожидать возврата NULL (nil).   -  person Rudy Velthuis    schedule 01.10.2018
comment
@RudyVelthuis = На самом деле, в Delphi отладчик покажет вам пустую строку, а в c++ отладчик покажет вам NULL для пустой строки.   -  person Z80    schedule 01.10.2018
comment
Я думаю, что это больше похоже на { NULL }, то есть на структуру с NULL в качестве единственного элемента. Насколько я знаю, в C++Builder эти строки являются структурами или классами, а в Delphi — встроенными типами. Структуры или классы C++Builder имитируют эти встроенные типы.   -  person Rudy Velthuis    schedule 01.10.2018
comment
Да, в C++ (Ansi|Wide|Unicode)String — это классы с одним членом Data, то есть NULL, когда строка пуста.   -  person Remy Lebeau    schedule 02.10.2018


Ответы (2)


TIniFile::ReadString() возвращает значение Default только в том случае, если указанное значение Ident вообще не существует. Если значение Ident существует, но является пустым, или при его чтении возникает ошибка, вместо этого возвращается пустая строка. Если вы хотите, чтобы ваше значение Default использовалось, если значение Ident пусто, вам придется проверить это вручную, например:

String s = pIni->ReadString (_D("x"), _D("CurrentFile"), _D("")); 
if (s.IsEmpty()) // or: if (s == _D(""))
    s = _D("DefaultVal");

Обратите внимание, что TIniFile::ReadInteger() возвращает значение Default, если значение Ident не может быть преобразовано в int по любой причине, будь то из-за того, что оно не существует, пусто, не может быть прочитано, не в числовом шестнадцатеричном формате и т. д.

person Remy Lebeau    schedule 02.10.2018

Мой вопрос глупый, но я не буду его удалять. Пусть другие тоже учатся на этом. Это был мой мозг Delphi, пытающийся охватить странные концепции C++ :)

Строки в стиле Delphi (AnsiString, RawByteString, UnicodeString и WideString) на самом деле не являются NULL в C++Builder, ДАЖЕ хотя это то, что показывает отладчик. Другими словами, всякий раз, когда ваш отладчик показывает NULL для такой строки, думайте о ней как о "пустой строке".

Следует отметить также, что

if (s == NULL)

не возвращает то, что вы ожидаете. Вместо этого используйте s.IsEmpty().

Вот полный ответ:

XE6 Как проверить, является ли UnicodeString нулевым?< /а>

person Z80    schedule 01.10.2018
comment
Причина, по которой if (s == NULL) не работает, заключается в том, что NULL определяется как 0, поэтому if (s == 0) преобразует 0 в строку, прежде чем сравнивать ее, так что вместо этого вы действительно делаете if (s == "0") - person Remy Lebeau; 02.10.2018