【问题标题】:String length with embeded null in vb.net在 vb.net 中嵌入空的字符串长度
【发布时间】:2012-11-27 22:22:40
【问题描述】:

我有一个简单的问题:vb.net 如何确定字符串长度并处理字符串的终止?
我知道在C(及其家族)中,空字符是字符串的结尾。在 vb6 中,空字符对字符串的终止没有影响,但在 vb.net 中它似乎有雾!
假设这个代码在 vb6 中:

Private Sub Command1_Click()
Dim Str As String
Str = "Death is a good user," & Chr(0) & " Yes I'm good"
RichTextBox1.Text = Str
RichTextBox1.Text = RichTextBox1.Text & vbNewLine & Len(Str)
End Sub

这段代码运行时会发生以下情况:

没关系。这是C中的类似代码:

#include "stdafx.h"
#include <string.h> 
int main(int argc, char* argv[])
{
    char *p="Death is a good user,\0 Yes I'm good";

    printf("String:%s\nString length:%d\n",p,strlen(p));

    return 0;
}

这就是发生的事情:

根据C 规则也可以,但这里是 vb.net 中的相同代码:

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    Dim str As String = "Death is a good user," & Chr(0) & " Yes I'm good"
    RichTextBox1.Text = str
    RichTextBox1.Text &= vbNewLine & str.Length
End Sub

然后会发生什么:


这似乎不太对!

编辑 1:写入文件似乎是正确的:

编辑 2Marktcarvin 建议,这可能是 UI 的问题,但它没有解释为什么 vb6 显示整个字符串!

编辑 3:我知道 Windows 及其 API、UI、... 是用 C 编写的,所以他们像 C 一样做出反应是正常的,但正如我所展示的上面,他们没有。

【问题讨论】:

标签: vb.net vb6 string-length


【解决方案1】:

在 VB.NET(和 C#)中,字符串的处理方式与 VB6 中的处理方式非常相似,即它们具有明确的长度,而不是基于其中包含的任何特定字符。

就 RichTextBox 而言,它似乎不支持嵌入的空字符。

【讨论】:

  • 我试图用标签显示strmsgbox 和 ... 都一样!我认为这不是 RichTextBox 的问题!
  • 是的,字符串变量没问题。视觉控制在这里很奇怪。如果将字符串写入文件会发生什么?
  • 同意,是 UI 不喜欢它。字符串只是一个字符数组,它不关心这些字符中的内容。
  • 底层 Windows 控件和 API 调用本质上类似于 C。他们将零字节视为字符串的终止。
  • @MarkJ 为什么 vb6 显示整个字符串?那个也是windows control!
【解决方案2】:

底层运行时支持库在您的 sn-ps 中使用了 3 种不同的字符串类型:

  • BSTR,由 VB6 使用。它是所有 ActiveX 控件使用的 COM 自动化类型,可以存储 Unicode 字符串并包括显式长度。因此,BSTR 可以存储嵌入的零。
  • C 字符串,由 C 语言使用。没有存储显式长度,零表示字符串结束。 winapi 基于 C 语言并在其函数中使用 C 字符串。
  • System.String,.NET 字符串类型,用于任何 .NET 代码。与 BSTR 类似,它也有一个明确的长度字段,因此可以存储嵌入零的字符串。

在所有三种情况下,底层运行时支持库都需要使用互操作来使字符串可见:

  • VB6 为 RichEditBox 使用 ActiveX 控件。很难猜出该控件的确切外观,它非常特定于 VB6,并被命名为richtx32.ocx。它也使用原生 Windows Richedit 控件 (riched32.dll),因此 ActiveX 控件非常充当包装器,使原生 Windows 控件可在 VB6 应用程序中使用。您已经最终证明它尊重 BSTR 的行为并处理嵌入的零,就像任何 ActiveX 控件一样。

  • C 程序使用 C 运行时库,该库又通过调用 winapi 控制台函数 WriteConsole() 来实现 printf()。这个 api 函数是基于 C 的,但降压已经在 printf() 处停止,嵌入的零是该函数的字符串终止符。这里没有惊喜。

  • Winforms 程序使用 .NET RichEditBox 类,它是riched20.dll 本机 Windows 控件的托管包装器。底层机制是 pinvoke,类的几乎所有属性和方法都是通过 pinvoking SendMessage() 来实现的,以发送像 EM_SETTEXTEX 这样的消息,该消息会改变控件显示的文本。这也是一个基于 C 的 api,零就像一个字符串终止符。与richtx32.ocx 包装器不同,.NET RichEditBox 包装器类努力正确处理嵌入零的字符串。它只是按原样传递字符串并将其留给 pinvoke 编组器以将 .NET 字符串转换为 C 字符串。由于 C 字符串没有长度字段,因此除了在零处截断字符串外别无选择。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-22
    • 2011-03-09
    • 1970-01-01
    • 2019-04-11
    • 2017-08-19
    相关资源
    最近更新 更多