C++ 使用GetDlgItemText()强制转换字符串类型,以便在C++;
我对Win32(ANSI)函数中的以下行为感到困惑: (多字节字符集不是UNICODE) 这将在每次调用时向控件追加文本 相反,在调用C++ 使用GetDlgItemText()强制转换字符串类型,以便在C++;,c++,winapi,string,C++,Winapi,String,我对Win32(ANSI)函数中的以下行为感到困惑: (多字节字符集不是UNICODE) 这将在每次调用时向控件追加文本 相反,在调用GetDlgItemText()之后,所有字符串连接都会失败,我假设是因为类型转换 我使用了三个字符串变量使它变得非常明显。如果sBuf受到影响,则不应影响sDisplay (另外,为什么len 1 char小于缓冲区中的长度?) GetDlgItemText()正确返回编辑控件的内容,SetDlgItemText()将正确设置sDisplay中的任何文本,但两者
GetDlgItemText()
之后,所有字符串连接都会失败,我假设是因为类型转换
我使用了三个字符串变量使它变得非常明显。如果sBuf
受到影响,则不应影响sDisplay
(另外,为什么len 1 char小于缓冲区中的长度?)
GetDlgItemText()
正确返回编辑控件的内容,SetDlgItemText()将正确设置sDisplay
中的任何文本,但两者之间的连接不会发生
这是string类的“隐藏特性”吗
添加:
是的,看起来问题是中间的终止。现在我明白了为什么len+1。该函数确保最后一个字符是NUL
使用sBuf.resize(len)代码>将把它切掉,一切都很好
添加:
查尔斯
撇开这个特殊函数奇怪的返回长度不谈,我们来谈谈使用字符串作为缓冲区:
该标准将basic_string::data()的返回值描述为指向数组的指针,该数组的成员等于字符串本身的元素
这正是我们需要的,不是吗
此外,它要求程序不得更改该数组的任何值
据我所知,这将随着所有字节都是连续的保证而改变。我忘了在哪里读过一篇关于这方面的长篇文章,但微软已经实现了它所断言的这一点
我不喜欢使用向量,因为在返回字节之前,字节会被复制两次:一次复制到向量中,另一次复制到字符串中。我还需要实例化一个向量对象和一个字符串对象。这是很大的开销。如果有一些字符串友好的处理向量(或cstring)的方法,而不必求助于旧的C函数或逐个处理字符,我会使用它们。字符串的语法非常友好。std::string上的data()
函数返回一个const char*
。不允许您直接进入它返回的缓冲区,它可能是重复的缓冲区
您可以改为使用std::vector
作为临时缓冲区
E.g. (untested)
std::vector<char> sBuf( len + 1 );
GetDlgItemText( /* ... */, &sBuf[0], len + 1 );
std::string newText( &sBuf[0] );
newText += sText;
编辑:
好的,我刚刚检查了合同中的GetWindowTextLength
和GetDlgItemText
。检查我上面的编辑。两个都将包含一个空终止符的空间,所以您需要将它从字符串的末尾砍下,否则两个字符串的级联将包含一个空终止符,在字符串的中间,而StdLgGITMTEX> <代码>调用只使用字符串的第一部分。
还有一个更复杂的问题是,GetWindowTextLength
不能保证准确,它只能保证返回一个足够大的数字,以便程序创建一个缓冲区来存储结果。这实际上不太可能影响调用代码所拥有的对话框项,但在其他情况下,实际文本可能比返回的长度短。因此,在任何情况下,您都应该在返回的文本中搜索第一个\0
我选择只使用std::string
构造函数,该构造函数接受const char*
,以便它正确地找到第一个\0
该标准将basic_string::data()
的返回值描述为指向数组的指针,该数组的成员等于字符串本身的元素。此外,它要求程序不得更改该数组的任何值。这意味着data()
的返回值可能是也可能不是字符串内部表示形式的副本,即使它不是副本,也不允许对其进行写入。我离win32 api及其字符串噩梦很远,但代码中有些东西可以检查。标准的C++字符串不需要空结束,空可能发生在字符串内的任何地方。我不会评论你正在用你的C风格演员来抛弃恒常性这一事实,这本身就是一个问题,但我会评论你的奇怪效果
最初创建字符串时,为null分配额外空间(并将所有元素初始化为“\0”),然后复制元素。此时,字符串的大小为len+1
,最后一个元素为null。在这之后,您将附加一些其他字符串,得到的是一个在len
位置仍有空字符的字符串。使用data()
(不保证空终止!)或c_str()
检索数据时,返回的缓冲区仍将在len
位置具有空字符。如果传递给一个在null处停止的函数(采用C样式的字符串),那么即使该字符串已完成,该函数也将只处理第一个len
字符,而忽略其余字符
#include <string>
#include <cstdio>
#include <iostream>
int main()
{
const char hi[] = "Hello, ";
const char all[] = "world!";
std::string result;
result.resize( sizeof(hi), 0 );
// simulate GetDlgItemText call
std::copy( hi, hi+sizeof(hi), const_cast<char*>(result.data()) ); // this is what your C-style cast is probably doing
// append
result.append( all );
std::cout << "size: " << result.size() // 14
<< ", contents" << result // "Hello, \0world!" - dump to a file and edit with a binary editor
<< std::endl;
std::printf( "%s\n", result.c_str() ); // "Hello, "
}
#包括
#包括
#包括
int main()
{
const char hi[]=“你好,”;
const char all[]=“世界!”;
std::字符串结果;
result.resize(sizeof(hi),0);
//模拟GetDlgItemText调用
std::copy(hi,hi+sizeof(hi),const_cast(result.data());//这可能就是您的C样式转换所做的
//附加
结果:追加(全部);
std::cout这是而不是一个答案。我在这里添加它只是为了在关于常量的长期讨论中使用格式
这是一个使用const\u cast
可以中断正在运行的应用程序的示例:
#include <iostream>
#include <map>
typedef std::map<int,int> map_type;
void dump( map_type const & m ); // implemented somewhere else for concision
int main() {
map_type m;
m[1] = 10;
m[2] = 20;
m[3] = 30;
map_type::iterator it = m.find(2);
const_cast<int&>(it->first) = 10;
// At this point the order invariant of the container is broken:
dump(); // (1,10),(10,20),(3,30) !!! unordered by key!!!!
// This happens with g++-4.0.1 in MacOSX 10.5
if ( m.find(3) == m.end() ) std::cout << "key 3 not found!!!" << std::endl;
}
#包括
#包括
typedef std::map_
#include <string>
#include <cstdio>
#include <iostream>
int main()
{
const char hi[] = "Hello, ";
const char all[] = "world!";
std::string result;
result.resize( sizeof(hi), 0 );
// simulate GetDlgItemText call
std::copy( hi, hi+sizeof(hi), const_cast<char*>(result.data()) ); // this is what your C-style cast is probably doing
// append
result.append( all );
std::cout << "size: " << result.size() // 14
<< ", contents" << result // "Hello, \0world!" - dump to a file and edit with a binary editor
<< std::endl;
std::printf( "%s\n", result.c_str() ); // "Hello, "
}
#include <iostream>
#include <map>
typedef std::map<int,int> map_type;
void dump( map_type const & m ); // implemented somewhere else for concision
int main() {
map_type m;
m[1] = 10;
m[2] = 20;
m[3] = 30;
map_type::iterator it = m.find(2);
const_cast<int&>(it->first) = 10;
// At this point the order invariant of the container is broken:
dump(); // (1,10),(10,20),(3,30) !!! unordered by key!!!!
// This happens with g++-4.0.1 in MacOSX 10.5
if ( m.find(3) == m.end() ) std::cout << "key 3 not found!!!" << std::endl;
}