tabla de búsqueda de mensajes c++ (iostream)

¿Hay una manera fácil en C++ de tener una tabla de búsqueda de mensajes que permita el uso de variables?

Por ejemplo en C puedes tener algo como esto:

const char* transaction_messages[] = {
"UNAUTHORIZED",
"UNKNOWN_ORDER",
"UNKNOWN_DEALER",
"UNKNOWN_COMMODITY",
"INVALID_MESSAGE",
"BOUGHT %d %s @ %f.1 FROM %s", //amount, commodity, price, dealer
"SOLD %d %s @ %f.1 FROM %s", //amount, commodity, price, dealer
"%d HAS BEEN FILLED", //order id
"%d HAS BEEN REVOKED", //order id
"%d %s %s %s %d %f.1 HAS BEEN POSTED", //order id, dealer, side, commodity, amount, price
"%d %s %s %s %d %f.1" //order id, dealer, side, commodity, amount, price
};

y luego usarlo en una función como esta:

void myfunction(int amount, char* commodity, double price, char* dealer){

    char *msg = transaction_message[6];
    printf(msg, amount, commodity, price, dealer);
}

Quiero poder hacer lo mismo con un ostream en lugar de tener que hacer algo con el operador << donde se vería lo mismo:

ostream << "BOUGHT" << amount << " " << commodity << " @ " << price << " FROM " << dealer;

la única forma en que puedo pensar en hacer esto ahora mismo sería tener un montón de funciones en línea que devuelvan cadenas y, en lugar de tener una tabla char*, tener una tabla de funciones que busque las funciones en línea. Debe haber una manera más fácil aunque.

preguntado el 15 de mayo de 12 a las 16:05

la pregunta es: ¿por qué? ¿Qué problema estás tratando de resolver con él? sabiendo que tal vez hay una solución diferente a ese problema. -

Notas la desventaja de la printf versión, que un pequeño error tipográfico como transaction_message[6] en lugar de [5] cambios de COMPRÓ a VENDIDO? No cometerías ese error en la segunda versión. -

@BoPersson Aunque estoy de acuerdo en que printf es demasiado propenso a errores para ser utilizado en el código de producción, un error en el índice es un error en el índice, independientemente de si la matriz contiene printf Cadenas de formato o punteros a funciones. -

3 Respuestas

Lo que estás haciendo es muy similar a la Localización (AKA L10N).

Hay un par de preguntas sobre esto: La mejor forma de diseñar para la localización de cadenas

Pero hay varios paquetes que ya se ocupan de esto.
Estos están básicamente diseñados para tomar todas las cadenas de su aplicación y empaquetarlas en un recurso separado (el recurso correcto (dependiendo generalmente de la configuración regional) se selecciona en tiempo de ejecución). Pero generalmente usan el "inglés" (o debería decir texto original para programadores que no están en inglés) como texto de búsqueda para encontrar la cadena de recursos correcta (por lo tanto, el desarrollador aún puede leer el código) y el usuario obtiene un idioma específico cadena mostrada.

Por supuesto, boost también tiene uno

Pero hay otros (búsqueda rápida de Google)

Otros recursos:

Pero conseguir la cuerda correcta es solo la mitad de la batalla. Luego, debe intercambiar correctamente los valores de tiempo de ejecución con marcadores de posición en la cadena. Personalmente aquí es donde creo boost :: formato realmente brilla.

Ejemplo:

sprintf("The time is %s in %s.", time, country);

El problema es que el orden de los sustantivos y los verbos difiere entre los idiomas. Por ejemplo, si traducimos

"Son las 12:00 en Alemania".

al azerbaiyano

"Saat Almaniya saat 12:00 deyil".

Notarás que la palabra para "Alemania" (Almaniya) cambia de lugar con el tiempo. Por lo tanto, la simple tarea de reemplazar artículos en un orden específico no funciona. Lo que necesita son marcadores de posición indexados. (boost::format al rescate).

std::cout << boost::formt("The time is %1 in %2.") << time << country;
// Notice the place holders are number '%1' means the first bound argument
// But the format string allows you to place them in any order in the string
// So your localized resource will look like this:

std::cout << boost::formt("Saat %2 saat %1 deyil.") % time % country;

O más probable:

std::cout << boost::formt(I10N.get("The time is %1 in %2.")) % time % country;

contestado el 23 de mayo de 17 a las 11:05

A mí no me parece una localización. (En la práctica, para cualquier cosa que tenga que ver con mensajes en idiomas nativos reales, la localización significa una DLL diferente por idioma, para manejar cosas como plurales, género, etc. correctamente). - james kanze

@JamesKanze: me parece una localización: transaction_messages[]. Donde el texto mostrado varía en tiempo de ejecución pero el índice de búsqueda es una constante de tiempo de compilación. Pero si. Cuando se trata de la localización, la cadena debe empaquetarse en sus propios recursos (DLL en sus términos). Si, por otro lado, el OP solo está intentando una forma más compacta de formatear su salida (podría leerlo de esta manera), la segunda mitad de mi respuesta cubre eso. - martín york

No veo idiomas diferentes, lo que sería típico de la internacionalización. Ni nada relacionado con el género, el número o cualquiera de los otros problemas que encuentras en la internacionalización. Me parece que está generando un mensaje de acuerdo con un tipo de transacción. - james kanze

@JamesKanze: L10N no I18N. Seguro que puedo estar equivocado. Entonces mi respuesta es demasiado compleja, pero la segunda mitad se aplica al formato de mensajes que él puede aplicar. - martín york

En c ++ boost::format se puede utilizar como un tipo de seguridad sprintf().

contestado el 15 de mayo de 12 a las 16:05

Qué tal si:

ostream& ToString(ostream&O, int amount, char* commodity, double price, char* dealer)
{
  char buf[80];

  char *msg = transaction_message[6];
  sprintf(msg, amount, commodity, price, dealer);

  return O << buf;
}

contestado el 15 de mayo de 12 a las 16:05

Eso te limita a 80 caracteres. en total sin embargo, probablemente no sea suficiente para tener sentido. - Ricardo J. Ross III

@ RichardJ.RossIII Espero que el programador sea lo suficientemente competente como para expandir esto a la longitud requerida. - Neil

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.