C
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax
-
Section 3: Functions
-
Section 4: Arrays and Strings
-
Section 5: Pointers
-
Section 6: Memory Management
-
Section 7: Structures and Unions
-
Section 8: The Preprocessor and Build Process
-
Section 9: Standard Library: stdio.h
-
Section 10: Standard Library: stdlib.h
-
Section 11: Standard Library: string.h
-
Section 12: Standard Library: ctype.h and wctype.h
-
Section 13: Standard Library: math.h, complex.h, fenv.h, tgmath.h
-
Section 14: Standard Library: Type and Limit Headers
-
Section 15: Standard Library: Error Handling and Debugging
-
Section 16: Standard Library: Localization and Encoding
-
Section 17: Standard Library: time.h
-
Section 18: Standard Library: Concurrency (C11)
-
Section 19: POSIX and System Programming (unistd.h)
-
Section 20: More Data Structures
-
Section 21: Algorithms in C
-
Section 22: Bitwise Operations
-
Section 23: Command-Line Programs
-
Section 24: Debugging and Best Practices
-
Section 25: Compiler and Language Internals
-
Section 26: Embedded and Cross-Platform Considerations
-
Section 27: Networking Basics
-
Section 28: Practical Projects
-
Section 29: Interview Practice
-
Section 30: C23 Modern Features
-
Section 31: More Practice and Review
78: Formatted Output with printf Family
I was working on a small RPG engine the other day, and I hit a wall with how I was displaying player stats. I had all the data—health, gold, experience—but when I printed it to the console, it looked like a jumbled mess. I wanted a clean, tabular layout, but my initial attempt was just a string of comma-separated values.
The Wall of Text Problem
Here is how I started. I just threw everything into a printf call and hoped for the best:
char *player = "Kaelith";
int level = 14;
float gold = 1250.75;
float health = 88.2;
printf("Player: %s | Lvl: %d | Gold: %f | HP: %f\n", player, level, gold, health);
// Output: Player: Kaelith | Lvl: 14 | Gold: 1250.750000 | HP: 88.200000
It works, but it's ugly. Those trailing zeros on the floats are an eyesore, and if I were to print a list of five players, the columns wouldn't line up because "Kaelith" is shorter than "Thorgrim the Bold". In C, we don't just pass variables to printf; we use format specifiers to tell the compiler exactly how we want that data to look on the screen.
Taming the Floating Point
First, I want to kill those extra zeros. I remember seeing something about precision. I'll try adding a dot and a number between the % and the f.
printf("Gold: %.2f | HP: %.1f\n", gold, health);
// Output: Gold: 1250.75 | HP: 88.2
That's better. The .2 tells C, "give me exactly two decimal places." If the number was 1250.758, it would round it to 1250.76. It's a simple change, but it immediately makes the output look like professional software rather than a debug dump.
Creating a Proper Table
Now for the alignment. I want my stats to line up in columns. I'll try adding a number before the dot. I'm thinking 10 characters of width should be enough for the name.
printf("Name: %10s | Lvl: %3d\n", player, level);
// Output: Name: Kaelith | Lvl: 14
Wait, it pushed the text to the right. That's because positive numbers in the width field right-align the text. For a name column, I usually prefer left-alignment. I'll try adding a minus sign.
printf("Name: %-10s | Lvl: %3d | Gold: %8.2f\n", player, level, gold);
// Output: Name: Kaelith | Lvl: 14 | Gold: 1250.75
Now we're talking. %-10s reserves 10 spaces and sticks the string to the left. %8.2f says "make the whole number (including the dot and decimals) take up 8 spaces, with 2 of those being decimals." If the number is smaller than 8 characters, it pads the left with spaces.
Expanding the Family
Once I got the formatting down, I realized I didn't always want to print to the console. Sometimes I needed to save these stats to a file or store them in a string to pass to a GUI function. This is where the "family" comes in. printf is actually just a specific version of a more general tool.
If I want to write to a file, I use fprintf (the 'f' stands for file). It takes a file pointer as the first argument, but the formatting strings are identical:
FILE *fptr = fopen("save.txt", "w");
fprintf(fptr, "Player: %-10s | Lvl: %3d\n", player, level);
fclose(fptr);
But what if I want to "print" the result into a character array (a string) instead of a file or the screen? That's sprintf (string print). This is incredibly useful for building complex strings dynamically:
char status_buffer[50];
sprintf(status_buffer, "LVL %d: %s", level, player);
// Now status_buffer contains "LVL 14: Kaelith"
Just a word of caution: sprintf is a bit dangerous because if your formatted string is longer than your buffer, you'll overflow the memory. In a real production environment, I'd use snprintf, which lets you specify the maximum size of the buffer to prevent the program from crashing.
📋 Practical Task
Exercise: High-Score Leaderboard Formatter
You are tasked with creating a leaderboard display for an arcade game. You have the following data for three players:
- Player 1: "Ace", Score: 15400, Accuracy: 92.5%
- Player 2: "Zelda", Score: 21000, Accuracy: 88.12%
- Player 3: "Big-Iron", Score: 850, Accuracy: 45.0%
Write a program that prints this data in a perfectly aligned table. Your output must meet these requirements:
- The "Player" column must be left-aligned and occupy 12 characters.
- The "Score" column must be right-aligned and occupy 8 characters.
- The "Accuracy" column must be right-aligned, occupy 6 characters, and show exactly 1 decimal place.
- Include a header row (e.g., "PLAYER SCORE ACC") that aligns perfectly with the data below it.
Bonus: Use snprintf to format the top player's name and score into a single "Champion" string (e.g., "Champion: Zelda - 21000") and print that string separately at the bottom.
There are no comments for now.