HackerRank — Java Output Formatting
printf() nedir? Formatlama parametrelerinin kullanımı ve Output Formatting sorusunun çözümü
HackerRank üzerindeki Java problemlerini çözüyoruz. Bu beşinci problem. Eğer diğer problem çözümlerini okumadıysanız önce onlara bakmanızı tavsiye ederim, hepsinin toplu hali:
Önce problemi anlayalım sonra da çözümüne geçelim. Problemi anlama kısmını okuduktan sonra problemi çözmeyi denemenizi sonra da buradaki çözümle karşılaştırmanızı şiddetle tavsiye ederim :)
Problemin linki 👇
Problemi anlayalım
Problem girilen input’ları formatlamak üzerine. Formatlama yaparken farklı yaklaşımlar kullanabiliriz. İlk ve en kolay yaklaşım printf kullanarak tek satırda output formatlamak olacak. Diğer yaklaşımlar formatlama işlemini printf aracılığı olmadan kontrollerle yapmak olacak.
printf() Nedir?
Formatlı output print eder. Bu method “ java.io.PrintStream” dan gelir. Üç şekilde kullanılabilir:
- System.out.printf(string); → println gibi çalışır
- System.out.printf(format, arguments); → formatlı output print eder
- System.out.printf(locale, format, arguments); → Formatlama yaparken verilen Locale değerine göre formatlı output print eder
Formatlama Parametreleri
Formatlama için aşağıdaki format parametrelerinin genel şeması şu şekildedir:
%[flags][width][.hassasiyet]formatlama-karakteri → [] içindekiler opsiyoneldir
Flag karakterleri:
- - : sola hizlama/yaslama yapar ( default olan sağa yaslamadır)
- + : sayısal bir değerse + veya — şeklinde sayının pozitif negatifliğini gösterir
- 0 : sayısal değerleri 0 ile doldurmayı sağlar( default olan boşluktur)
- ** (space)** : sayı negatifse “-” gösterir, pozitifse boşluk olur
Width karakteri:
Output’ta oluşacak alanın genişliği belirlenir. Output’a minimum kaç karakter yazılacağı belirlenir.
Hassasiyet karakteri:
Sayı ise basamak sayısını, string ise karakter uzunluğunu belirler.
Formatlama karakterlerinden en sık kullanılanlar:
- d : decimal integer formatı[byte, short, int, long]
- f : floating-point formatı [float, double]
- c : character formatı (Büyük harfle C olursa karakter büyük harf olur)
- s : String formatı (Büyük harfle S olursa string büyük harflerle formatlanır)
- n : yeni satır karakteri
- t : tarih/saat formatı
Bu öğrendiklerimizi örneklendirelim, aşağıdaki ilk örneğimiz string değer aldığını için “%s” kullanıldı ve çıktı olarak da “Hello” çıktısını verecek.
System.out.printf("%s", "Hello");
Eğer yukarıdaki örnekte “%s” yerine “%S” kullansaydık, çıktı “HELLO” olacaktı.
Aşağıdaki örnekte “a” karakterinden sonra “%” ile formatlama başlatılmış, sonrasında “-” flag karakteri kullanılarak sola yaslama yapılacağı belirtilmiş, “10” ile genişlik verilmiş, yani bu formatlanan alan için en az 10 karakterlik yer ayrılmış. Eğer 10 karakterden az olursa karakterin sağında 10'a tamamlayan boş karakterler olacak, 10 karakterden fazlaysa bir değişiklik görmeyeceğiz. “s” karakteri ile bunun bir string olduğu belirtilmiş. Sonunda belirteç olması için “b” ekledim ama onun herhangi bir özelliği yok o cümlenin devamı gibi. Örneğimizin çıktısı “aHello b” olacak, burada 5 boşluk koymama izin vermedi Hello ve b arasında 5 boşluk karakteri var.
System.out.printf("a%-10sb", "Hello");
Eğer “-” olmasaydı çıktı “a Hellob” olacaktı, burada 5 boşluk koymama izin vermedi Hello ve a arasında 5 boşluk karakteri var.
Daha fazla örneğe bakalım:
System.out.printf("%c %n", 'e');
System.out.printf("%C %n", 'e');
System.out.printf("%d %n", 10005);
System.out.printf(Locale.GERMANY, "%,d %n", 100500);
System.out.printf(Locale.US, "%,d %n", 100500);
System.out.printf("%f %n", 55.1458);
System.out.printf("%.3f %n", 55.1458);
Date date = new Date();
System.out.printf("%tT %n", date);
System.out.printf("saat %tH: dakika %tM: saniye %tS%n", date, date, date);
System.out.printf("%1$tA, %1$tB %1$tY %n", date);
System.out.printf("%b %n", 5 < 4);
System.out.printf("%B %n", 5 < 4);
Sırasıyla çıktıları şu şekilde:
e
E
10005
100.500
100,500
55,145800
55,146
17:38:39
hours 17: minutes 38: seconds 39
Salı, Eylül 2024
false
FALSE
İlk satırda “%c” ile karakter formatladık. “%C” olduğunda karakter büyük harfle formatlandı. “%d” yaptığımızda integer formatladık.
Locale kullandığımız satırlarda, “Locale.GERMANY” kulandığımızda nokta ile “Locale.US” kullandığımızda virgül ile çıktı oluştu.
“%f” ile float değer formatlarken, “%.3f” yaptığımızda virgülden sonra 3 hassasiyet ile çıktı ürettik, yani virgülden sonra 3 basamak yazıldı.
“%tT” ile direkt saat formatında çıktı üretilirken, “ saat %tH: dakika %tM: saniye %tS” ile saat-dakika-saniye cinsinden ayrı ayrı yazdırabildik.
“%1$tA, %1$tB %1$tY” ile tarihi formatladık ve çıktısı “Gün, Ay Yıl” şeklinde oldu.
“%b” ile boolean çıktı üretirken “%B” yaptığımızda büyük harfle sonuç ürettik.
Daha fazla örnek ve çıktıları:
Problem Beklentisi
Her satır bir string ve integer içerecek. String değer 10 karakterli olacak, integer değer de [0–999] arası bir değer olacak.
Her çıktı satırında 2 sütun bulunacak. İlk sütun stringi sola yaslanmış ve 15 karakterlik yer ayrılmış şekilde sunacak. İkinci sütunda integer değer en az 3 basamaklı olacak, sayı 3 basamaktan az ise önüne sıfır eklenerek 3 basamaklı hale getirilecek.
Input(Girdi): Örnek bir input 👇
java 100
cpp 65
python 50
Output(Çıktı): Örnek bir output 👇
================================
java 100
cpp 065
python 050
================================
Problem Çözümü
İki farklı çözüm sunacağım burada, ilk çözüm en basiti ama yukarıdaki öğrendiklerimizi bilmeden yazmak akla gelmeyeni 😃
Çözüm 1:
public static void solutionOne() {
Scanner sc = new Scanner(System.in);
System.out.println("================================");
for (int i = 0; i < 3; i++) {
String s1 = sc.next();
int x = sc.nextInt();
System.out.printf("%-15s%03d%n", s1, x);
}
System.out.println("================================");
}
Burada sadece tek bir satır ekledik:
System.out.printf("%-15s%03d%n", s1, x);
Yukarıda öğrendiklerimizle bu satırı çözümleyelim. “%” karakteri ormatın başladığını gösteriyor. “-” ile sola doğru yaslama olacağını görüyoruz. “15” ile problemde istenen 15 karakterlik alan sağlanıyor. Böylelikle 15 karakter olmadığında boşluk karakteri ile alan ayrılacak. “s” ile de bu formatlamanın string için olduğunu belirttik.
İkinci “%” ile formatlamayı devam ettirdik. “0” ile flag eklenerek sayının 0 ile doldurulacağı söyleniyor. Sonrasında gelen “3” sayının 3 basamak olacağını ifade ediyor. En sonda “d” ile integer olduğunu ifade ediyoruz.
Son formatlama karakteri “%n” ile yeni satıra geçiyoruz.
Bu tek satır ile problemde verilen kıstaslar ile çözümü sağlamış oluyoruz.
İkinci çözümde burada yaptığımız işlemi manuel olarak yapıyoruz. Eğer formatlama bilmeseydik, problemi şu şekilde çözecektik:
public static void solutionTwo() {
Scanner sc = new Scanner(System.in);
System.out.println("================================");
for (int i = 0; i < 3; i++) {
String s1 = sc.next();
int x = sc.nextInt();
String resultStr = s1;
for (int a = 0; a < (15 - s1.length()); a++) {
resultStr += " ";
}
String resultInt;
if (x >= 0 && x <= 9) {
resultInt = "00" + x;
} else if (x >= 10 && x <= 99) {
resultInt = "0" + x;
} else {
resultInt = String.valueOf(x);
}
System.out.println(resultStr + resultInt);
}
System.out.println("================================");
}
İlk önce string için “15 — s1.length()” kere boşluk karakteri eklendi. Bu işlemi ilk çözümde “%-15s” ile sağlamıştık.
Ardından resultInt değişkenine girilen inputtaki sayıya göre kontroller yapılarak 0 karakteri eklendi. İlk çözümde karşılığı “%03d”.
Bu iki result değişkeni println aracılığıyla print edildi, böylelikle ikinci satır yeni satırdan başladı. İlk çözümde karşılığı “%n”.
İki çözüm arasındaki farklara baktığımızda formatlama bilmenin tek çözüm olmadığını ama kodu nasıl kısalttığını görebilirsiniz. İlk çözümde uzun uzadıya bir algoritma oluşturmaya çalışmak yerine formatlama karakterilerini kullanarak çözüme hızlıca ulaşabildik.
“ Java Output Formatting” problemini de çözmüş olduk! Bol kodlu ama bug’sız günler dilerim :)
Tüm problemlerin çözümleri 👇
Bu yazı için output formating konusunda kaynakçam: “https://dev.to/ritvikdubey27/printf-in-java-4265”