This program reads a filename and a count n from the command line, reads the first n characters from the file, reverses them in-place using a two-pointer swap, and prints the result. It demonstrates combining command-line argument parsing, file I/O with fread(), and in-place string reversal in a single practical program.
The original post used conio.h, process.h, void main(), and a one-character-only hack (*argv[2]-48) that silently broke for any n >= 10. This rewrite uses atoi(), proper file I/O, fprintf(stderr, ...) for errors, and a clean two-pointer reversal.
C Program: Reverse First n Characters in a File
/* Reverse first n characters in a file (command-line arguments)
* Usage: ./reversefile <filename> <n>
* Compile: gcc -ansi -Wall -Wextra reversefile.c -o reversefile */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
FILE *fp;
char buf[256];
int n, i, j, len;
char tmp;
if (argc != 3) {
fprintf(stderr, "Usage: %s <filename> <n>\n", argv[0]);
return 1;
}
n = atoi(argv[2]);
if (n <= 0) {
fprintf(stderr, "Error: n must be a positive integer\n");
return 1;
}
if (n > (int)(sizeof(buf) - 1)) {
fprintf(stderr, "Error: n too large (max %d)\n", (int)(sizeof(buf) - 1));
return 1;
}
fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "Error: cannot open '%s'\n", argv[1]);
return 1;
}
len = (int)fread(buf, 1, (size_t)n, fp);
fclose(fp);
if (len == 0) {
fprintf(stderr, "Error: file is empty or n exceeds file length\n");
return 1;
}
buf[len] = '\0';
/* Reverse in-place using two-pointer swap */
i = 0;
j = len - 1;
while (i < j) {
tmp = buf[i];
buf[i] = buf[j];
buf[j] = tmp;
i++;
j--;
}
printf("First %d characters reversed: %s\n", len, buf);
return 0;
}
How to Compile and Run
gcc -ansi -Wall -Wextra reversefile.c -o reversefile
# Create a test file
echo "Hello, World!" > testfile.txt
# Reverse first 5 characters
./reversefile testfile.txt 5
# Reverse first 13 characters
./reversefile testfile.txt 13
Sample Output
First 5 characters reversed: olleH First 13 characters reversed: !dlroW ,olleH
How It Works — Step by Step
| Step | Action | Result (n=5, file=”Hello, World!”) |
|---|---|---|
| 1 | Validate argc == 3 | argv[1]=”testfile.txt”, argv[2]=”5″ |
| 2 | n = atoi(argv[2]) | n = 5 |
| 3 | fopen(argv[1], “r”) | File opened for reading |
| 4 | fread(buf, 1, 5, fp) | buf = “Hello”, len = 5 |
| 5 | buf[5] = ‘\0’ | null-terminate the buffer |
| 6 | Two-pointer swap: i=0,j=4 → swap H and o | buf = “oellH” |
| 7 | i=1, j=3 → swap e and l | buf = “olleH” |
| 8 | i=2, j=2 → i < j is false, stop | buf = “olleH” (middle char unchanged) |
| 9 | printf result | “First 5 characters reversed: olleH” |
Code Explanation
atoi(argv[2])instead of*argv[2]-48— the original used*argv[2]-48which dereferences argv[2] to get the first character and subtracts ASCII ‘0’ (decimal 48) to get a digit. This only works for single digits (n = 0–9). For n=10 or above it silently produces wrong results.atoi()converts the entire string to an integer and handles any number of digits.fread(buf, 1, n, fp)— reads up tonbytes (one byte per read element) into buf. Returns the actual number of bytes read (may be less than n if the file is shorter). The return value is stored inlen, not n, so the reversal always operates on exactly the bytes that were read.buf[len] = '\0'— fread does not null-terminate the buffer. Null termination is required before passing to printf with %s. Without it, printf reads past the valid data into garbage memory.- Two-pointer reversal — start i at the left end, j at the right end. Swap buf[i] and buf[j], then move i right and j left. Stop when i >= j. This runs in O(n/2) = O(n) time and O(1) extra space (just the tmp variable).
fclose(fp)before the reversal — close the file immediately after reading is done. There is no reason to keep it open while we reverse and print, and forgetting to close files is a resource leak.- Error messages to stderr —
fprintf(stderr, "...")writes error messages to the standard error stream. This keeps error output separate from normal output, which is important when the program is used in a pipeline.
What This Program Teaches
- fread() for binary-safe reading — unlike fgets(), fread() reads raw bytes without interpreting newlines. It is the right choice when you want to read exactly n bytes from a file, regardless of content.
- Two-pointer in-place reversal — this is a classic technique: no second array needed, just swap from both ends toward the middle in O(n) time. It is the same algorithm used to reverse arrays, strings, and linked lists.
- Command-line arguments for file tools — any tool that processes files should take the filename as a command-line argument (not prompt the user). This makes the program scriptable — you can call it in a shell loop, pipe its output, or use it in a Makefile.
- Validate before using argc/argv — always check that argc has the expected count before accessing argv[1], argv[2], etc. If the user omits an argument, argv[1] might be NULL and dereferencing it is undefined behavior.
Related Programs
- Command Line Arguments in C
- File Copy in C
- Delete n Characters from String in C
- Pointers in C — Complete Guide
- File Handling in C — Complete Guide
Recommended book:
The C Programming Language — Kernighan & Ritchie (India) |
(US)
|
C Programming: A Modern Approach — K.N. King (India) |
(US)
Practice what you learned: C Aptitude Questions — or try our C Programming Quiz App on Android.