将C++与MFC一起使用.来自C#背景我通常只使用字符串表示所有字符串.我将它们用于类成员,方法参数和方法返回值.
现在在C++中我有std :: string,CString,char*,LPCTSTR等等.当我设计我的数据成员,方法参数和方法返回值时,我应该使用哪种类型?易用性很重要,CString似乎提供了这一点,但我的直觉是针对便携式标准,尽管我的优先级列表(现在)的可移植性相当低.另外,我不喜欢创建字符串缓冲区并将它们传递给方法和函数的c语义.
我认为从编码的角度来看,CStrings可能具有优势.但是,总体而言,"高代码质量"的方式是什么?
编辑:
我特别关注代码中的接口点(即方法参数和返回值).例如:
Shape::SetCaption(const char *caption) {...}
Shape::SetCaption(CString caption) {...}
Shape::SetCaption(std::string caption) {...}
Shape::SetCaption(std::wstring caption) {...}
Run Code Online (Sandbox Code Playgroud) 它是有效的创建一个迭代end(str)+1的std::string?
如果不是,为什么不呢?
这个问题是限制在C++ 11以后,因为在预C++ 11中的数据已经存储在连续块中的任何但是罕见POC玩具的实现,该数据没有具有要被存储的方式.
而且我认为这可能会产生重大影响.
std::string我推测的任何其他标准容器之间的显着差异在于它总是包含一个元素size,而不是它的零终止符,以满足要求.c_str().
21.4.7.1 basic_string访问器[string.accessors]
Run Code Online (Sandbox Code Playgroud)const charT* c_str() const noexcept; const charT* data() const noexcept;1返回:一个指针
p,p + i == &operator[](i)用于每个iin[0,size()].
2复杂性:恒定时间.
3要求:程序不得更改存储在字符数组中的任何值.
尽管如此,尽管它应该保证所述表达式是有效的,但为了保持与零终止字符串的一致性和互操作性,如果没有别的话,我发现的唯一一段对此表示怀疑:
21.4.1 basic_string一般要求[string.require]
4对象中的类似char的
basic_string对象应连续存储.也就是说,任何basic_string对象s,身份&*(s.begin() + n) == &*s.begin() + n应持的所有值n这样0 <= n < s.size().
(所有引用均来自C++ 14最终草案(n3936).)
相关: …
所以这里有一个小测试程序:
#include <string>
#include <iostream>
#include <memory>
#include <vector>
class Test
{
public:
Test(const std::vector<int>& a_, const std::string& b_)
: a(std::move(a_)),
b(std::move(b_)),
vBufAddr(reinterpret_cast<long long>(a.data())),
sBufAddr(reinterpret_cast<long long>(b.data()))
{}
Test(Test&& mv)
: a(std::move(mv.a)),
b(std::move(mv.b)),
vBufAddr(reinterpret_cast<long long>(a.data())),
sBufAddr(reinterpret_cast<long long>(b.data()))
{}
bool operator==(const Test& cmp)
{
if (vBufAddr != cmp.vBufAddr) {
std::cout << "Vector buffers differ: " << std::endl
<< "Ours: " << std::hex << vBufAddr << std::endl
<< "Theirs: " << cmp.vBufAddr << std::endl;
return false;
}
if (sBufAddr != cmp.sBufAddr) {
std::cout …Run Code Online (Sandbox Code Playgroud) 我需要一个如何使用Crypto ++从std :: string生成SHA256哈希并输出std :: string的示例.我似乎无法弄明白.我尝试的一切都给了我无效的输出.
这是interjay回答后的新代码:
string SHA256(string data)
{
byte const* pbData = (byte*) data.data();
unsigned int nDataLen = data.size();
byte abDigest[CryptoPP::SHA256::DIGESTSIZE];
CryptoPP::SHA256().CalculateDigest(abDigest, pbData, nDataLen);
return string((char*)abDigest);
}
Run Code Online (Sandbox Code Playgroud)
SHA256的输出("A"); 是

如何将其转换为可读格式?
感谢interjay的回答,我能够生成最终的哈希值.
互联网上有几篇帖子暗示你应该使用std::vector<unsigned char>或类似的二进制数据.
但我更倾向于使用std::basic_string变体,因为它提供了许多方便的字符串操作功能.和AFAIK一样,自C++ 11以来,该标准保证了每个已知的C++ 03实现已经完成的工作:std::basic_string将其内容连续存储在内存中.
乍一看,std::basic_string<unsigned char>可能是一个不错的选择.
std::basic_string<unsigned char>但是,我不想使用,因为几乎所有操作系统函数都只接受char*,因此需要进行显式转换.此外,字符串文字是const char*,所以const unsigned char*每次我将字符串文字分配给我的二进制字符串时,我都需要显式强制转换,我也想避免.此外,用于读取和写入文件或网络缓冲区的函数同样接受char*和const char*指针.
这离开了std::string,这基本上是一个typedef std::basic_string<char>.
使用std::string二进制数据的唯一潜在剩余问题(我可以看到)是std::string使用char(可以签名).
char,signed char和,unsigned char是三种不同的类型,char可以是未签名或签名.
因此,当11111111b从std::string:operator[]char 返回实际字节值,并且您想要检查其值时,其值可以是255(如果char是无符号的),也可能是"负面的"(如果char已签名,则取决于您的数字表示).
类似地,如果要将实际字节值显式附加11111111b到a std::string,则只需附加(char) (255)可能是实现定义的(甚至引发信号),如果char已签名且intto char会话导致溢出. …
在下面的代码中
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a,c="!";
cin>>a;
int l=a.size();
for(int i=0;i<l;i++)
{
c=c+"#"+a[i];
}
cout<<c;
}
Run Code Online (Sandbox Code Playgroud)
如果我替换c=c+"#"+a[i]为c+="#"+a[i]我会得到意外的输出。第二种情况下的输出是 !boxboxboxbox 与https://www.onlinegdb.com/上的输入无关。在“dev c++”上,输出是 -
但是 a += b 等价于 a = a + b 。那么造成输出差异的原因是什么呢?
我正在使用一个用C++实现的开源UNIX工具,我需要更改一些代码才能让它做我想做的事情.我想做出尽可能小的改变,希望上传接受我的补丁.可以在标准C++中实现并且不创建更多外部依赖性的解决方案是首选.
这是我的问题.我有一个C++类 - 我们称之为"A" - 目前使用fprintf()将其格式严格的数据结构打印到文件指针.在其print函数中,它还递归调用几个成员类的相同定义的打印函数("B"是一个例子).还有另一个C类,它有一个成员std :: string"foo",需要设置为A实例的print()结果.把它想象成A的to_str()成员函数.
在伪代码中:
class A {
public:
...
void print(FILE* f);
B b;
...
};
...
void A::print(FILE *f)
{
std::string s = "stuff";
fprintf(f, "some %s", s);
b.print(f);
}
class C {
...
std::string foo;
bool set_foo(std::str);
...
}
...
A a = new A();
C c = new C();
...
// wish i knew how to write A's to_str()
c.set_foo(a.to_str());
Run Code Online (Sandbox Code Playgroud)
我应该提到C是相当稳定的,但是A和B(以及A的其余部分)处于不稳定的状态,因此所需的代码变化越少越好.还需要保留当前的打印(FILE*F)界面.我已经考虑了几种实现A :: to_str()的方法,每种方法都有优点和缺点:
将对fprintf()的调用更改为sprintf()
尝试在字符串流中捕获a.print()的结果 …
假设我需要调用一个函数foo,该函数std::string从我的代码中的很多地方获取const 引用:
int foo(const std::string&);
..
foo("bar");
..
foo("baz");
Run Code Online (Sandbox Code Playgroud)
使用像这样的字符串文字调用函数将创建临时std::string对象,每次复制文字.
除非我弄错了,否则编译器不会通过为std::string每个文字创建一个可以重复用于后续调用的静态对象来优化它.我知道g ++有高级字符串池机制,但我不认为它扩展到std::string对象本身.
我自己可以做这个"优化",这使代码的可读性降低:
static std::string bar_string("bar");
foo(bar_string);
..
static std::string baz_string("baz");
foo(baz_string);
Run Code Online (Sandbox Code Playgroud)
使用Callgrind,我可以确认这确实加快了我的程序.
我以为我会尝试为此制作一个宏,但我不知道是否可能.我想要的是:
foo(STATIC_STRING("bar"));
..
foo(STATIC_STRING("baz"));
Run Code Online (Sandbox Code Playgroud)
我尝试使用文字作为模板参数创建模板,但事实证明这是不可能的.由于代码块中的函数定义是不可能的,我完全没有想法.
有没有一种优雅的方式来做到这一点,还是我不得不求助于那种不太可读的解决方案?
我有以下代码:
Tools::Logger.Log(string(GetLastError()), Error);
Run Code Online (Sandbox Code Playgroud)
GetLastError()返回一个DWORD数值,但构造函数std::string不接受a DWORD.
我能做什么?
我在std :: string中有一个unsigned char数组,但我目前的方法是使用reinterpret_cast,我想避免使用它.有更清洁的方法吗?
unsigned char my_txt[] = {
0x52, 0x5f, 0x73, 0x68, 0x7e, 0x29, 0x33, 0x74, 0x74, 0x73, 0x72, 0x55
}
unsigned int my_txt_len = 12;
std::string my_std_string(reinterpret_cast<const char *>(my_txt), my_txt_len);
Run Code Online (Sandbox Code Playgroud)