mam 8 cyfrowy całkowitą które mogę zostać wydrukowane sformatowane tak:formatowania liczbę całkowitą C++
XXX xx-XXX
ja jak korzystać z funkcji, która jest int i powraca ciąg znaków.
Co to jest dobry sposób na zrobienie tego?
mam 8 cyfrowy całkowitą które mogę zostać wydrukowane sformatowane tak:formatowania liczbę całkowitą C++
XXX xx-XXX
ja jak korzystać z funkcji, która jest int i powraca ciąg znaków.
Co to jest dobry sposób na zrobienie tego?
Tak to zrobię, osobiście. Być może nie jest to najszybszy sposób rozwiązania problemu i zdecydowanie nie nadaje się do ponownego użycia jako funkcja egrunin, ale wydaje mi się, że jest zarówno czysty, jak i łatwy do zrozumienia. Wrzucę to na ringu jako alternatywę dla rozwiązań matematycznych i pętlowych.
#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;
nie jego funkcji, ale jego ogólny sposób analizowania numer int przez liczbę.
Możesz użyć klasy std :: ostringstream, aby przekonwertować liczbę na łańcuch. Następnie możesz użyć ciągu cyfr i wydrukować je przy użyciu dowolnego formatowania, zgodnie z poniższym kodem:
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
}
Jak to jest?
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();
}
Edycja 1: Widzę strstream jest przestarzała i zastąpiona stringstream.
Edytuj 2: Naprawiono problem braku wiodących zer. Wiem, to brzydkie.
Oczywiście jest to char *
, a nie string
, ale masz pomysł. Po zakończeniu pracy musisz zwolnić dane wyjściowe i prawdopodobnie powinieneś dodać kontrolę błędów, ale powinno to zrobić:
char * formatter(int i)
{
char *buf = malloc(11*sizeof(char));
sprintf(buf, "%03d-%02d-%03d", i/100000, (i/1000)%100, i%1000);
return buf;
}
dlaczego malloc, jesteśmy w C++ tutaj –
Dlaczego ręczny przydział? Jeśli cokolwiek, uczyń bufor automatycznie, a nie dynamicznie ('sizeof (char)' jest zawsze 1, stwórz bufor 16, tylko dlatego, że jest ładnym numerem), 'sprintf' do tego, a następnie zwróć' std :: string'. – GManNickG
Sprawdzone, działa.
Parametr format
to "XXX-XX-XXX", ale analizuje tylko (i pomija) myślniki.
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;
}
Zastosowanie:
int main()
{
printf(foo("###-##-###", 12345678).c_str());
return 0;
}
+1, aby uzyskać bardziej ogólne rozwiązanie. – andand
+0 za naruszenie YAGNI :-) – paxdiablo
Ale co robi "cout << foo (" ### - ## ", 12345) << endl'? Jeśli funkcja ma działać tylko z określoną długością ciągu formatu, powinieneś to "potwierdzić". IMO powinieneś "zapewnić" warunki zasięgu, a nie po cichu. – msandiford
Oto kompletny program, który pokazuje, jak zrobiłbym to:
#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;
}
Running to z pewnych nakładów daje:
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
Te dwie ostatnie wskazują na znaczenie testowania . Jeśli chcesz innego zachowania, musisz zmodyfikować kod. I ogólnie zdecydować się na cichym egzekwowania przepisów, jeśli rozmówca nie może być jedno (lub jest zbyt głupi), aby ich przestrzegać, ale najwyraźniej niektórzy ludzie lubią używać zasadę najmniejszego zdziwienia i podnieść wyjątek :-)
#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;
}
Ten algorytm będzie działał z dowolną liczbą całkowitą, o ile ciąg znaków formatowania ma liczbę X równą długości liczby całkowitej. Na przykład w przypadku liczby całkowitej z 8 cyframi ciąg znaków musi składać się z 8 znaków X. – wilhelmtell
Dlatego może być lepiej zakończyć na podstawie 'first == last' zamiast' n == 0'. –
Oto nieco odmienny sposób, że stara się pracować z biblioteki standardowej i zmusić go do zrobienia najbardziej realnej pracy:
#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
aby powrócić ciąg, po prostu napisz do stringstream, i zwraca jego .str()
.
Może to być przesada, jeśli chcesz wydrukować tylko jeden numer w ten sposób, ale jeśli chcesz robić tego rodzaju rzeczy w więcej niż jednym miejscu (lub, szczególnie, jeśli chcesz sformatować , wszystkie numery będą do określonego strumienia w ten sposób) staje się bardziej rozsądny.
Naprawdę nie widzę zbyt wielu ludzi, którzy rozwiązują ten konkretny problem w ten sposób, ale +1 za najbardziej niesamowitą odpowiedź. – msandiford
Nie wymaga malloc
lub new
, wystarczy zdefiniować buf
jak char buff[11];
zdecydowanie najłatwiej zrozumieć (czyli przeczytać) wszystkie odpowiedzi. – Inverse