如何检查 LPTSTR 字符串的内容?
Posted
技术标签:
【中文标题】如何检查 LPTSTR 字符串的内容?【英文标题】:How to check the contents of a LPTSTR string? 【发布时间】:2014-09-02 08:05:38 【问题描述】:我试图了解为什么在这段代码的执行过程中会出现分段错误 (SIGSEGV)。这个错误是在测试while
指令中指定的条件时出现的,但不是在第一次迭代时出现,而是在第二次迭代时出现。
LPTSTR arrayStr[STR_COUNT];
LPTSTR inputStr;
LPTSTR str;
// calls a function from external library
// in order to set the inputStr string
set_input_str(param1, (char*)&inputStr, param3);
str = inputStr;
while( *str != '\0' )
if( debug )
printf("String[%d]: %s\n", i, (char*)str);
arrayStr[i] = str;
str = str + strlen((char*)str) + 1;
i++;
看了this answer之后,我在网上做了一些研究,发现this article,所以我尝试修改上面的代码,使用这篇文章中读到的这段代码(见下文)。然而,这个改变并没有解决问题。
for (LPTSTR pszz = pszzStart; *pszz; pszz += lstrlen(pszz) + 1)
... do something with pszz ...
正如this answer 中所假设的那样,代码似乎需要双空终止的字符串数组。因此,我想知道如何检查inputStr
字符串的内容,以检查它是否实际上只包含一个空终止符。
注意:printf
指令打印的字符串中的字符数是第一次迭代时lstrlen(str)
函数调用返回值的两倍。
【问题讨论】:
你认为str = str + strlen(str) + 1;
会做什么?
好吧,最后的+ 1
越界了,但是不知道这段代码的目的是什么。
循环的编写可能需要一组连续的字符串,而不是单个字符串。
我认为,如果您向我们展示已注释掉的 其他说明,可能会有所帮助。这可能会证实(或以其他方式)@Harry 和我的预感。
@DavidHeffernan:其他说明不变str
。
【参考方案1】:
好的,既然您已经包含了其余代码,很明显它确实是为了解析一组连续的字符串。问题是您混合了窄字符串和宽字符串类型。修复它所需要做的就是更改变量定义(并删除强制转换):
char *arrayStr[STR_COUNT];
char *inputStr;
char *str;
// calls a function from external library
// in order to set the inputStr string
set_input_str(param1, &inputStr, param3);
str = inputStr;
while( *str != '\0' )
if( debug )
printf("String[%d]: %s\n", i, str);
arrayStr[i] = str;
str = str + strlen(str) + 1;
i++;
具体来说,问题发生在这一行:
while( *str != '\0' )
由于您没有将 str
转换为 char *
,因此比较寻找的是宽 nul 而不是窄 nul。
【讨论】:
+1 我的猜测是原始代码无缘无故地使用了 TCHAR,为 ANSI 编译,并使用 strlen 等。然后提问者出现,用 Unicode 编译代码,发现它不会编译,抛弃错误,并为对编译器撒谎付出代价。【参考方案2】:str = str + strlen(str) + 1;
你出界了,换成
str = str + 1;
或者简单地说:
str++;
【讨论】:
问题是我不知道这段代码的目标是什么:似乎每次迭代我们都想移动到字符串的末尾,但我不明白原因。 .. 这叫做指针算法,看看C-FAQ的Chapter 10.2 Pointers and Arrays; Pointer Arithmetic,最后你有一个类似strcpy
实现的例子。
@Alter 其实根本不是这样的【参考方案3】:
当然你在使用TSTR
和strlen
时不一致,后者假设TCHAR = char
无论如何,strlen
返回字符串的长度,即它包含的字符数,不包括 nul 字符。
你的算术加一,但你知道在分配缓冲区时必须将字符串的长度加一。
但是,您从位置 0 开始并添加长度,这意味着您位于位置 len
,这是字符串的长度。现在字符串从偏移量0
运行到偏移量len - 1
并且偏移量len
包含空字符。偏移量len + 1
超出范围。
如果有额外的填充,有时您可能会逃脱阅读它,但这是未定义的行为,在这里您遇到了段错误。
【讨论】:
【参考方案4】:在我看来,这就像需要双空终止字符串数组的代码。我怀疑您正在传递一个以空字符结尾的字符串。
所以你正在使用这样的东西:
const char* inputStr = "blah";
但代码需要两个空终止符。如:
const char* inputStr = "blah\0";
或者可能是具有多个字符串的输入值:
const char* inputStr = "foo\0bar\0";
请注意,这最后两个字符串确实是双空终止的。虽然在字符串末尾只显式写入了一个空终止符,但编译器隐式添加了另一个。
您的问题编辑在工作中引发了新的扳手?演员表
strlen((char*)str)
非常可疑。如果你需要施法,那么施法一定是错误的。有人想知道LPTSTR
为您扩展了什么。大概它扩展为wchar_t*
,因为您添加了该转换以使代码编译。如果是这样,那么演员阵容就没有好处。你在对编译器撒谎(str
不是 char*
),对编译器撒谎永远不会结束。
【讨论】:
那么,如何单独打印LPTSTR
中的每个字符?
如何在 LPTSTR 的末尾添加一个额外的空终止符?
如何打印每个字符?这听起来像是一个完全不同的问题。至于下一条评论,我展示了如何在答案中加倍 null 终止。【参考方案5】:
Alter 的回答已经给出了分段错误的原因。但是,我想补充一点,解析 C 风格字符串的常用风格更优雅,更简洁
while (char ch = *str++)
// other instructions
// ...
ch
的范围仅在循环体内。
旁白:将问题标记为C
或C++
,但不能同时标记,它们是不同的语言。
【讨论】:
以上是关于如何检查 LPTSTR 字符串的内容?的主要内容,如果未能解决你的问题,请参考以下文章
ANSI与Unicode编码,TCHAR | LPSTR | LPCSTR | LPWSTR | LPCWSTR | LPTSTR | LPCTSTR 的含义