如何检查 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】:

当然你在使用TSTRstrlen时不一致,后者假设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 的范围仅在循环体内。

旁白:将问题标记为CC++,但不能同时标记,它们是不同的语言。

【讨论】:

以上是关于如何检查 LPTSTR 字符串的内容?的主要内容,如果未能解决你的问题,请参考以下文章

ANSI与Unicode编码,TCHAR | LPSTR | LPCSTR | LPWSTR | LPCWSTR | LPTSTR | LPCTSTR 的含义

char*”类型的值不能用于初始化“LPTSTR , Const char*”类型的值不能用于初始化“LPCTSTR

LPTSTRLPCSTRLPCTSTRLPSTR

如何检查字符串内容中是不是包含任何 HTML?

win32 api 文件处理

如何在 C# 中检查内容类型/应用程序文本