Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用GetDlgItemText()强制转换字符串类型,以便在C++;_C++_Winapi_String - Fatal编程技术网

C++ 使用GetDlgItemText()强制转换字符串类型,以便在C++;

C++ 使用GetDlgItemText()强制转换字符串类型,以便在C++;,c++,winapi,string,C++,Winapi,String,我对Win32(ANSI)函数中的以下行为感到困惑: (多字节字符集不是UNICODE) 这将在每次调用时向控件追加文本 相反,在调用GetDlgItemText()之后,所有字符串连接都会失败,我假设是因为类型转换 我使用了三个字符串变量使它变得非常明显。如果sBuf受到影响,则不应影响sDisplay (另外,为什么len 1 char小于缓冲区中的长度?) GetDlgItemText()正确返回编辑控件的内容,SetDlgItemText()将正确设置sDisplay中的任何文本,但两者

我对Win32(ANSI)函数中的以下行为感到困惑: (多字节字符集不是UNICODE)

这将在每次调用时向控件追加文本

相反,在调用
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;
}