2010-05-12 25 views
10

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?

Respuesta

11

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, "-"); 
}; 
+0

definitivamente el más fácil de entender (es decir, leer) de todas las respuestas. – Inverse

1
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; 

http://www.ideone.com/17eRv

no su una función, pero es un método general para analizar un número por número int.

3

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 
} 
1

¿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.

0

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; 
} 
+1

qué malloc, estamos en C++ aquí –

+1

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

6

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; 
} 
+0

+1 para una solución más general. – andand

+1

+0 por violar YAGNI :-) – paxdiablo

+3

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

4

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 :-)

1
#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; 
} 
+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

+0

Por lo tanto, podría ser mejor terminar basándose en 'first == last' en lugar de' n == 0'. –

5

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.

+3

Realmente no puedo ver mucha gente resolviendo este problema en particular de esta manera, pero +1 es la respuesta más increíble. – msandiford

-1

No se requiere malloc o new, tal como se define bufchar buff[11];

Cuestiones relacionadas