Chapter 7: Practical Applications
In this chapter you apply what you know about C to three projects: writing a simple game, building a small web server, and creating system utilities. Building real programs gives you a better sense of how to use C effectively.
7.1 Writing a simple game: Guess the Number
The first project is a simple number guessing game. The program generates a random number, and the user has to guess it.
Python:
import random
def guess_the_number():
number = random.randint(1, 100)
guess = None
while guess != number:
guess = int(input("Guess the number between 1 and 100: "))
if guess < number:
print("Too low!")
elif guess > number:
print("Too high!")
else:
print("Congratulations! You guessed the number.")
guess_the_number()
C:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
int number, guess;
// Initialize random number generator
srand(time(0));
number = rand() % 100 + 1;
printf("Guess the number between 1 and 100: ");
do {
scanf("%d", &guess);
if (guess < number) {
printf("Too low! Try again: ");
} else if (guess > number) {
printf("Too high! Try again: ");
} else {
printf("Congratulations! You guessed the number.\n");
}
} while (guess != number);
return 0;
}
Explanation:
srand(time(0))initializes the random number generator with the current time.- The
rand()function then generates a random number between 1 and 100. - A
do-whileloop keeps asking the user for guesses until they get the number right.
7.2 Building a small web server
Next, you’ll build a simple web server. To keep it short, it answers every request with the same fixed text response instead of serving files, and it uses only basic socket programming.
Python:
import socket
def start_server():
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_socket.bind(('localhost', 8080))
server_socket.listen(1)
print("Server is running on port 8080...")
while True:
client_socket, client_address = server_socket.accept()
request = client_socket.recv(1024).decode()
print("Request received:")
print(request)
response = 'HTTP/1.0 200 OK\n\nHello, World!'
client_socket.sendall(response.encode())
client_socket.close()
start_server()
C:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
int main() {
int server_fd, new_socket;
struct sockaddr_in address;
socklen_t addrlen = sizeof(address);
char buffer[1024] = {0};
char *hello = "HTTP/1.0 200 OK\n\nHello, World!";
// Creating socket file descriptor
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket failed");
exit(EXIT_FAILURE);
}
// Bind the socket to the port 8080
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(8080);
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("bind failed");
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0) {
perror("listen");
exit(EXIT_FAILURE);
}
printf("Server is running on port 8080...\n");
// Accept incoming connection
while (1) {
if ((new_socket = accept(server_fd, (struct sockaddr *)&address, &addrlen)) < 0) {
perror("accept");
exit(EXIT_FAILURE);
}
ssize_t bytes_read = read(new_socket, buffer, sizeof(buffer) - 1);
buffer[bytes_read > 0 ? bytes_read : 0] = '\0';
printf("Request received:\n%s\n", buffer);
write(new_socket, hello, strlen(hello));
close(new_socket);
}
return 0;
}
Explanation:
- The server listens for incoming HTTP requests on port 8080.
- When a request arrives, it sends back a simple “Hello, World!” response.
- It is built from basic socket programming functions such as
socket(),bind(),listen(),accept(), andwrite(). - These functions return
-1when they fail, so the checks test for a negative result. A return value of0fromsocket()is a valid file descriptor. read()doesn’t add a terminating'\0', so the code adds one after the last byte read before printing the buffer as a string.
7.3 Creating system utilities: file copy utility
The last project is a utility that copies the contents of one file to another.
Python:
def copy_file(src, dst):
with open(src, 'r') as f_src:
with open(dst, 'w') as f_dst:
f_dst.write(f_src.read())
copy_file('source.txt', 'destination.txt')
C:
#include <stdio.h>
#include <stdlib.h>
void copyFile(const char *src, const char *dst) {
FILE *f_src = fopen(src, "r");
if (f_src == NULL) {
perror("Error opening source file");
exit(EXIT_FAILURE);
}
FILE *f_dst = fopen(dst, "w");
if (f_dst == NULL) {
perror("Error opening destination file");
fclose(f_src);
exit(EXIT_FAILURE);
}
int ch;
while ((ch = fgetc(f_src)) != EOF) {
fputc(ch, f_dst);
}
fclose(f_src);
fclose(f_dst);
}
int main() {
copyFile("source.txt", "destination.txt");
printf("File copied successfully.\n");
return 0;
}
Explanation:
- The program opens the source file for reading and the destination file for writing.
- It reads the source file character by character and writes each character to the destination file.
chis anint, not achar, becausefgetcreturns anint: either a character value orEOF, which is a separate negative value. Stored in achar, a real byte could compare equal toEOFand end the copy early, or, wherecharis unsigned, the loop would never seeEOFat all.- The program checks whether each file opened successfully and handles the error if it didn’t.