2012-02-25 137 views
0

我需要strncpy()(有效)从一个(编辑:MFC)CString对象到一个C字符串变量。众所周知,strncpy()有时会失败(取决于源长** EDIT和调用中指定的长度)以正确终止dest C字符串。为了避免这种罪恶,我想在CString源对象中存储一个NUL char,然后到strcpy()memmove()那个家伙。(编辑:MFC)CString类的对象的内部结构是什么?

这是一个合理的方式去解决它吗?如果是这样,我必须在CString对象内部操作什么?如果没有,那么保证正确终止的目标C字符串的替代方案是什么?

+4

C++标准库中不存在“CString”。你是在谈论'std :: string'还是其他的东西(可能是[MFC]中的CString](http://msdn.microsoft.com/en-us/library/5bzxfsea(v = vs.100).aspx ))? – spencercw 2012-02-25 16:57:04

+0

难道你不能把它转换成'std :: string'吗?例如:'std :: string cppString(yourCString);'。如果您确实需要原始字符串,请从'cppString.c_str()'中获取。只要注意一些Unicode转换将不起作用。 – jweyrich 2012-02-25 16:59:54

+2

几乎在所有情况下,您都应该优先使用std :: string优先于CString。 – 111111 2012-02-25 16:59:58

回答

1

strncpy()只有“失败”为null终止目标字符串时,源字符串是超过您指定的长度限制。您可以通过将其最后一个字符设置为null来确保目标为空终止。例如:

#define DEST_STR_LEN 10 

char dest_str[DEST_STR_LEN + 1]; // +1 for the null 
strncpy(dest_str, src_str, DEST_STR_LEN); 
dest_str[DEST_STR_LEN] = '\0'; 

如果src_str超过DEST_STR_LEN字符长,dest_str将是DEST_STR_LEN字符正确终止字符串。如果src_str比这更短,strncpy()会在dest_str内的某个位置放置一个空终止符,所以最后的空值无关紧要且无害。

+0

是的,当然这就是答案。谢谢! – 2012-02-25 18:12:15

+1

但问题是在CString上!我没有看到这个答案,只是有点相关。 – CapelliC 2012-02-25 18:20:31

+0

@chac,我回答了实际*问题*(不正确使用'strncpy()')而不是*问题*(如何实现对问题的误导性解决方法)。 – Wyzard 2012-04-12 03:03:07

1

CSimpleStringT::GetString给出一个指向空终止字符串的指针。使用这个作为strncpy的源。因为这是C++,所以在与传统API进行交互时应该只使用C风格的字符串。改为使用std::string

1

我希望他们不要从当我用他们改变了:那是许多年前:)

他们用了一个有趣的“伎俩”来处理引用计数和非常快速,高效的自动转换为char * :即指针指向LPCSTR,但保留一些返回字节以保持实现状态。

所以结构可以是使用与旧的Windows API(LPCSTR没有开销)。当时我发现这个想法很有趣!

当然,关键在于分配器的可用性:它们在mallocing/freeing时简单地抵消指针。

我记得有一个缓冲区请求来(例如)修改可用的数据:GetBuffer(0),其次是ReleaseBuffer()。

HTH

1

其中一种替代方法是首先将字符串置零,然后从CString中强制转换或使用memcpy。

1

如果您没有编译启用_UNICODE,那么您可以非常容易地从CString获得const char *。只需将其投射到LPCTSTR

CString myString("stuff"); 
const char *byteString = (LPCTSTR)myString; 

这保证以NULL结尾。

如果你的内置_UNICODE,那么CString是一个UTF-16编码的字符串。你不能直接做任何事情。

如果您确实需要从CString复制数据,那么这非常简单,即使使用C风格的代码。只要确保你分配足够的内存,并复制正确的长度:

CString myString("stuff"); 
char *outString = (char*)malloc(myString.Length() + 1); 
strncpy(outString, (LPCTSTR)myString, myString.Length()); 
1

的CString用NULL所以只要你的文字是正确的结束(没有NULL字符内),然后复制应该是安全的。你可以写:

char szStr[256]; 
strncpy(szStr, (LPCSTR) String, 3); 
szStr[3]='\0'; /// b-cos no null-character is implicitly appended to the end of destination 
如果你店内的CString空somehere

对象,有可能会导致自己更多的问题,内部CString的存储其lenght。

+0

是的,这很好。谢谢! – 2012-02-25 18:22:40

0

另一种替代解决方案宁愿涉及CPU或编译器的支持,因为它更好 - 只需确保在“安全”模式下复制内存时,在每次原子操作之后的任何时间,在末尾添加零时,所以当整个循环失败时,目标字符串仍然会被终止,而无需在复制之前完全清零。 也可以支持快速调零 - 只需标记调零区域的开始和停止,并立即在RAM中清除,这会使事情变得更容易。