2010-04-05 6 views
12

Estoy usando una API nativa de bajo nivel en la que envío un puntero de buffer de bytes inseguro para obtener un valor de cadena de caracteres.Ayuda con 0 cadenas finalizadas en C#

Por lo tanto, me da

// 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)"; 

Así que, obviamente, no estoy haciendo las cosas bien, ¿cómo me deshago del exceso?

+0

Obtuve algo similar cuando recibí una cadena a través de RS-232. Eventualmente lo estaba haciendo mal: descubrí que se llama al controlador para cada byte recibido y en el controlador utilicé 'serialPortInstance.Read (...)' para leer más de 1 byte. – Dor

+0

No estoy seguro, pero podría echarle un vistazo a RegularExpression, algo así como string re1 = "((?: [A-z] [a-z] +))"; y obtenga la primera coincidencia –

+0

La "regla" de cadenas terminadas en nulo es que * todo * que comience con el primer nulo debe ignorarse. Varias de las otras respuestas que simplemente Trim() o Replace() no consideran que podría haber algún "junco" no nulo después del nulo inicial. [Esta respuesta] (https://stackoverflow.com/a/35182252/1633949) brinda una solución de una sola línea. –

Respuesta

0

Creo \ 0 es "nulo" en ascii - ¿estás seguro de que la cadena que recibes está en realidad codificada en ascii?

+0

Creo que quiere decir que está obteniendo una serie de bytes nulos, no es que realmente esté obteniendo la secuencia de cadena "\ 0". – Randolpho

+0

Sí, es ASCII – y2k

+0

Supongo que haré como .Trim ("\ 0") haha ​​ – y2k

5

Puede haber una opción para quitar NUL en la conversión.

Más allá de eso, probablemente podría limpiarlo con:

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

... o, si usted cree que puede haber caracteres no NUL después de algunos NULs, esto puede ser más seguro:

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

. Las cadenas .NET no tienen terminación nula (como puede haber adivinado a partir de esto). Entonces, puedes tratar el '\ 0' como tratarías a cualquier personaje normal. La manipulación normal de cadenas arreglará las cosas por ti. Aquí hay algunas (pero no todas) opciones.

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

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

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

Si definitivamente desea desechar cualquier valor después del primer carácter nulo, esto podría funcionar mejor para usted. Pero ten cuidado, solo funciona en cadenas que realmente incluyen el carácter nulo.

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

Estos enfoques omiten el hecho de que podría haber caracteres no nulos después del primer nulo en la cadena. [Esta respuesta] (https://stackoverflow.com/a/35182252/1633949) brinda una solución más robusta. –

+0

Um ... ¿cómo es que alguno de estos enfoques le faltan caracteres después de los nulos? Trim solo funciona en los extremos de las cadenas. Reemplazar no hace nada a ninguna parte de la cadena, excepto el carácter nulo.Split explícitamente mantiene todo excepto el carácter nulo, produciendo una matriz de cadenas. Parece que cada opción maneja con seguridad cada carácter no nulo en cualquier cadena. –

+0

sus soluciones funcionan bien para la cadena específica que el OP le dio. Pero las cadenas devueltas desde una API nativa (C++) pueden incluir basura después del nulo inicial. Una solución general debe ignorar todo después del nulo inicial, no solo omitir los null (s). Pruebe cada una de sus soluciones en esta cadena de muestra ("Aquí hay una cadena \ 0memoryjunkhere") para ver a qué me refiero. –

2

¿Qué tal uno de los métodos System.Runtime.InteropServices.Marshall.PtrToString*?

Marshal.PtrToStringAnsi - Copia todos los caracteres hasta el primer carácter nulo de una cadena ANSI no administrada a una cadena administrada, y amplía cada carácter ANSI a Unicode.

Marshal.PtrToStringUni - Asigna un String gestionado y copia todo o parte del primer nulo de una cadena Unicode no administrada en él.

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"