Necesito concatenar algunas cadenas y necesito incluir bytes NULL. No quiero tratar un ‘\ 0’ como un byte de terminación. ¡Quiero guardar mis valiosos bytes NULL!
En un ejemplo de código, si
char *a = "\0hey\0\0";
Necesito imprimir en un formato que genere “\0hey\0\0”.
-AUstin
Qué tal si:
int i;
for(i = 0; i < 4; i++)
printf("%c", a[i]);
Si desea que una función ‘similar a printf’ use esto cuando especifique %s
en una cadena de formato, podría incluir el código anterior en su propia función. Pero como mencionó @Neil, tendrá dificultades para encontrar una alternativa a la búsqueda de bytes nulos para determinar la longitud de las cadenas. Para eso, supongo que podrías usar algún tipo de personaje de escape.
-
¿Por qué tomaría mucho código? ¿Es un bucle for trivial? Es difícil ver una alternativa a esto.
–David Heffernan
23 de mayo de 2011 a las 6:55
-
Digo mucho código porque hacer esto para 10 cadenas significa 10 bucles for. no es el fin del mundo, por supuesto. simplemente parece menos ideal, sin embargo, admito que no estoy trabajando con la situación más ideal
– austin
23 de mayo de 2011 a las 7:25
-
@austin – ¿No significa una función y diez llamadas?
– Bo Person
23 de mayo de 2011 a las 16:37
-
Recomiendo usar putchar() en lugar de printf() para esto. No es necesario formatear los caracteres, por lo que putchar() es mucho más eficiente.
– Búho
25 de agosto de 2016 a las 0:47
-
o que tal
fwrite(a, 1, 4, stdout);
. Eso es incluso mejor queputchar
; no es necesario recorrer los bytes de uno en uno.– Peter Cordes
3 de enero de 2019 a las 16:29
mateo k
El problema aquí es que la longitud de la cadena a
no se puede determinar fácilmente. Por ejemplo, su código ..
char *a = "\0hey\0\0";
.. asigna siete bytes a la cadena, siendo el último el terminador NULL. Usando una función como strlen
devolvería 0.
Si conoce la longitud precisa de la cadena, puede escribir o iterar sobre los bytes de la siguiente manera:
#ifdef ESCAPE_NULLS
int i;
for (i = 0; i <= 6; i++)
if (a[i] == 0)
printf("\\0");
else
printf("%c", a[i]);
#else
write(1, a, 6);
#endif
Pero tienes que saber sobre el 6.
La alternativa es no usar cadenas terminadas en NULL y, en su lugar, implementar un mecanismo de almacenamiento alternativo para sus bytes; por ejemplo, una matriz codificada por longitud.
#include <stdio.h>
typedef struct {
int length;
char *bytes;
} bytearr;
void my_printf(bytearr *arr)
{
#ifdef ESCAPE_NULLS
int i;
for (i = 0; i <= arr->length; i++)
if (arr->bytes[i] == 0)
printf("\\0");
else
printf("%c", arr->bytes[i]);
#else
write(1, arr->bytes, arr->length);
#endif
}
void main(void)
{
bytearr foo = {
6, "\0hey\0\0"
};
my_printf(&foo);
}
Sin gracia, pero espero que entiendas la idea.
Editar: 2011-05-31
Al volver a leer la pregunta, acabo de notar la palabra “concatenar”. Si los caracteres NULL se van a copiar fielmente de un lugar de la memoria a otro (sin barra invertida de escape), y sabe el número total de bytes en cada matriz de antemano, simplemente puede usar memcpy
.
#include <string.h>
char *a = "\0hey\0\0"; /* 6 */
char *b = "word\0up yo"; /* 10 */
char *c = "\0\0\0\0"; /* 4 */
void main(void)
{
char z[20];
char *zp = z;
zp = memcpy(zp, a, 6);
zp = memcpy(zp, b, 10);
zp = memcpy(zp, c, 4);
/* now z contains all 20 bytes, including 8 NULLs */
}
-
tiene una declaración if/else en la primera parte de su respuesta. ¿Esto implica que un printf(“%c”) en un byte NULL no funcionará?
– austin
23 de mayo de 2011 a las 7:28
-
Depende de si desea pasar fielmente el byte nulo a STDOUT, o si desea escapar de él (que fue como leí la pregunta original).
– Matty K.
26 mayo 2011 a las 14:40
-
@MattyK: No debería
write(1, a, 6);
serwrite(1, a, sizeof(char)*6);
?– usuario2284570
21/10/2015 a las 13:00
-
Claro, si está escribiendo un código portátil adecuado. Es fácil ser perezoso y asumir
sizeof(char)==1
– Matty K.
22 de octubre de 2015 a las 6:48
-
No mezcle POSIX
write()
con stdioprintf
. Utilizarfwrite
. y no usesprintf("%c"
para bytes individuales, useputchar
! O mejor, busca el siguiente0
y usefwrite
para todos los bytes distintos de cero con una llamada de función. O copiar y escapar en un búfer local y escribir eso. Y por cierto,memcpy
no esstrcat
:memcpy
devuelve su primer argumento sin modificar, no el fin de donde escribió. Entonces su actualización sobrescribe repetidamente el comienzo dez
. Pero sí, memcpy es la herramienta adecuada para el trabajo, si usa el puntero de destino correcto.– Peter Cordes
3 de enero de 2019 a las 16:27
char *a="\0hey\0\0";
int alen = 7;
char buf[20] = {0};
int bufSize = 20;
int i=0;
int j=0;
while( i<bufSize && j<alen )
{
if(a[j]=='\0') {
buf[i++]='\\';
buf[i++]='0';
j++;
}
else {
buf[i++] = a[j++];
}
}
printf(buf);
¿Cómo vas a calcular cuánto mide la cuerda?
– usuario2100815
23 de mayo de 2011 a las 6:40
está predeterminado. He asignado espacio, digamos 8 bytes. quiero juntar algunas cadenas de varios tamaños dados, usando un printf(%s%s%s…)
– austin
23 de mayo de 2011 a las 6:44
Si la matriz tiene valores nulos incrustados, no es una cadena. No lo llames una cadena. Llámelo una matriz de caracteres (sin firmar) (con valores nulos incrustados). Como no es una cadena, no puede usar de manera confiable ninguna función de cadena en ese objeto: no
"%s"
conversión aprintf
(oscanf
), nofputs
nofgets
nostrcpy
nostrcat
…– pmg
23 de mayo de 2011 a las 11:05