【发布时间】:2009-02-02 21:28:58
【问题描述】:
我在一个 C++ 非托管项目中工作。
我需要知道如何获取像“一些要加密的数据”这样的字符串并获得一个字节[] 数组,我将使用它作为 Encrypt 的源。
在 C# 中我会这样做
for (int i = 0; i < text.Length; i++)
buffer[i] = (byte)text[i];
我需要知道的是如何使用非托管 C++ 做同样的事情。
谢谢!
【问题讨论】:
我在一个 C++ 非托管项目中工作。
我需要知道如何获取像“一些要加密的数据”这样的字符串并获得一个字节[] 数组,我将使用它作为 Encrypt 的源。
在 C# 中我会这样做
for (int i = 0; i < text.Length; i++)
buffer[i] = (byte)text[i];
我需要知道的是如何使用非托管 C++ 做同样的事情。
谢谢!
【问题讨论】:
如果你只需要只读权限,那么c_str() 就可以了:
char const *c = myString.c_str();
如果您需要读/写访问权限,则可以将字符串复制到向量中。向量为您管理动态内存。那么你不必搞乱分配/解除分配:
std::vector<char> bytes(myString.begin(), myString.end());
bytes.push_back('\0');
char *c = &bytes[0];
【讨论】:
std::string::data 似乎是足够且最有效的。如果您想使用非常量内存来操作(加密很奇怪),您可以使用 memcpy 将数据复制到缓冲区:
unsigned char buffer[mystring.length()];
memcpy(buffer, mystring.data(), mystring.length());
STL 粉丝会鼓励您改用 std::copy:
std::copy(mystring.begin(), mystring.end(), buffer);
但这确实没有太大的好处。如果您需要空终止,请使用std::string::c_str() 和其他人提供的各种字符串复制技术,但我通常会避免这种情况,只需查询length。特别是对于密码学,您只知道有人会尝试通过将空值插入其中来尝试破解它,并且使用 std::string::data() 会阻止您懒惰地对字符串中的底层位进行假设。
【讨论】:
unsigned char buffer[mystring.length()] 不是标准 C++。一些编译器支持它们,但 Visual Studio 不支持。
通常,加密函数需要
encrypt(const void *ptr, size_t bufferSize);
作为参数。可以直接传递 c_str 和 length:
encrypt(strng.c_str(), strng.length());
这样,额外的空间被分配或浪费。
【讨论】:
如果您想获取 char_t 缓冲区指针,可以从 std::string 使用 c_ptr() 方法。
看起来你只是想将字符串的字符复制到一个新的缓冲区中。我会简单地使用std::string::copy 函数:
length = str.copy( buffer, str.size() );
【讨论】:
如果你只是需要读取数据。
encrypt(str.data(),str.size());
如果您需要数据的读/写副本,请将其放入向量中。 (不要动态分配空间,这是向量的工作)。
std::vector<byte> source(str.begin(),str.end());
encrypt(&source[0],source.size());
当然我们都假设字节是一个字符!!!
【讨论】:
在C++17 及以后你可以使用std::byte 来表示实际的字节数据。我会推荐这样的东西:
std::vector<std::byte> to_bytes(std::string const& s)
{
std::vector<std::byte> bytes;
bytes.reserve(std::size(s));
std::transform(std::begin(s), std::end(s), std::back_inserter(bytes), [](char c){
return std::byte(c);
});
return bytes;
}
【讨论】:
std::byte 并没有出现在 C++11 中,而是出现在 C++17 中。见en.cppreference.com/w/cpp/types/byte
如果这只是普通的 C,那么:
strcpy(buffer, text.c_str());
假设缓冲区已分配并且足够大以容纳“文本”的内容,这是您原始代码中的假设。
如果 encrypt() 采用 'const char *' 那么你可以使用
encrypt(text.c_str())
而且你不需要复制字符串。
【讨论】:
你可以使用range-based for 循环,看起来像这样:
std::vector<std::byte> getByteArray(const string& str)
{
std::vector<std::byte> buffer;
for (char str_char : str)
buffer.push_back(std::byte(str_char));
return buffer;
}
【讨论】:
我认为您不想使用那里的 c# 代码。他们提供 System.Text.Encoding.ASCII(也是 UTF-*)
string str = "some text;
byte[] bytes = System.Text.Encoding.ASCII.GetBytes(str);
您的问题源于忽略 c# 中的编码而不是您的 c++ 代码
【讨论】: