Cuando se utilizan varias cadenas como esta es posible evitar la sobrecarga puntero para cada cadena (4 u 8 bytes cada uno) mediante la concatenación de ellos junto con \0
s (1 byte) y el uso de una función de búsqueda.
#include <stdio.h>
static const char strings[]="hello\0world\0test";
char * nthstring(const char *s, unsigned n){
while(n--)
while(*s++)
;
return s;
}
int main(void) {
printf("%s\n",nthstring(strings,1));
return 0;
}
Sin embargo, si la longitud de la cadena es menor que UCHAR_MAX puede optimizar las operaciones de búsqueda mediante el uso de los marcadores de posición cero bytes para almacenar longitudes (más 1 adicional al principio) Esto cuesta sólo 1 byte de datos adicional, pero ahorra mucho de saltos condicionales e incrementos en la función de búsqueda.
#include <stdio.h>
/* each "string" is prefixed with its octal length */
static const char lenstrings[]="\05hello\05world\04test";
char * ithstring(const char *s, unsigned n){
while(n--){
s+=*s+1;
}
return s;
}
int main(void) {
char *s=ithstring(lenstrings,1);
/* use the length because we don't have terminating \0 */
printf ("%.*s",(unsigned char)*s,s+1);
//write(1,s+1,(unsigned char)*s); //POSIX variation via <unistd.h>
return 0;
}
Para ambas variaciones, es mejor mantener primero las cadenas más necesarias; sin embargo, el segundo método le permitirá usar datos comprimidos (elija el que mejor funcione para sus datos - David Cary's answer tiene una lista de soluciones viables) siempre que ajuste los separadores de longitud a la longitud comprimida.
Nota: Para conseguir la máxima compresión de los compresores estándar, es probable que desee modificar el campo de longitud de sus cabeceras ser unsigned char
(o unsigned short
si las longitudes de serie más de 256, pero no 65536 bytes) ya que la mayoría de ellos se trate para admitir la compresión de archivos de gran tamaño (esto podría ahorrar 3-7 bytes por cadena)
Y si puede reservar 1 bit del campo de tamaño para marcar si la cadena está comprimida o no, ni siquiera tiene que adivinar: solo intente comprimir cada cadena. Si se vuelve más pequeño, guárdelo comprimido. Si no es así, guárdelo sin comprimir. Esto es más o menos lo que permite PKZIP (y supongo que otros contenedores comprimidos, es solo PKZIP es el que he implementado una vez). Desafortunadamente, el rango de tamaño 10-250 no admite de manera eficiente un bit "repuesto" en una arquitectura de 8 bits. –