Converteer een getal naar een string met gespecificeerde lengte in C++

Ik heb een aantal getallen van verschillende lengte (zoals 1, 999, 76492, enzovoort) en ik wil ze allemaal converteren naar strings met een gemeenschappelijke lengte (als de lengte bijvoorbeeld 6 is, dan zijn die strings: ‘000001’, ‘000999’, ‘076492’).

Met andere woorden, ik moet het juiste aantal voorloopnullen aan het getal toevoegen.

int n = 999;
string str = some_function(n,6);
//str = '000999'

Is er een functie als deze in C++?


Antwoord 1, autoriteit 100%

of met behulp van de stringstreams:

#include <sstream>
#include <iomanip>
std::stringstream ss;
ss << std::setw(10) << std::setfill('0') << i;
std::string s = ss.str();

Ik heb de informatie verzameld die ik vond op arachnoid.comomdat ik het type- veilige manier van iostreams meer. Bovendien kun je deze code ook op elke andere uitvoerstroom gebruiken.


Antwoord 2, autoriteit 23%

char str[7];
snprintf (str, 7, "%06d", n);

Zie snprintf


Antwoord 3, autoriteit 13%

Eén ding waarvan u misschienop de hoogte wilt zijn, is de mogelijke vergrendeling die kan plaatsvinden wanneer u de stringstream-benadering gebruikt. In de STL die bij Visual Studio 2008 wordt geleverd, zijn er in ieder geval veel vergrendelingen verwijderd en vrijgegeven omdat tijdens het formatteren verschillende landinstellingen worden gebruikt. Dit kan al dan niet een probleem voor je zijn, afhankelijk van hoeveel threads je hebt die tegelijkertijd getallen naar strings kunnen converteren…

De sprintf-versie heeft geen sloten nodig (tenminste volgens de tool voor het bewaken van sloten die ik op dit moment aan het ontwikkelen ben…) en is dus misschien ‘beter’ voor gebruik in gelijktijdige situaties.

Ik merkte dit alleen op omdat mijn tool onlangs de ‘lokale’ sloten uitspuwde als een van de meest bevochten sloten in mijn serversysteem; het kwam als een beetje als een verrassing en kan ertoe leiden dat ik de aanpak die ik heb gevolgd herzien (dwz teruggaan naar sprintfvan stringstream)…


Antwoord 4, autoriteit 5%

Er zijn veel manieren om dit te doen. De eenvoudigste zou zijn:

int n = 999;
char buffer[256]; sprintf(buffer, "%06d", n);
string str(buffer);

Antwoord 5, autoriteit 5%

Deze methode gebruikt geen streams of sprintf. Afgezien van het hebben van vergrendelingsproblemen, brengen streams prestatieoverhead met zich mee en is het echt een overkill. Voor stromen komt de overhead voort uit de noodzaak om de stoom- en stroombuffer aan te leggen. Voor sprintf komt de overhead voort uit het interpreteren van de formatstring. Dit werkt zelfs wanneer nnegatief is of wanneer de tekenreeksrepresentatie van nlanger is dan len. Dit is de SNELSTE oplossing.

inline string some_function(int n, int len)
{
    string result(len--, '0');
    for (int val=(n<0)?-n:n; len>=0&&val!=0; --len,val/=10)
       result[len]='0'+val%10;
    if (len>=0&&n<0) result[0]='-';
    return result;
}

Antwoord 6, autoriteit 4%

stringstream zal doen (als xtofl opgemerkt). Boost-indelingis een handiger vervanging voor snprintf.


Antwoord 7, autoriteit 4%

Dit is een oude thread, maar aangezien fmtde standaard zou kunnen worden, hier is een extra oplossing:

#include <fmt/format.h>
int n = 999;
const auto str = fmt::format("{:0>{}}", n, 6);

Merk op dat de fmt::format("{:0>6}", n)even goed werkt als de gewenste breedte bekend is tijdens het compileren. Een andere optie is abseil:

#include <absl/strings/str_format.h>
int n = 999;
const auto str = absl::StrFormat("%0*d", 6, n);

Nogmaals, abs::StrFormat("%06d", n)is mogelijk. boost-indelingis een ander hulpmiddel voor dit probleem:

#include <boost/format.hpp>
int n = 999;
const auto str = boost::str(boost::format("%06d") % n);

Helaas worden variabele breedte-specificaties als argumenten geketend met de %operator niet ondersteund, dit vereist een format string setup (bijv. const std::string fmt = "%0" + std::to_string(6) + "d";).

Qua prestaties beweren abseil en fmt zeer aantrekkelijk en sneller te zijn dan boost. In ieder geval zouden alle drie de oplossingen efficiënter moeten zijn dan std::stringstreambenaderingen, en behalve de std::*printffamilie, offeren ze geen typeveiligheid op.


Antwoord 8

sprintf is de C-achtige manier om dit te doen, wat ook werkt in C++.

In C++, een combinatie van een stringstream- en stream-uitvoeropmaak (zie http://www .arachnoid.com/cpptutor/student3.html) zal het werk doen.

Other episodes