tengo un entero de 8 dígitos que quisiera para imprimir formateado como esto:Formateo de un número entero en C++
XXX-XX-XXX
me gustaría usar una función que toma un int y vuelve una cuerda.
¿Cuál es una buena manera de hacer esto?
tengo un entero de 8 dígitos que quisiera para imprimir formateado como esto:Formateo de un número entero en C++
XXX-XX-XXX
me gustaría usar una función que toma un int y vuelve una cuerda.
¿Cuál es una buena manera de hacer esto?
Así es como yo lo haría, personalmente. Puede que no sea la forma más rápida de resolver el problema, y definitivamente no es tan reutilizable como la función de egrunin, pero me parece tan limpio como fácil de entender. Lo lanzaré al ring como una alternativa a las soluciones de mathier y loopier.
#include <sstream>
#include <string>
#include <iomanip>
std::string format(long num) {
std::ostringstream oss;
oss << std::setfill('0') << std::setw(8) << num;
return oss.str().insert(3, "-").insert(6, "-");
};
int your_number = 12345678;
std::cout << (your_number/10000000) % 10 << (your_number/1000000) % 10 << (your_number/100000) %10 << "-" << (your_number/10000) %10 << (your_number/1000) %10 << "-" << (your_number/100) %10 << (your_number/10) %10 << (your_number) %10;
no su una función, pero es un método general para analizar un número por número int.
Puede usar la clase std :: ostringstream para convertir el número en una cadena. A continuación, puede utilizar la cadena de dígitos e imprimirlos utilizando cualquier formato que desee, como en el siguiente código:
std::ostringstream oss;
oss << std::setfill('0') << std::setw(8) << number;
std::string str = oss.str();
if (str.length() != 8){
// some form of handling
}else{
// print digits formatted as desired
}
¿Cómo es esto?
std::string format(int x)
{
std::stringstream ss
ss.fill('0');
ss.width(3);
ss << (x/10000);
ss.width(1);
ss << "-";
ss.width(2);
ss << (x/1000) % 100;
ss.width(1);
ss << "-";
ss.width(3);
ss << x % 1000;
return ss.str();
}
Editar 1: Veo strstream es obsoleto y reemplazado con stringstream.
Editar 2: Se ha solucionado el problema de falta de 0 principales. Lo sé, es feo.
Obviamente un char *
y no un string
, pero se entiende. Tendrá que liberar a la salida una vez que haya terminado, y probablemente debería añadir la comprobación de errores, pero esto debe hacerlo:
char * formatter(int i)
{
char *buf = malloc(11*sizeof(char));
sprintf(buf, "%03d-%02d-%03d", i/100000, (i/1000)%100, i%1000);
return buf;
}
qué malloc, estamos en C++ aquí –
asignación manual de ¿Por qué? En todo caso, haz que el búfer sea automático y no dinámico ('sizeof (char)' siempre es 1, crea un búfer de 16 solo porque es un buen número), 'sprintf' en eso, luego devuelve un' std :: string'. – GManNickG
probado esto, funciona.
El parámetro format
aquí es "XXX-XX-XXX", pero solo mira (y omite) los guiones.
std::string foo(char *format, long num)
{
std::string s(format);
if (num < 0) { return "Input must be positive"; }
for (int nPos = s.length() - 1; nPos >= 0; --nPos)
{
if (s.at(nPos) == '-') continue;
s.at(nPos) = '0' + (num % 10);
num = num/10;
}
if (num > 0) { return "Input too large for format string"; }
return s;
}
Uso:
int main()
{
printf(foo("###-##-###", 12345678).c_str());
return 0;
}
+1 para una solución más general. – andand
+0 por violar YAGNI :-) – paxdiablo
Pero, ¿qué hace 'cout << foo (" ### - ## ", 12345) << endl' do? Si la función solo va a funcionar con una longitud particular de cadena de formato, debe 'afirmar 'eso. OMI debe 'afirmar' las condiciones de rango en lugar de fallar silenciosamente también. – msandiford
He aquí un programa completo que muestra cómo lo haría:
#include <iostream>
#include <iomanip>
#include <sstream>
std::string formatInt (unsigned int i) {
std::stringstream s;
s << std::setfill('0') << std::setw(3) << ((i % 100000000)/100000) << '-'
<< std::setfill('0') << std::setw(2) << ((i % 100000)/1000) << '-'
<< std::setfill('0') << std::setw(3) << (i % 1000);
return s.str();
}
int main (int argc, char *argv[]) {
if (argc > 1)
std::cout << formatInt (atoi (argv[1])) << std::endl;
else
std::cout << "Provide an argument, ya goose!" << std::endl;
return 0;
}
La ejecución de este con ciertos insumos da:
Input Output
-------- ----------
12345678 123-45-678
0 000-00-000
7012 000-07-012
10101010 101-01-010
123456789 234-56-789
-7 949-67-289
Esos dos últimos muestran la importancia de las pruebas . Si quieres un comportamiento diferente, deberás modificar el código. Yo por lo general optar por la aplicación de normas en silencio si la persona que llama no puede ser molestado (o es demasiado estúpida) a seguirlos pero al parecer algunas personas les gusta usar el principio de menor asombro y lanzar una excepción :-)
#include <iostream>
#include <string>
using namespace std;
template<class Int, class Bi>
void format(Int n, Bi first, Bi last)
{
if(first == last) return;
while(n != 0) {
Int t(n % 10);
n /= 10;
while(*--last != 'X' && last != first);
*last = t + '0';
}
}
int main(int argc, char* argv[])
{
int i = 23462345;
string s("XXX-XX-XXX");
format(i, s.begin(), s.end());
cout << s << endl;
return 0;
}
Este algoritmo funcionará con cualquier número entero, siempre que la cadena de formato tenga un número de X caracteres igual a la longitud del número entero. Por ejemplo, en el caso de un entero con 8 dígitos, la cadena de formato debe tener 8 caracteres X. – wilhelmtell
Por lo tanto, podría ser mejor terminar basándose en 'first == last' en lugar de' n == 0'. –
Aquí está una manera diferente de bits que intenta trabajar con la librería estándar y conseguir que haga la mayor parte del trabajo real:
#include <locale>
template <class T>
struct formatter : std::numpunct<T> {
protected:
T do_thousands_sep() const { return T('-'); }
std::basic_string<T> do_grouping() const {
return std::basic_string<T>("\3\2\3");
}
};
#ifdef TEST
#include <iostream>
int main() {
std::locale fmt(std::locale::classic(), new formatter<char>);
std::cout.imbue(fmt);
std::cout << 12345678 << std::endl;
return 0;
}
#endif
para devolver una cadena, simplemente escribir en un stringstream, y regresar a su .str()
.
Esto puede ser excesivo si sólo desea imprimir un número de esa manera, pero si usted quiere hacer este tipo de cosas en más de un lugar (o, sobre todo, si usted quiere dar formato todos números que van a un flujo particular de esa manera) se vuelve más razonable.
Realmente no puedo ver mucha gente resolviendo este problema en particular de esta manera, pero +1 es la respuesta más increíble. – msandiford
No se requiere malloc
o new
, tal como se define buf
char buff[11];
definitivamente el más fácil de entender (es decir, leer) de todas las respuestas. – Inverse