Легко узнать размер строки, содержащей нулевой символ

Длинный вопрос для очень простого & Новобранец проблемы, НО все же мне нужно несколько советов.

Фон

Итак, у меня есть двоичный файл, который мне нужно проанализировать. Этот файл начинается с некоторой магической строки, которая содержит нулевой символ (\0). давайте определим как ab\0cd,

Я пишу метод, который возвращает true, если какой-то файл начинается с магической строки.

Попытка 1

#define MAGIC_STRING "ab\0cd"
bool IsMagicFile(const wpath& pathFile)
{
string strData;
if (!ReadFile(pathFile, strData))
return false;

if (strData.size() < 5)
return false;

string strPrefix = strData.substr(0, 5);

if (strcmp(strPrefix.c_str(), MAGIC_STRING) != 0)
return false;

return true;
}

Проблема 1

Что беспокоит меня в приведенном выше коде, так это то, что я «жестко» предполагаю, что размер магической строки 5,

что если завтра волшебная нить изменится? сказать:

#define MAGIC_STRING "abe\0fcd"

макрос строки изменен, и код больше не работает должным образом.

Попытка 2

#define MAGIC_STRING "ab\0cd"
bool IsMagicFile(const wpath& pathFile)
{
string strMagic = MAGIC_STRING;

string strData;
if (!ReadFile(pathFile, strData))
return false;

if (strData.size() < strMagic.size())
return false;

string strPrefix = strData.substr(0, strMagic.size());

if (strcmp(strPrefix.c_str(), MAGIC_STRING) != 0)
return false;

return true;
}

Проблема 2

Якобы избавился от жестко заданной проблемы с размером, НО размер strMagic на самом деле не 5, а 2. строка заканчивается \0

Попытка 3

#define MAGIC_STRING        "ab\0cd"    // CAUTION - MAGIC_STRING & MAGIC_STRING_SIZE must be changes together
#define MAGIC_STRING_SIZE   5           // CAUTION - MAGIC_STRING & MAGIC_STRING_SIZE must be changes together

bool IsMagicFile(const wpath& pathFile)
{
string strData;
if (!ReadFile(pathFile, strData))
return false;

if (strData.size() < MAGIC_STRING_SIZE)
return false;

string strPrefix = strData.substr(0, MAGIC_STRING_SIZE);

if (strcmp(strPrefix.c_str(), MAGIC_STRING) != 0)
return false;

return true;
}

Проблема 3

Это решило первую проблему, но я до сих пор не получил желаемого бесшовного изменения магической строки.

Вопрос

Является ли попытка 3 достаточно хорошей? у вас есть лучший подход?

1

Решение

Вместо использования определения макроса вы можете определить постоянный массив символов. Например

const char MAGIC_STRING[] = "abe\0fcd";

В этом случае количество символов, исключая завершающий ноль, равно

sizeof( MAGIC_STRING ) - 1

Для сравнения необработанных байтов вы можете использовать стандартную функцию C memcmp предоставляя количество сравниваемых байтов, которое равно выражению выше.

Вот демонстрационная программа

#include <iostream>
#include <string>
#include <cstring>
#include <iterator>

const char MAGIC_STRING[] = "abe\0fcd";

int main()
{
std::string s( std::begin( MAGIC_STRING ), std::prev( std::end( MAGIC_STRING ) )  );

if ( memcmp( s.c_str(), MAGIC_STRING, sizeof( MAGIC_STRING ) - 1 ) == 0 )
{
std::cout << "The string starts with the MAGIC_STRING" << std::endl;
}

return 0;
}

Его вывод

The string starts with the MAGIC_STRING
2

Другие решения

Если вы точно знаете, что ваша волшебная строка будет содержать \0 тогда вы могли бы написать свой собственный size(string str)функция, которая будет возвращать правильную длину, продолжая считать после первого \0,

Если неизвестно, сколько \0s есть в волшебной строке, я бы посоветовал вам пойти с попыткой 3.

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

0

Лично я бы не использовал MACROS. Также я бы не использовал функции, предназначенные для строк с нулевым символом в конце, таких как станд :: зЬгстр. Вы можете проверить, содержит ли начало строки определенную последовательность символов, используя станд :: равны от стандарта <algorithm> библиотека:

// create a character array to preserve compile time size
// but remember string literals add a null-terminator extra character
const char magic_string[] = "ab\0cd";

bool IsMagicFile(const wpath& pathFile)
{
string strData;
if (!ReadFile(pathFile, strData))
return false;

// -1 to avoid null terminator from magic_string character array
return std::equal(magic_string, magic_string + sizeof(magic_string) - 1,
strData.begin());
}
0
По вопросам рекламы [email protected]