2010-04-05 96 views
12

我正在使用一个低级别的本地API,我发送一个不安全的字节缓冲区指针来获取c-string值。帮助在C#中终止字符串0#

所以它给了我

// using byte[255] c_str 
string s = new string(Encoding.ASCII.GetChars(c_str)); 

// now s == "heresastring\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0(etc)"; 

所以,很显然我不这样做是正确的,我该怎么摆脱多余的?

+0

当通过RS-232接收到字符串时,我得到了类似的东西。最终我做错了:我发现为接收到的每个字节调用处理程序,并在处理程序中使用'serialPortInstance.Read(...)'读取多于1个字节。 – Dor 2010-04-05 21:59:23

+0

我不确定,但可能看看RegularExpression,像string re1 =“((?:[a-z] [a-z] +))”;并获得第一个匹配 – 2017-03-24 20:37:07

+0

以null结尾的字符串的“规则”是,应该忽略以first null开头的* everything *。 Trim()或Replace()的其他一些答案没有考虑到在初始空值之后可能存在一些非空的“垃圾”。 [这个答案](https://stackoverflow.com/a/35182252/1633949)给出了一个单线解决方案。 – 2018-01-26 16:38:02

回答

0

我相信\ 0在ascii中为“null” - 你确定你得到的字符串实际上是ASCII编码吗?

+0

我认为他意味着他得到一系列空字节,而不是他实际上得到“\ 0”字符串序列。 – Randolpho 2010-04-05 21:40:24

+0

是的,它的ASCII – y2k 2010-04-05 21:40:38

+0

我想我会做.Trim(“\ 0”)哈哈 – y2k 2010-04-05 21:43:18

5

可能有一个选项可以在转换中剥离NUL。

除此之外,你也许可以用它清理干净:

s = s.Trim('\0'); 

...或者,如果你认为可能会有一些完全无效后非NULL字符,这可能是更安全:

int pos = s.IndexOf('\0'); 
if (pos >= 0) 
    s = s.Substring(0, pos); 
28

.NET字符串不是空终止的(正如您可能已经猜到的那样)。所以,你可以像对待任何普通字符那样对待'\ 0'。正常的字符串操作将为您解决问题。这里有一些(但不是全部)选项。

s = s.Trim('\0'); 

s = s.Replace("\0", ""); 

var strings = s.Split(new char[] {'\0'}, StringSplitOptions.RemoveEmptyEntries); 

如果你一定要第一个空字符后扔掉的任何值,这可能为你工作好。但要小心,它只适用于实际包含空字符的字符串。

s = s.Substring(0, Math.Max(0, s.IndexOf('\0'))); 
+0

这些方法错过了字符串中第一个空值后可能有非空字符的事实。 [这个答案](https://stackoverflow.com/a/35182252/1633949)提供了一个更强大的解决方案。 – 2018-01-26 16:44:16

+0

嗯......这些方法中的任何一种如何在空值之后缺少字符?修剪仅适用于字符串的末尾。替换不会对字符串中除空字符以外的任何部分执行任何操作。拆分显式保留除空字符以外的所有内容,生成一个字符串数组。它看起来像每个选项安全地处理任何字符串中的每个非空字符。 – 2018-01-29 04:56:32

+0

您的解决方案适用于OP提供的特定字符串。但是从本机(C++)API返回的字符串可能包含初始null后的垃圾。一般的解决方案必须忽略初始空值之后的所有内容,而不仅仅是省略null(s)。试试这个示例字符串上的每个解决方案(“这里是一个字符串\ 0memoryjunkhere”)来查看我的意思。 – 2018-01-29 12:53:16

2

System.Runtime.InteropServices.Marshall.PtrToString*方法之一怎么样?

Marshal.PtrToStringAnsi - 将从非托管ANSI字符串到第一个空字符的所有字符复制到托管字符串,并将每个ANSI字符扩展为Unicode。

Marshal.PtrToStringUni - 分配托管字符串并将全部或部分复制到非托管Unicode字符串的第一个空格中。

2
// s == "heresastring\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0(etc)"  
s = s.Split(new[] { '\0' }, 2)[0]; 
// s == "heresastring"