2012-03-31 8 views
8

Można obciąć ciągi z specyfikatorem printf field-width:Określanie maksymalnej szerokości pola printf dla liczb (obcięcie w razie potrzeby)?

printf("%.5s", "abcdefgh"); 

> abcde 

Niestety to nie działa dla liczb (zastępując d z x jest taka sama): istnieje prosty

printf("%2d", 1234); // for 34 
printf("%.2d", 1234); // for 34 
printf("%-2d", 1234); // for 12 
printf("%-.2d", 1234); // for 12 

> 1234 

jest/trywialny sposób określenia liczby cyfr do wydrukowania, nawet jeśli oznacza to obcięcie liczby?

MSDN specjalnie says that it will not happen, który wydaje się niepotrzebnie ograniczać. (Tak, można to zrobić, tworząc ciągi i takie, ale mam nadzieję na “printf trick” lub sprytny kludge.)

Odpowiedz

15

Podobnie jak wiele z moich najlepszych pomysłów, odpowiedź przyszła do mnie leżąc w łóżku, czekając na upadek śpi (w tym czasie nie ma nic więcej do roboty).

Użyj modułu!

printf("%2d\n", 1234%10); // for 4 
printf("%2d\n", 1234%100); // for 34 

printf("%2x\n", 1234%16); // for 2 
printf("%2x\n", 1234%256); // for d2 

To nie jest idealny, ponieważ nie można obciąć od lewej (np 12 zamiast 34), ale działa na głównych przypadków użycia. Na przykład:

// print a decimal ruler 
for (int i=0; i<36; i++) 
    printf("%d", i%10); 
+1

Jeśli chcesz obciąć od lewej, przy założeniu wartości są liczbami całkowitymi, tylko dzielić. np .: '1234/100 // dla 12' –

+0

@ortang, tak, wiem, ale to [nie to samo co obcięcie z prawej] (http://stackoverflow.com/questions/9953125/9957649?noredirect= 1 # comment34294951_22533677). – Synetech

3

Jeśli chcesz skrócić z prawej strony, możesz przekształcić swój numer na ciąg, a następnie użyć specyfikatora szerokości pola.

"%.3s".format(1234567.toString) 
+1

Już potwierdziłem, że konwertujesz je na łańcuchy; to pytanie dotyczy liczb surowych. Można przypuszczać (ktoś musiałby to sprawdzić, ale wydaje się to uzasadnione), konwersja w 'printf' jest bardziej optymalna niż konwersja ręczna. – Synetech

0

Można używać sprintf obciąć z prawej

char buf[10]; 
static const int WIDTH_INCL_NULL = 3; 

snprintf(buf, WIDTH_INCL_NULL, "%d", 1234); // buf will contain 12 
+0

Który używa bufora i zakodowanych wartości, więc jest jeszcze mniej idealna - użycie dynamicznie przydzielonej pamięci byłoby jeszcze gorsze. – Synetech

0

Dlaczego nie od lewej? Jedyną różnicą jest użycie prostego podziału:

printf("%2d", 1234/100); // you get 12 
+2

Kiedy powiedziałem, że moje rozwiązanie nie może skracać od lewej strony, nie miałem na myśli, że nie jest to możliwe; jak wykazałeś, możesz użyć podziału. Powodem, dla którego go nie używałem, jest to, że w przeciwieństwie do modułu, który może dać ci najbardziej prawe * n * cyfry * dowolnej * liczby, aby skrócić z lewej strony, musisz najpierw określić liczbę cyfr w liczbie przed możesz podzielić (w twoim przykładzie musisz użyć '1000' zamiast' 100', jeśli liczba to '12345'). Stwarza to o wiele więcej pracy, aby najpierw określić liczbę cyfr, a następnie pomnożyć 10, aby uzyskać maskę, a następnie podzielić, wszystko po to, by ją skrócić. ': - /' – Synetech

+0

Mogą istnieć (prawdopodobnie są) przypadki krańcowe, o których nie myślę, ale coś takiego jak 'num/pow (10, (int) log10 (num) - cyfry + 1);' powinno działać dla prostych przypadki (zakładając podstawę 10). –

0

przykład z linii poleceń bash

localhost ~$ printf "%.3s\n" $(printf "%03d" 1234) 
123 
localhost ~$ 
Powiązane problemy