C 语言实例教程 💡
🎯 概述
本章节提供了丰富的 C 语言实例,从基础到进阶,涵盖各种常见的编程场景。每个示例都包含完整的代码、详细的注释和运行结果,帮助你快速掌握 C 语言编程技巧。
📋 目录
1️⃣ 基础示例
示例 1.1:Hello World
c
#include <stdio.h>
int main(void) {
printf("Hello, World!\n");
return 0;
}输出:
Hello, World!示例 1.2:变量和数据类型
c
#include <stdio.h>
int main(void) {
// 整型
int age = 25;
printf("年龄: %d\n", age);
// 浮点型
float height = 1.75f;
printf("身高: %.2f 米\n", height);
// 双精度浮点型
double pi = 3.14159265359;
printf("圆周率: %.10f\n", pi);
// 字符型
char grade = 'A';
printf("等级: %c\n", grade);
// 字符串
char name[] = "张三";
printf("姓名: %s\n", name);
return 0;
}输出:
年龄: 25
身高: 1.75 米
圆周率: 3.1415926536
等级: A
姓名: 张三示例 1.3:基本运算
c
#include <stdio.h>
int main(void) {
int a = 10, b = 3;
printf("a = %d, b = %d\n", a, b);
printf("加法: %d + %d = %d\n", a, b, a + b);
printf("减法: %d - %d = %d\n", a, b, a - b);
printf("乘法: %d * %d = %d\n", a, b, a * b);
printf("除法: %d / %d = %d\n", a, b, a / b);
printf("取余: %d %% %d = %d\n", a, b, a % b);
// 浮点数除法
printf("浮点除法: %.2f / %.2f = %.2f\n",
(float)a, (float)b, (float)a / b);
return 0;
}输出:
a = 10, b = 3
加法: 10 + 3 = 13
减法: 10 - 3 = 7
乘法: 10 * 3 = 30
除法: 10 / 3 = 3
取余: 10 % 3 = 1
浮点除法: 10.00 / 3.00 = 3.33示例 1.4:输入输出
c
#include <stdio.h>
int main(void) {
char name[50];
int age;
float height;
printf("请输入您的姓名: ");
scanf("%s", name);
printf("请输入您的年龄: ");
scanf("%d", &age);
printf("请输入您的身高(米): ");
scanf("%f", &height);
printf("\n=== 个人信息 ===\n");
printf("姓名: %s\n", name);
printf("年龄: %d 岁\n", age);
printf("身高: %.2f 米\n", height);
return 0;
}2️⃣ 控制流示例
示例 2.1:判断奇偶数
c
#include <stdio.h>
int main(void) {
int number;
printf("请输入一个整数: ");
scanf("%d", &number);
if (number % 2 == 0) {
printf("%d 是偶数\n", number);
} else {
printf("%d 是奇数\n", number);
}
return 0;
}示例 2.2:计算器
c
#include <stdio.h>
int main(void) {
char operator;
double num1, num2, result;
printf("请输入运算符 (+, -, *, /): ");
scanf(" %c", &operator);
printf("请输入两个数字: ");
scanf("%lf %lf", &num1, &num2);
switch (operator) {
case '+':
result = num1 + num2;
printf("%.2f + %.2f = %.2f\n", num1, num2, result);
break;
case '-':
result = num1 - num2;
printf("%.2f - %.2f = %.2f\n", num1, num2, result);
break;
case '*':
result = num1 * num2;
printf("%.2f * %.2f = %.2f\n", num1, num2, result);
break;
case '/':
if (num2 != 0) {
result = num1 / num2;
printf("%.2f / %.2f = %.2f\n", num1, num2, result);
} else {
printf("错误:除数不能为零!\n");
}
break;
default:
printf("错误:无效的运算符!\n");
}
return 0;
}示例 2.3:打印乘法表
c
#include <stdio.h>
int main(void) {
int n;
printf("请输入乘法表的大小: ");
scanf("%d", &n);
printf("\n%d x %d 乘法表:\n\n", n, n);
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
printf("%4d", i * j);
}
printf("\n");
}
return 0;
}输出(n=5):
5 x 5 乘法表:
1 2 3 4 5
2 4 6 8 10
3 6 9 12 15
4 8 12 16 20
5 10 15 20 25示例 2.4:判断闰年
c
#include <stdio.h>
#include <stdbool.h>
bool is_leap_year(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int main(void) {
int year;
printf("请输入年份: ");
scanf("%d", &year);
if (is_leap_year(year)) {
printf("%d 年是闰年\n", year);
} else {
printf("%d 年不是闰年\n", year);
}
return 0;
}示例 2.5:求最大公约数
c
#include <stdio.h>
// 欧几里得算法
int gcd(int a, int b) {
while (b != 0) {
int temp = b;
b = a % b;
a = temp;
}
return a;
}
int main(void) {
int num1, num2;
printf("请输入两个正整数: ");
scanf("%d %d", &num1, &num2);
int result = gcd(num1, num2);
printf("%d 和 %d 的最大公约数是: %d\n", num1, num2, result);
// 最小公倍数
int lcm = (num1 * num2) / result;
printf("%d 和 %d 的最小公倍数是: %d\n", num1, num2, lcm);
return 0;
}3️⃣ 函数示例
示例 3.1:阶乘计算
c
#include <stdio.h>
// 递归方式
long long factorial_recursive(int n) {
if (n <= 1) {
return 1;
}
return n * factorial_recursive(n - 1);
}
// 迭代方式
long long factorial_iterative(int n) {
long long result = 1;
for (int i = 2; i <= n; i++) {
result *= i;
}
return result;
}
int main(void) {
int n;
printf("请输入一个正整数: ");
scanf("%d", &n);
if (n < 0) {
printf("错误:请输入非负整数!\n");
return 1;
}
printf("%d! (递归) = %lld\n", n, factorial_recursive(n));
printf("%d! (迭代) = %lld\n", n, factorial_iterative(n));
return 0;
}示例 3.2:斐波那契数列
c
#include <stdio.h>
// 递归方式(效率低)
int fibonacci_recursive(int n) {
if (n <= 1) {
return n;
}
return fibonacci_recursive(n - 1) + fibonacci_recursive(n - 2);
}
// 迭代方式(效率高)
int fibonacci_iterative(int n) {
if (n <= 1) {
return n;
}
int prev = 0, curr = 1;
for (int i = 2; i <= n; i++) {
int next = prev + curr;
prev = curr;
curr = next;
}
return curr;
}
int main(void) {
int n;
printf("请输入要计算的斐波那契数列项数: ");
scanf("%d", &n);
printf("\n前 %d 项斐波那契数列:\n", n);
for (int i = 0; i < n; i++) {
printf("%d ", fibonacci_iterative(i));
}
printf("\n");
return 0;
}示例 3.3:判断素数
c
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
bool is_prime(int n) {
if (n <= 1) {
return false;
}
if (n <= 3) {
return true;
}
if (n % 2 == 0 || n % 3 == 0) {
return false;
}
// 只需检查到 sqrt(n)
for (int i = 5; i * i <= n; i += 6) {
if (n % i == 0 || n % (i + 2) == 0) {
return false;
}
}
return true;
}
int main(void) {
int start, end;
printf("请输入范围 (开始 结束): ");
scanf("%d %d", &start, &end);
printf("\n%d 到 %d 之间的素数:\n", start, end);
int count = 0;
for (int i = start; i <= end; i++) {
if (is_prime(i)) {
printf("%d ", i);
count++;
if (count % 10 == 0) {
printf("\n");
}
}
}
printf("\n\n共找到 %d 个素数\n", count);
return 0;
}示例 3.4:温度转换
c
#include <stdio.h>
double celsius_to_fahrenheit(double celsius) {
return celsius * 9.0 / 5.0 + 32.0;
}
double fahrenheit_to_celsius(double fahrenheit) {
return (fahrenheit - 32.0) * 5.0 / 9.0;
}
double celsius_to_kelvin(double celsius) {
return celsius + 273.15;
}
double kelvin_to_celsius(double kelvin) {
return kelvin - 273.15;
}
int main(void) {
int choice;
double temp, result;
printf("=== 温度转换器 ===\n");
printf("1. 摄氏度 → 华氏度\n");
printf("2. 华氏度 → 摄氏度\n");
printf("3. 摄氏度 → 开尔文\n");
printf("4. 开尔文 → 摄氏度\n");
printf("请选择 (1-4): ");
scanf("%d", &choice);
printf("请输入温度值: ");
scanf("%lf", &temp);
switch (choice) {
case 1:
result = celsius_to_fahrenheit(temp);
printf("%.2f°C = %.2f°F\n", temp, result);
break;
case 2:
result = fahrenheit_to_celsius(temp);
printf("%.2f°F = %.2f°C\n", temp, result);
break;
case 3:
result = celsius_to_kelvin(temp);
printf("%.2f°C = %.2fK\n", temp, result);
break;
case 4:
result = kelvin_to_celsius(temp);
printf("%.2fK = %.2f°C\n", temp, result);
break;
default:
printf("无效的选择!\n");
}
return 0;
}4️⃣ 数组和字符串
示例 4.1:数组基本操作
c
#include <stdio.h>
int main(void) {
int numbers[] = {5, 2, 8, 1, 9, 3, 7, 4, 6};
int size = sizeof(numbers) / sizeof(numbers[0]);
// 打印数组
printf("原始数组: ");
for (int i = 0; i < size; i++) {
printf("%d ", numbers[i]);
}
printf("\n");
// 求和
int sum = 0;
for (int i = 0; i < size; i++) {
sum += numbers[i];
}
printf("数组总和: %d\n", sum);
// 求平均值
double average = (double)sum / size;
printf("平均值: %.2f\n", average);
// 找最大值和最小值
int max = numbers[0], min = numbers[0];
for (int i = 1; i < size; i++) {
if (numbers[i] > max) max = numbers[i];
if (numbers[i] < min) min = numbers[i];
}
printf("最大值: %d\n", max);
printf("最小值: %d\n", min);
return 0;
}示例 4.2:冒泡排序
c
#include <stdio.h>
void bubble_sort(int arr[], int n) {
for (int i = 0; i < n - 1; i++) {
bool swapped = false;
for (int j = 0; j < n - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
// 交换
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
swapped = true;
}
}
// 如果没有交换,说明已经排序完成
if (!swapped) {
break;
}
}
}
void print_array(int arr[], int n) {
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
}
int main(void) {
int numbers[] = {64, 34, 25, 12, 22, 11, 90};
int size = sizeof(numbers) / sizeof(numbers[0]);
printf("排序前: ");
print_array(numbers, size);
bubble_sort(numbers, size);
printf("排序后: ");
print_array(numbers, size);
return 0;
}示例 4.3:字符串操作
c
#include <stdio.h>
#include <string.h>
#include <ctype.h>
// 字符串长度
int string_length(const char *str) {
int len = 0;
while (str[len] != '\0') {
len++;
}
return len;
}
// 字符串反转
void reverse_string(char *str) {
int len = strlen(str);
for (int i = 0; i < len / 2; i++) {
char temp = str[i];
str[i] = str[len - 1 - i];
str[len - 1 - i] = temp;
}
}
// 统计字符
void count_characters(const char *str) {
int letters = 0, digits = 0, spaces = 0, others = 0;
for (int i = 0; str[i] != '\0'; i++) {
if (isalpha(str[i])) {
letters++;
} else if (isdigit(str[i])) {
digits++;
} else if (isspace(str[i])) {
spaces++;
} else {
others++;
}
}
printf("字母: %d\n", letters);
printf("数字: %d\n", digits);
printf("空格: %d\n", spaces);
printf("其他: %d\n", others);
}
int main(void) {
char str1[] = "Hello World";
char str2[] = "Hello123 World!";
printf("字符串: %s\n", str1);
printf("长度: %d\n", string_length(str1));
reverse_string(str1);
printf("反转后: %s\n", str1);
printf("\n字符统计 (%s):\n", str2);
count_characters(str2);
return 0;
}示例 4.4:回文判断
c
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <ctype.h>
bool is_palindrome(const char *str) {
int left = 0;
int right = strlen(str) - 1;
while (left < right) {
// 跳过非字母数字字符
while (left < right && !isalnum(str[left])) {
left++;
}
while (left < right && !isalnum(str[right])) {
right--;
}
// 比较字符(忽略大小写)
if (tolower(str[left]) != tolower(str[right])) {
return false;
}
left++;
right--;
}
return true;
}
int main(void) {
char test_strings[][50] = {
"level",
"A man a plan a canal Panama",
"race car",
"hello",
"Was it a car or a cat I saw"
};
int count = sizeof(test_strings) / sizeof(test_strings[0]);
for (int i = 0; i < count; i++) {
printf("\"%s\" %s回文\n",
test_strings[i],
is_palindrome(test_strings[i]) ? "是" : "不是");
}
return 0;
}示例 4.5:二维数组(矩阵)
c
#include <stdio.h>
#define ROWS 3
#define COLS 3
void print_matrix(int matrix[][COLS], int rows) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < COLS; j++) {
printf("%4d", matrix[i][j]);
}
printf("\n");
}
}
void add_matrices(int a[][COLS], int b[][COLS], int result[][COLS], int rows) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < COLS; j++) {
result[i][j] = a[i][j] + b[i][j];
}
}
}
void multiply_matrices(int a[][COLS], int b[][COLS], int result[][COLS], int rows) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < COLS; j++) {
result[i][j] = 0;
for (int k = 0; k < COLS; k++) {
result[i][j] += a[i][k] * b[k][j];
}
}
}
}
int main(void) {
int matrix1[ROWS][COLS] = {
{1, 2, 3},
{4, 5, 6},
{7, 8, 9}
};
int matrix2[ROWS][COLS] = {
{9, 8, 7},
{6, 5, 4},
{3, 2, 1}
};
int sum[ROWS][COLS];
int product[ROWS][COLS];
printf("矩阵 A:\n");
print_matrix(matrix1, ROWS);
printf("\n矩阵 B:\n");
print_matrix(matrix2, ROWS);
add_matrices(matrix1, matrix2, sum, ROWS);
printf("\nA + B:\n");
print_matrix(sum, ROWS);
multiply_matrices(matrix1, matrix2, product, ROWS);
printf("\nA × B:\n");
print_matrix(product, ROWS);
return 0;
}5️⃣ 指针示例
示例 5.1:指针基础
c
#include <stdio.h>
int main(void) {
int value = 42;
int *ptr = &value;
printf("变量值: %d\n", value);
printf("变量地址: %p\n", (void*)&value);
printf("指针值(地址): %p\n", (void*)ptr);
printf("指针指向的值: %d\n", *ptr);
// 通过指针修改值
*ptr = 100;
printf("\n修改后的值: %d\n", value);
return 0;
}示例 5.2:指针与数组
c
#include <stdio.h>
int main(void) {
int numbers[] = {10, 20, 30, 40, 50};
int *ptr = numbers; // 数组名就是指向第一个元素的指针
printf("使用数组下标访问:\n");
for (int i = 0; i < 5; i++) {
printf("numbers[%d] = %d\n", i, numbers[i]);
}
printf("\n使用指针访问:\n");
for (int i = 0; i < 5; i++) {
printf("*(ptr + %d) = %d\n", i, *(ptr + i));
}
printf("\n使用指针递增访问:\n");
ptr = numbers; // 重置指针
for (int i = 0; i < 5; i++) {
printf("*ptr = %d\n", *ptr);
ptr++;
}
return 0;
}示例 5.3:函数指针
c
#include <stdio.h>
// 定义几个简单的数学函数
int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }
int divide(int a, int b) { return b != 0 ? a / b : 0; }
// 使用函数指针的计算器
int calculate(int a, int b, int (*operation)(int, int)) {
return operation(a, b);
}
int main(void) {
int x = 10, y = 5;
printf("%d + %d = %d\n", x, y, calculate(x, y, add));
printf("%d - %d = %d\n", x, y, calculate(x, y, subtract));
printf("%d * %d = %d\n", x, y, calculate(x, y, multiply));
printf("%d / %d = %d\n", x, y, calculate(x, y, divide));
// 函数指针数组
int (*operations[])(int, int) = {add, subtract, multiply, divide};
char *symbols[] = {"+", "-", "*", "/"};
printf("\n使用函数指针数组:\n");
for (int i = 0; i < 4; i++) {
printf("%d %s %d = %d\n", x, symbols[i], y, operations[i](x, y));
}
return 0;
}示例 5.4:指针与字符串
c
#include <stdio.h>
#include <string.h>
// 使用指针复制字符串
void string_copy(char *dest, const char *src) {
while ((*dest++ = *src++) != '\0');
}
// 使用指针连接字符串
void string_concat(char *dest, const char *src) {
// 移动到 dest 的末尾
while (*dest != '\0') {
dest++;
}
// 复制 src 到 dest
while ((*dest++ = *src++) != '\0');
}
int main(void) {
char str1[50] = "Hello";
char str2[50];
char str3[] = " World";
// 复制字符串
string_copy(str2, str1);
printf("复制后: %s\n", str2);
// 连接字符串
string_concat(str1, str3);
printf("连接后: %s\n", str1);
// 指针数组(字符串数组)
char *fruits[] = {"Apple", "Banana", "Orange", "Grape"};
int count = sizeof(fruits) / sizeof(fruits[0]);
printf("\n水果列表:\n");
for (int i = 0; i < count; i++) {
printf("%d. %s\n", i + 1, fruits[i]);
}
return 0;
}6️⃣ 结构体示例
示例 6.1:学生管理系统
c
#include <stdio.h>
#include <string.h>
#define MAX_STUDENTS 100
typedef struct {
int id;
char name[50];
int age;
float score;
} Student;
void print_student(const Student *s) {
printf("学号: %d\n", s->id);
printf("姓名: %s\n", s->name);
printf("年龄: %d\n", s->age);
printf("成绩: %.2f\n", s->score);
printf("------------------------\n");
}
float calculate_average(const Student students[], int count) {
float sum = 0;
for (int i = 0; i < count; i++) {
sum += students[i].score;
}
return count > 0 ? sum / count : 0;
}
void find_top_student(const Student students[], int count) {
if (count == 0) return;
int top_index = 0;
for (int i = 1; i < count; i++) {
if (students[i].score > students[top_index].score) {
top_index = i;
}
}
printf("成绩最高的学生:\n");
print_student(&students[top_index]);
}
int main(void) {
Student students[] = {
{1001, "张三", 20, 85.5},
{1002, "李四", 21, 92.0},
{1003, "王五", 19, 78.5},
{1004, "赵六", 22, 88.0}
};
int count = sizeof(students) / sizeof(students[0]);
printf("=== 学生信息 ===\n");
for (int i = 0; i < count; i++) {
print_student(&students[i]);
}
printf("\n平均成绩: %.2f\n\n", calculate_average(students, count));
find_top_student(students, count);
return 0;
}示例 6.2:图书管理系统
c
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define MAX_BOOKS 100
#define MAX_TITLE 100
#define MAX_AUTHOR 50
typedef struct {
int id;
char title[MAX_TITLE];
char author[MAX_AUTHOR];
int year;
bool is_available;
} Book;
typedef struct {
Book books[MAX_BOOKS];
int count;
} Library;
void init_library(Library *lib) {
lib->count = 0;
}
bool add_book(Library *lib, int id, const char *title,
const char *author, int year) {
if (lib->count >= MAX_BOOKS) {
return false;
}
Book *book = &lib->books[lib->count];
book->id = id;
strncpy(book->title, title, MAX_TITLE - 1);
strncpy(book->author, author, MAX_AUTHOR - 1);
book->year = year;
book->is_available = true;
lib->count++;
return true;
}
void print_book(const Book *book) {
printf("ID: %d\n", book->id);
printf("书名: %s\n", book->title);
printf("作者: %s\n", book->author);
printf("出版年份: %d\n", book->year);
printf("状态: %s\n", book->is_available ? "可借" : "已借出");
printf("------------------------\n");
}
void list_books(const Library *lib) {
printf("\n=== 图书列表 ===\n");
for (int i = 0; i < lib->count; i++) {
print_book(&lib->books[i]);
}
}
Book *find_book_by_id(Library *lib, int id) {
for (int i = 0; i < lib->count; i++) {
if (lib->books[i].id == id) {
return &lib->books[i];
}
}
return NULL;
}
bool borrow_book(Library *lib, int id) {
Book *book = find_book_by_id(lib, id);
if (book == NULL) {
printf("未找到该图书!\n");
return false;
}
if (!book->is_available) {
printf("该图书已被借出!\n");
return false;
}
book->is_available = false;
printf("成功借出《%s》\n", book->title);
return true;
}
bool return_book(Library *lib, int id) {
Book *book = find_book_by_id(lib, id);
if (book == NULL) {
printf("未找到该图书!\n");
return false;
}
if (book->is_available) {
printf("该图书未被借出!\n");
return false;
}
book->is_available = true;
printf("成功归还《%s》\n", book->title);
return true;
}
int main(void) {
Library library;
init_library(&library);
// 添加图书
add_book(&library, 1, "C程序设计语言", "Brian Kernighan", 1978);
add_book(&library, 2, "算法导论", "Thomas Cormen", 2009);
add_book(&library, 3, "深入理解计算机系统", "Randal Bryant", 2015);
// 列出所有图书
list_books(&library);
// 借书
printf("\n");
borrow_book(&library, 1);
borrow_book(&library, 1); // 尝试再次借出
// 还书
printf("\n");
return_book(&library, 1);
return 0;
}7️⃣ 文件操作
示例 7.1:文件读写基础
c
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *fp;
char content[] = "Hello, File I/O!\n这是第二行。\n";
// 写入文件
fp = fopen("test.txt", "w");
if (fp == NULL) {
perror("无法打开文件");
return 1;
}
fprintf(fp, "%s", content);
fclose(fp);
printf("文件写入成功!\n");
// 读取文件
fp = fopen("test.txt", "r");
if (fp == NULL) {
perror("无法打开文件");
return 1;
}
printf("\n文件内容:\n");
char buffer[256];
while (fgets(buffer, sizeof(buffer), fp) != NULL) {
printf("%s", buffer);
}
fclose(fp);
return 0;
}示例 7.2:学生成绩文件管理
c
#include <stdio.h>
#include <string.h>
typedef struct {
int id;
char name[50];
float score;
} Student;
// 保存学生数据到文件
int save_students(const char *filename, const Student students[], int count) {
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
return -1;
}
for (int i = 0; i < count; i++) {
fprintf(fp, "%d,%s,%.2f\n",
students[i].id,
students[i].name,
students[i].score);
}
fclose(fp);
return 0;
}
// 从文件加载学生数据
int load_students(const char *filename, Student students[], int max_count) {
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
return -1;
}
int count = 0;
while (count < max_count &&
fscanf(fp, "%d,%49[^,],%f\n",
&students[count].id,
students[count].name,
&students[count].score) == 3) {
count++;
}
fclose(fp);
return count;
}
int main(void) {
Student students[] = {
{1001, "张三", 85.5},
{1002, "李四", 92.0},
{1003, "王五", 78.5}
};
int count = 3;
// 保存到文件
if (save_students("students.csv", students, count) == 0) {
printf("学生数据已保存到 students.csv\n");
}
// 从文件加载
Student loaded[10];
int loaded_count = load_students("students.csv", loaded, 10);
if (loaded_count > 0) {
printf("\n从文件加载了 %d 个学生:\n", loaded_count);
for (int i = 0; i < loaded_count; i++) {
printf("%d. %s (学号: %d, 成绩: %.2f)\n",
i + 1, loaded[i].name, loaded[i].id, loaded[i].score);
}
}
return 0;
}示例 7.3:文件复制程序
c
#include <stdio.h>
#include <stdlib.h>
int copy_file(const char *source, const char *destination) {
FILE *src = fopen(source, "rb");
if (src == NULL) {
perror("无法打开源文件");
return -1;
}
FILE *dest = fopen(destination, "wb");
if (dest == NULL) {
perror("无法创建目标文件");
fclose(src);
return -1;
}
char buffer[4096];
size_t bytes;
while ((bytes = fread(buffer, 1, sizeof(buffer), src)) > 0) {
if (fwrite(buffer, 1, bytes, dest) != bytes) {
perror("写入错误");
fclose(src);
fclose(dest);
return -1;
}
}
fclose(src);
fclose(dest);
return 0;
}
int main(int argc, char *argv[]) {
if (argc != 3) {
printf("用法: %s <源文件> <目标文件>\n", argv[0]);
return 1;
}
printf("正在复制 %s 到 %s...\n", argv[1], argv[2]);
if (copy_file(argv[1], argv[2]) == 0) {
printf("文件复制成功!\n");
} else {
printf("文件复制失败!\n");
return 1;
}
return 0;
}示例 7.4:日志记录系统
c
#include <stdio.h>
#include <time.h>
#include <stdarg.h>
typedef enum {
LOG_DEBUG,
LOG_INFO,
LOG_WARNING,
LOG_ERROR
} LogLevel;
const char *log_level_strings[] = {
"DEBUG",
"INFO",
"WARNING",
"ERROR"
};
void log_message(LogLevel level, const char *format, ...) {
FILE *fp = fopen("app.log", "a");
if (fp == NULL) {
return;
}
// 获取当前时间
time_t now = time(NULL);
struct tm *t = localtime(&now);
// 写入时间戳和日志级别
fprintf(fp, "[%04d-%02d-%02d %02d:%02d:%02d] [%s] ",
t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
t->tm_hour, t->tm_min, t->tm_sec,
log_level_strings[level]);
// 写入日志消息
va_list args;
va_start(args, format);
vfprintf(fp, format, args);
va_end(args);
fprintf(fp, "\n");
fclose(fp);
}
int main(void) {
log_message(LOG_INFO, "程序启动");
log_message(LOG_DEBUG, "调试信息: x = %d, y = %d", 10, 20);
log_message(LOG_WARNING, "警告: 内存使用率达到 80%%");
log_message(LOG_ERROR, "错误: 无法连接到数据库");
log_message(LOG_INFO, "程序结束");
printf("日志已写入 app.log\n");
return 0;
}8️⃣ 动态内存
示例 8.1:动态数组
c
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int n;
printf("请输入数组大小: ");
scanf("%d", &n);
// 动态分配内存
int *array = (int *)malloc(n * sizeof(int));
if (array == NULL) {
printf("内存分配失败!\n");
return 1;
}
// 输入数据
printf("请输入 %d 个整数:\n", n);
for (int i = 0; i < n; i++) {
scanf("%d", &array[i]);
}
// 计算总和
int sum = 0;
for (int i = 0; i < n; i++) {
sum += array[i];
}
printf("总和: %d\n", sum);
printf("平均值: %.2f\n", (double)sum / n);
// 释放内存
free(array);
return 0;
}示例 8.2:动态字符串处理
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *string_duplicate(const char *str) {
if (str == NULL) {
return NULL;
}
size_t len = strlen(str);
char *copy = (char *)malloc(len + 1);
if (copy != NULL) {
strcpy(copy, str);
}
return copy;
}
char *string_concat(const char *str1, const char *str2) {
if (str1 == NULL || str2 == NULL) {
return NULL;
}
size_t len1 = strlen(str1);
size_t len2 = strlen(str2);
char *result = (char *)malloc(len1 + len2 + 1);
if (result == NULL) {
return NULL;
}
strcpy(result, str1);
strcat(result, str2);
return result;
}
int main(void) {
const char *original = "Hello";
// 复制字符串
char *copy = string_duplicate(original);
if (copy != NULL) {
printf("原始: %s\n", original);
printf("复制: %s\n", copy);
free(copy);
}
// 连接字符串
char *combined = string_concat("Hello", " World");
if (combined != NULL) {
printf("连接: %s\n", combined);
free(combined);
}
return 0;
}示例 8.3:动态二维数组
c
#include <stdio.h>
#include <stdlib.h>
int **create_matrix(int rows, int cols) {
int **matrix = (int **)malloc(rows * sizeof(int *));
if (matrix == NULL) {
return NULL;
}
for (int i = 0; i < rows; i++) {
matrix[i] = (int *)malloc(cols * sizeof(int));
if (matrix[i] == NULL) {
// 释放已分配的内存
for (int j = 0; j < i; j++) {
free(matrix[j]);
}
free(matrix);
return NULL;
}
}
return matrix;
}
void free_matrix(int **matrix, int rows) {
if (matrix == NULL) {
return;
}
for (int i = 0; i < rows; i++) {
free(matrix[i]);
}
free(matrix);
}
void print_matrix(int **matrix, int rows, int cols) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%4d", matrix[i][j]);
}
printf("\n");
}
}
int main(void) {
int rows = 3, cols = 4;
int **matrix = create_matrix(rows, cols);
if (matrix == NULL) {
printf("内存分配失败!\n");
return 1;
}
// 初始化矩阵
int value = 1;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
matrix[i][j] = value++;
}
}
printf("矩阵:\n");
print_matrix(matrix, rows, cols);
free_matrix(matrix, rows);
return 0;
}示例 8.4:链表实现
c
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node *next;
} Node;
// 创建新节点
Node *create_node(int data) {
Node *new_node = (Node *)malloc(sizeof(Node));
if (new_node != NULL) {
new_node->data = data;
new_node->next = NULL;
}
return new_node;
}
// 在链表头部插入
void insert_front(Node **head, int data) {
Node *new_node = create_node(data);
if (new_node == NULL) {
return;
}
new_node->next = *head;
*head = new_node;
}
// 在链表尾部插入
void insert_back(Node **head, int data) {
Node *new_node = create_node(data);
if (new_node == NULL) {
return;
}
if (*head == NULL) {
*head = new_node;
return;
}
Node *current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = new_node;
}
// 删除节点
void delete_node(Node **head, int data) {
if (*head == NULL) {
return;
}
// 如果要删除的是头节点
if ((*head)->data == data) {
Node *temp = *head;
*head = (*head)->next;
free(temp);
return;
}
// 查找要删除的节点
Node *current = *head;
while (current->next != NULL && current->next->data != data) {
current = current->next;
}
if (current->next != NULL) {
Node *temp = current->next;
current->next = current->next->next;
free(temp);
}
}
// 打印链表
void print_list(Node *head) {
Node *current = head;
while (current != NULL) {
printf("%d -> ", current->data);
current = current->next;
}
printf("NULL\n");
}
// 释放链表
void free_list(Node **head) {
Node *current = *head;
while (current != NULL) {
Node *temp = current;
current = current->next;
free(temp);
}
*head = NULL;
}
int main(void) {
Node *head = NULL;
// 插入元素
insert_back(&head, 10);
insert_back(&head, 20);
insert_back(&head, 30);
insert_front(&head, 5);
printf("链表: ");
print_list(head);
// 删除元素
delete_node(&head, 20);
printf("删除 20 后: ");
print_list(head);
// 释放链表
free_list(&head);
return 0;
}9️⃣ 实用工具
示例 9.1:命令行参数处理
c
#include <stdio.h>
#include <string.h>
void print_usage(const char *program_name) {
printf("用法: %s [选项] <文件名>\n", program_name);
printf("选项:\n");
printf(" -h, --help 显示帮助信息\n");
printf(" -v, --verbose 详细输出\n");
printf(" -o <文件> 指定输出文件\n");
}
int main(int argc, char *argv[]) {
int verbose = 0;
char *output_file = NULL;
char *input_file = NULL;
// 解析命令行参数
for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
print_usage(argv[0]);
return 0;
} else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
verbose = 1;
} else if (strcmp(argv[i], "-o") == 0) {
if (i + 1 < argc) {
output_file = argv[++i];
} else {
printf("错误: -o 选项需要参数\n");
return 1;
}
} else {
input_file = argv[i];
}
}
// 检查必需参数
if (input_file == NULL) {
printf("错误: 未指定输入文件\n");
print_usage(argv[0]);
return 1;
}
// 处理文件
if (verbose) {
printf("输入文件: %s\n", input_file);
if (output_file != NULL) {
printf("输出文件: %s\n", output_file);
}
}
printf("处理文件: %s\n", input_file);
return 0;
}示例 9.2:简单的配置文件解析器
c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_LINE 256
#define MAX_KEY 50
#define MAX_VALUE 200
typedef struct {
char key[MAX_KEY];
char value[MAX_VALUE];
} ConfigItem;
typedef struct {
ConfigItem items[100];
int count;
} Config;
void trim(char *str) {
char *start = str;
char *end;
// 去除前导空格
while (*start == ' ' || *start == '\t') {
start++;
}
// 去除尾随空格
end = start + strlen(start) - 1;
while (end > start && (*end == ' ' || *end == '\t' || *end == '\n')) {
end--;
}
*(end + 1) = '\0';
// 移动字符串
if (start != str) {
memmove(str, start, strlen(start) + 1);
}
}
int load_config(const char *filename, Config *config) {
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
return -1;
}
config->count = 0;
char line[MAX_LINE];
while (fgets(line, sizeof(line), fp) != NULL) {
// 跳过注释和空行
if (line[0] == '#' || line[0] == '\n') {
continue;
}
// 查找等号
char *equals = strchr(line, '=');
if (equals == NULL) {
continue;
}
// 分割键和值
*equals = '\0';
char *key = line;
char *value = equals + 1;
trim(key);
trim(value);
// 保存配置项
if (config->count < 100) {
strncpy(config->items[config->count].key, key, MAX_KEY - 1);
strncpy(config->items[config->count].value, value, MAX_VALUE - 1);
config->count++;
}
}
fclose(fp);
return 0;
}
const char *get_config_value(const Config *config, const char *key) {
for (int i = 0; i < config->count; i++) {
if (strcmp(config->items[i].key, key) == 0) {
return config->items[i].value;
}
}
return NULL;
}
int main(void) {
// 创建示例配置文件
FILE *fp = fopen("config.ini", "w");
if (fp != NULL) {
fprintf(fp, "# 配置文件示例\n");
fprintf(fp, "host = localhost\n");
fprintf(fp, "port = 8080\n");
fprintf(fp, "username = admin\n");
fprintf(fp, "debug = true\n");
fclose(fp);
}
// 加载配置
Config config;
if (load_config("config.ini", &config) == 0) {
printf("配置加载成功!\n\n");
// 读取配置值
printf("host = %s\n", get_config_value(&config, "host"));
printf("port = %s\n", get_config_value(&config, "port"));
printf("username = %s\n", get_config_value(&config, "username"));
printf("debug = %s\n", get_config_value(&config, "debug"));
}
return 0;
}示例 9.3:简单的 JSON 解析器(基础版)
c
#include <stdio.h>
#include <string.h>
#include <ctype.h>
// 简化的 JSON 解析器,只处理简单的键值对
void parse_json_simple(const char *json) {
const char *ptr = json;
// 跳过开始的 {
while (*ptr && *ptr != '{') ptr++;
if (*ptr) ptr++;
while (*ptr) {
// 跳过空白字符
while (*ptr && isspace(*ptr)) ptr++;
// 检查结束
if (*ptr == '}') break;
// 读取键
if (*ptr == '"') {
ptr++;
const char *key_start = ptr;
while (*ptr && *ptr != '"') ptr++;
int key_len = ptr - key_start;
char key[100];
strncpy(key, key_start, key_len);
key[key_len] = '\0';
ptr++; // 跳过结束的 "
// 跳过 :
while (*ptr && *ptr != ':') ptr++;
if (*ptr) ptr++;
// 跳过空白
while (*ptr && isspace(*ptr)) ptr++;
// 读取值
if (*ptr == '"') {
// 字符串值
ptr++;
const char *value_start = ptr;
while (*ptr && *ptr != '"') ptr++;
int value_len = ptr - value_start;
char value[100];
strncpy(value, value_start, value_len);
value[value_len] = '\0';
printf("%s: %s\n", key, value);
ptr++;
} else if (isdigit(*ptr) || *ptr == '-') {
// 数字值
const char *value_start = ptr;
while (*ptr && (isdigit(*ptr) || *ptr == '.' || *ptr == '-')) {
ptr++;
}
int value_len = ptr - value_start;
char value[100];
strncpy(value, value_start, value_len);
value[value_len] = '\0';
printf("%s: %s\n", key, value);
}
// 跳过逗号
while (*ptr && *ptr != ',' && *ptr != '}') ptr++;
if (*ptr == ',') ptr++;
}
}
}
int main(void) {
const char *json = "{\"name\": \"张三\", \"age\": 25, \"city\": \"北京\"}";
printf("解析 JSON:\n%s\n\n", json);
printf("结果:\n");
parse_json_simple(json);
return 0;
}示例 9.4:进度条显示
c
#include <stdio.h>
#include <unistd.h> // for sleep
void print_progress_bar(int current, int total, int width) {
float percentage = (float)current / total;
int filled = (int)(percentage * width);
printf("\r[");
for (int i = 0; i < width; i++) {
if (i < filled) {
printf("=");
} else if (i == filled) {
printf(">");
} else {
printf(" ");
}
}
printf("] %.1f%%", percentage * 100);
fflush(stdout);
}
int main(void) {
int total = 100;
printf("处理中...\n");
for (int i = 0; i <= total; i++) {
print_progress_bar(i, total, 50);
usleep(50000); // 暂停 50 毫秒
}
printf("\n完成!\n");
return 0;
}🚀 综合项目
项目 1:通讯录管理系统
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CONTACTS 100
#define NAME_LEN 50
#define PHONE_LEN 20
#define EMAIL_LEN 50
typedef struct {
int id;
char name[NAME_LEN];
char phone[PHONE_LEN];
char email[EMAIL_LEN];
} Contact;
typedef struct {
Contact contacts[MAX_CONTACTS];
int count;
} AddressBook;
void init_address_book(AddressBook *book) {
book->count = 0;
}
int add_contact(AddressBook *book, const char *name,
const char *phone, const char *email) {
if (book->count >= MAX_CONTACTS) {
return -1;
}
Contact *contact = &book->contacts[book->count];
contact->id = book->count + 1;
strncpy(contact->name, name, NAME_LEN - 1);
strncpy(contact->phone, phone, PHONE_LEN - 1);
strncpy(contact->email, email, EMAIL_LEN - 1);
book->count++;
return contact->id;
}
Contact *find_contact_by_name(AddressBook *book, const char *name) {
for (int i = 0; i < book->count; i++) {
if (strcmp(book->contacts[i].name, name) == 0) {
return &book->contacts[i];
}
}
return NULL;
}
void list_contacts(const AddressBook *book) {
if (book->count == 0) {
printf("通讯录为空\n");
return;
}
printf("\n%-5s %-20s %-15s %-30s\n", "ID", "姓名", "电话", "邮箱");
printf("-------------------------------------------------------------------\n");
for (int i = 0; i < book->count; i++) {
const Contact *c = &book->contacts[i];
printf("%-5d %-20s %-15s %-30s\n",
c->id, c->name, c->phone, c->email);
}
}
int delete_contact(AddressBook *book, int id) {
int index = -1;
for (int i = 0; i < book->count; i++) {
if (book->contacts[i].id == id) {
index = i;
break;
}
}
if (index == -1) {
return -1;
}
// 移动后面的联系人
for (int i = index; i < book->count - 1; i++) {
book->contacts[i] = book->contacts[i + 1];
}
book->count--;
return 0;
}
int save_to_file(const AddressBook *book, const char *filename) {
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
return -1;
}
for (int i = 0; i < book->count; i++) {
const Contact *c = &book->contacts[i];
fprintf(fp, "%d,%s,%s,%s\n", c->id, c->name, c->phone, c->email);
}
fclose(fp);
return 0;
}
int load_from_file(AddressBook *book, const char *filename) {
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
return -1;
}
book->count = 0;
Contact *c;
while (book->count < MAX_CONTACTS) {
c = &book->contacts[book->count];
if (fscanf(fp, "%d,%49[^,],%19[^,],%49[^\n]\n",
&c->id, c->name, c->phone, c->email) != 4) {
break;
}
book->count++;
}
fclose(fp);
return book->count;
}
void print_menu(void) {
printf("\n=== 通讯录管理系统 ===\n");
printf("1. 添加联系人\n");
printf("2. 查找联系人\n");
printf("3. 显示所有联系人\n");
printf("4. 删除联系人\n");
printf("5. 保存到文件\n");
printf("6. 从文件加载\n");
printf("0. 退出\n");
printf("请选择: ");
}
int main(void) {
AddressBook book;
init_address_book(&book);
int choice;
char name[NAME_LEN], phone[PHONE_LEN], email[EMAIL_LEN];
while (1) {
print_menu();
scanf("%d", &choice);
getchar(); // 消耗换行符
switch (choice) {
case 1:
printf("姓名: ");
fgets(name, NAME_LEN, stdin);
name[strcspn(name, "\n")] = 0;
printf("电话: ");
fgets(phone, PHONE_LEN, stdin);
phone[strcspn(phone, "\n")] = 0;
printf("邮箱: ");
fgets(email, EMAIL_LEN, stdin);
email[strcspn(email, "\n")] = 0;
if (add_contact(&book, name, phone, email) >= 0) {
printf("添加成功!\n");
} else {
printf("通讯录已满!\n");
}
break;
case 2:
printf("请输入姓名: ");
fgets(name, NAME_LEN, stdin);
name[strcspn(name, "\n")] = 0;
Contact *found = find_contact_by_name(&book, name);
if (found != NULL) {
printf("\n找到联系人:\n");
printf("ID: %d\n", found->id);
printf("姓名: %s\n", found->name);
printf("电话: %s\n", found->phone);
printf("邮箱: %s\n", found->email);
} else {
printf("未找到该联系人\n");
}
break;
case 3:
list_contacts(&book);
break;
case 4:
printf("请输入要删除的联系人 ID: ");
int id;
scanf("%d", &id);
if (delete_contact(&book, id) == 0) {
printf("删除成功!\n");
} else {
printf("未找到该联系人\n");
}
break;
case 5:
if (save_to_file(&book, "contacts.csv") == 0) {
printf("保存成功!\n");
} else {
printf("保存失败!\n");
}
break;
case 6:
if (load_from_file(&book, "contacts.csv") >= 0) {
printf("加载成功!共 %d 个联系人\n", book.count);
} else {
printf("加载失败!\n");
}
break;
case 0:
printf("再见!\n");
return 0;
default:
printf("无效的选择!\n");
}
}
return 0;
}项目 2:简单的文本编辑器
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINES 1000
#define MAX_LINE_LENGTH 256
typedef struct {
char *lines[MAX_LINES];
int line_count;
} TextBuffer;
void init_buffer(TextBuffer *buffer) {
buffer->line_count = 0;
for (int i = 0; i < MAX_LINES; i++) {
buffer->lines[i] = NULL;
}
}
void free_buffer(TextBuffer *buffer) {
for (int i = 0; i < buffer->line_count; i++) {
free(buffer->lines[i]);
}
}
int add_line(TextBuffer *buffer, const char *line) {
if (buffer->line_count >= MAX_LINES) {
return -1;
}
buffer->lines[buffer->line_count] = strdup(line);
if (buffer->lines[buffer->line_count] == NULL) {
return -1;
}
buffer->line_count++;
return 0;
}
void print_buffer(const TextBuffer *buffer) {
for (int i = 0; i < buffer->line_count; i++) {
printf("%3d: %s", i + 1, buffer->lines[i]);
}
}
int load_file(TextBuffer *buffer, const char *filename) {
FILE *fp = fopen(filename, "r");
if (fp == NULL) {
return -1;
}
char line[MAX_LINE_LENGTH];
while (fgets(line, sizeof(line), fp) != NULL) {
if (add_line(buffer, line) != 0) {
break;
}
}
fclose(fp);
return 0;
}
int save_file(const TextBuffer *buffer, const char *filename) {
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
return -1;
}
for (int i = 0; i < buffer->line_count; i++) {
fputs(buffer->lines[i], fp);
}
fclose(fp);
return 0;
}
void print_menu(void) {
printf("\n=== 简单文本编辑器 ===\n");
printf("1. 显示文本\n");
printf("2. 添加行\n");
printf("3. 删除行\n");
printf("4. 加载文件\n");
printf("5. 保存文件\n");
printf("0. 退出\n");
printf("请选择: ");
}
int main(void) {
TextBuffer buffer;
init_buffer(&buffer);
int choice;
char line[MAX_LINE_LENGTH];
char filename[100];
while (1) {
print_menu();
scanf("%d", &choice);
getchar();
switch (choice) {
case 1:
printf("\n当前文本:\n");
print_buffer(&buffer);
break;
case 2:
printf("输入文本(输入空行结束):\n");
while (1) {
if (fgets(line, sizeof(line), stdin) == NULL) {
break;
}
if (line[0] == '\n') {
break;
}
add_line(&buffer, line);
}
break;
case 3:
printf("输入要删除的行号: ");
int line_num;
scanf("%d", &line_num);
if (line_num > 0 && line_num <= buffer.line_count) {
free(buffer.lines[line_num - 1]);
for (int i = line_num - 1; i < buffer.line_count - 1; i++) {
buffer.lines[i] = buffer.lines[i + 1];
}
buffer.line_count--;
printf("删除成功!\n");
} else {
printf("无效的行号!\n");
}
break;
case 4:
printf("输入文件名: ");
fgets(filename, sizeof(filename), stdin);
filename[strcspn(filename, "\n")] = 0;
free_buffer(&buffer);
init_buffer(&buffer);
if (load_file(&buffer, filename) == 0) {
printf("加载成功!共 %d 行\n", buffer.line_count);
} else {
printf("加载失败!\n");
}
break;
case 5:
printf("输入文件名: ");
fgets(filename, sizeof(filename), stdin);
filename[strcspn(filename, "\n")] = 0;
if (save_file(&buffer, filename) == 0) {
printf("保存成功!\n");
} else {
printf("保存失败!\n");
}
break;
case 0:
free_buffer(&buffer);
printf("再见!\n");
return 0;
default:
printf("无效的选择!\n");
}
}
return 0;
}📚 学习建议
如何使用这些示例
- 从简单开始:按顺序学习,从基础示例开始
- 动手实践:亲自编写和运行每个示例
- 理解原理:不要只是复制代码,要理解每行代码的作用
- 修改实验:尝试修改示例,观察结果变化
- 解决问题:遇到错误时,学会调试和解决问题
练习建议
- 为每个示例添加错误处理
- 优化代码性能
- 添加新功能
- 重构代码使其更清晰
- 编写测试用例
进阶方向
- 数据结构:实现栈、队列、树、图等
- 算法:排序、搜索、动态规划等
- 系统编程:进程、线程、网络编程
- 项目实战:开发完整的应用程序
🎓 总结
本章节提供了 50+ 个实用的 C 语言示