Agregar ceros iniciales a la cadena, sin (s)printf

5 minutos de lectura

avatar de usuario
Guus Geurkink

Quiero agregar una variable de ceros a la izquierda a una cadena. No pude encontrar nada en Google, sin que alguien mencionara (s)printfpero quiero hacer esto sin (s)printf.

¿Alguien de los lectores sabe una manera?

avatar de usuario
Ruslan Guseinov

Puedo dar esta solución de una línea si desea un campo de n_zero ceros:

auto new_str = std::string(n_zero - std::min(n_zero, old_str.length()), '0') + old_str;

por ejemplo, para std::string old_str = "45"; size_t n_zero = 4; usted obtiene new_str == "0045".

  • Me gusta esto. Significa que no tengo que construir un flujo de cadenas, que tiene bastante bagaje con respecto a las partes internas.

    –Robinson

    29 de enero de 2016 a las 12:14

  • ¡Muy buena solución! ¿Qué sucede cuando (n_zero – old_string.length()) es negativo? EDITAR: Acabo de probarlo, parece que todavía funciona pasando un valor negativo.

    – Castaña

    6 de abril de 2018 a las 5:32


  • @Castaa El argumento para la cantidad de caracteres es un std::string::size_type, que, como la mayoría de los tipos de tamaño en stdlib, no está firmado. Entonces, si el usuario pasa un número negativo, eso se envuelve y dará como resultado un gran número positivo. Por lo tanto, debería “funcionar”, pero probablemente no haga lo esperado/útil (de ahí que los tipos de tamaño sin firmar sean malos, bueno).

    – subrayado_d

    21 de enero de 2020 a las 14:57

  • se agregó una corrección sobre el desbordamiento de enteros

    – Ruslán Guseinov

    12 de noviembre de 2021 a las 9:22

  • @lys agregó una aclaración para los tipos esperados, en particular, n_zero debe ser del tipo size_t, entonces también es compatible con el constructor std::string que usamos.

    – Ruslán Guseinov

    22 de agosto a las 11:42

avatar de usuario
Robᵩ

podrías usar std::string::insert, std::stringstream con manipuladores de flujoo Boost.Formato :

#include <string>
#include <iostream>
#include <iomanip>
#include <boost/format.hpp>
#include <sstream>

int main() {
  std::string s("12");
  s.insert(0, 3, '0');
  std::cout << s << "\n";

  std::ostringstream ss;
  ss << std::setw(5) << std::setfill('0') << 12 << "\n";
  std::string s2(ss.str());
  std::cout << s2;

  boost::format fmt("%05d\n");
  fmt % 12;
  std::string s3 = fmt.str();
  std::cout << s3;
}

  • Una aplicación: Para rellenar un número entero a 20 caracteres: auto padded = std::to_string(num); padded.insert(0, 20U - std::min(std::string::size_type(20), padded.length()), '0'); los min evita que se enrolle si la cuerda que está tratando de rellenar es demasiado larga. (20 caracteres no tendrán este problema para ningún número entero de menos de 64 bits). el elenco a size_type es necesario porque min se queja de discrepancias en algunas plataformas.

    – Epónimo

    29 de agosto de 2017 a las 21:38

  • Me gustaría que pudieras explicar ese primer ejemplo usando std::string

    – Jeff

    4 de junio de 2019 a las 14:22

Podrías hacer algo como:

std::cout << std::setw(5) << std::setfill('0') << 1;

Esto debería imprimir 00001.

Tenga en cuenta, sin embargo, que el carácter de relleno es “pegajoso”, por lo que cuando termine de usar el relleno cero, tendrá que usar std::cout << std::setfill(' '); para obtener el comportamiento habitual de nuevo.

  • No, gracias por tu aporte, pero es de la misma manera usando sprintf (:

    – Guus Geurkink

    26 mayo 2011 a las 19:33

  • no parece ser pegajoso. std::cout << std::setw(5) << std::setfill('0') << 1 << 1 << std::endl; produce: 000011

    -Aleksander Fular

    14/04/2016 a las 13:37


  • @AleksanderFular std::setw no es pegajoso std::setfill es pegajoso, pero no sirve de mucho sin un ancho de gran tamaño para darle algo que hacer. Entonces tu primero 1 obtiene el setw(5) y por lo tanto tiene ceros delante, pero entonces el setw vuelve a los valores predeterminados, por lo que su segundo 1 simplemente se imprime como 1. Asi que, 00001 + 1 = 000011. El punto es que si luego configuras setwencontrará que el anterior setfill carácter todavía estaba en vigor, porque setfill no es pegajoso => ​​no se restablece a su espacio predeterminado.

    – subrayado_d

    3 oct 2016 a las 16:22


  • Exactamente lo que necesitaba. Gracias.

    – Rapti

    12 dic 2016 a las 21:12

// assuming that `original_string` is of type `std:string`:

std::string dest = std::string( number_of_zeros, '0').append( original_string);

Esto funciona bien para mi. No necesita volver a cambiar setfill a ‘ ‘, ya que se trata de una transmisión temporal.

std::string to_zero_lead(const int value, const unsigned precision)
{
     std::ostringstream oss;
     oss << std::setw(precision) << std::setfill('0') << value;
     return oss.str();
}

avatar de usuario
Genhis

Si desea modificar la cadena original en lugar de crear una copia, puede usar std::string::insert().

std::string s = "123";
unsigned int number_of_zeros = 5 - s.length(); // add 2 zeros

s.insert(0, number_of_zeros, '0');

Resultado:

00123

avatar de usuario
seth robertson

memcpy(target,'0',sizeof(target));
target[sizeof(target)-1] = 0;

Luego pegue la cadena que desee con el prefijo cero al final del búfer.

Si es un número entero, recuerda log_base10(number)+1 (también conocido como ln(number)/ln(10)+1) te da la longitud del número.

  • No, gracias por intentarlo, pero quiero poder agregar una cantidad variable de ceros.

    – Guus Geurkink

    26 mayo 2011 a las 19:19

  • @Guus: Eso es un número variable de ceros. Sin embargo, puede reemplazar el (tamaño de (objetivo)) con algún otro número si lo hace feliz.

    – Seth Robertson

    26 mayo 2011 a las 19:21


  • @Guus: Específicamente, según su comentario a continuación, quería %05d, ¿verdad? Si el búfer tiene seis caracteres de largo, eso es exactamente lo que mi código haría por usted (al menos la parte de relleno cero, poner el número al final se dejó para usted).

    – Seth Robertson

    26 mayo 2011 a las 19:23

¿Ha sido útil esta solución?