C语言核心特性:函数、数组与指针
在掌握了C语言基础之后,我们现在来学习C语言的核心特性。这些特性是C语言强大功能的基础,也是区别于其他高级语言的重要特征。
1. 函数:代码的模块化工具
函数是C程序的基本构建块,它允许我们将复杂的任务分解为更小、更易管理的部分。
函数定义与声明
c
#include <stdio.h>
// 函数声明(原型)
int add(int a, int b);
void print_message(const char* message);
int factorial(int n);
// 主函数
int main() {
int result = add(5, 3);
printf("5 + 3 = %d\n", result);
print_message("Hello, Function!");
int fact = factorial(5);
printf("5! = %d\n", fact);
return 0;
}
// 函数定义
int add(int a, int b) {
return a + b;
}
void print_message(const char* message) {
printf("消息: %s\n", message);
}
// 递归函数示例
int factorial(int n) {
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
}参数传递方式
C语言中的参数传递采用值传递方式:
c
#include <stdio.h>
// 值传递:不会修改原始变量
void modify_value(int x) {
x = 100;
printf("函数内 x = %d\n", x);
}
// 通过指针传递地址:可以修改原始变量
void modify_by_pointer(int* ptr) {
*ptr = 200;
printf("函数内 *ptr = %d\n", *ptr);
}
int main() {
int num = 50;
printf("调用前 num = %d\n", num);
modify_value(num);
printf("值传递后 num = %d\n", num);
modify_by_pointer(&num);
printf("指针传递后 num = %d\n", num);
return 0;
}函数的高级用法
c
#include <stdio.h>
// 可变参数函数
#include <stdarg.h>
int sum(int count, ...) {
va_list args;
va_start(args, count);
int total = 0;
for (int i = 0; i < count; i++) {
total += va_arg(args, int);
}
va_end(args);
return total;
}
// 内联函数(C99标准)
static inline int max(int a, int b) {
return (a > b) ? a : b;
}
int main() {
// 可变参数函数调用
int result = sum(4, 10, 20, 30, 40);
printf("sum(10, 20, 30, 40) = %d\n", result);
// 内联函数
printf("max(5, 8) = %d\n", max(5, 8));
return 0;
}2. 数组:数据的集合
数组是存储相同类型数据的连续内存区域。
一维数组
c
#include <stdio.h>
int main() {
// 数组定义和初始化
int numbers[5] = {1, 2, 3, 4, 5};
int scores[10]; // 未初始化,值不确定
int primes[] = {2, 3, 5, 7, 11}; // 自动计算大小
// 数组访问
printf("第一个元素: %d\n", numbers[0]);
printf("最后一个元素: %d\n", numbers[4]);
// 数组遍历
printf("数组元素: ");
for (int i = 0; i < 5; i++) {
printf("%d ", numbers[i]);
}
printf("\n");
// 数组大小
int size = sizeof(numbers) / sizeof(numbers[0]);
printf("数组大小: %d\n", size);
return 0;
}二维数组
c
#include <stdio.h>
int main() {
// 二维数组定义和初始化
int matrix[3][4] = {
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
};
// 访问二维数组元素
printf("matrix[1][2] = %d\n", matrix[1][2]);
// 遍历二维数组
printf("矩阵内容:\n");
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 4; j++) {
printf("%3d ", matrix[i][j]);
}
printf("\n");
}
return 0;
}字符数组与字符串
c
#include <stdio.h>
#include <string.h>
int main() {
// 字符数组定义
char name1[] = "张三";
char name2[20] = "李四";
char name3[10];
// 字符串输入输出
printf("请输入姓名: ");
scanf("%s", name3);
printf("你好, %s!\n", name3);
// 字符串处理函数
printf("name1长度: %zu\n", strlen(name1));
printf("name1和name2比较: %d\n", strcmp(name1, name2));
// 字符串复制
char copy[20];
strcpy(copy, name1);
printf("复制的字符串: %s\n", copy);
// 字符串连接
char full_name[50] = "姓名: ";
strcat(full_name, name1);
printf("%s\n", full_name);
return 0;
}3. 指针基础:C语言的灵魂
指针是C语言最强大也是最复杂的特性,它直接操作内存地址。
指针的基本概念
c
#include <stdio.h>
int main() {
int num = 42;
int* ptr; // 声明指针变量
// 指针赋值
ptr = # // &取地址运算符
// 指针解引用
printf("num的值: %d\n", num);
printf("num的地址: %p\n", &num);
printf("ptr的值(地址): %p\n", ptr);
printf("ptr指向的值: %d\n", *ptr); // *解引用运算符
// 通过指针修改值
*ptr = 100;
printf("修改后num的值: %d\n", num);
return 0;
}指针与数组
c
#include <stdio.h>
int main() {
int arr[5] = {10, 20, 30, 40, 50};
int* ptr = arr; // 数组名就是指向首元素的指针
// 通过数组下标访问
printf("数组元素: ");
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]);
}
printf("\n");
// 通过指针访问
printf("指针访问: ");
for (int i = 0; i < 5; i++) {
printf("%d ", *(ptr + i)); // 指针算术运算
}
printf("\n");
// 指针递增
printf("指针递增访问: ");
for (int i = 0; i < 5; i++) {
printf("%d ", *ptr);
ptr++; // 指针指向下一个元素
}
printf("\n");
return 0;
}指针与函数
c
#include <stdio.h>
// 通过指针交换两个数
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
// 函数返回指针
int* find_max(int arr[], int size) {
int* max_ptr = &arr[0];
for (int i = 1; i < size; i++) {
if (arr[i] > *max_ptr) {
max_ptr = &arr[i];
}
}
return max_ptr;
}
int main() {
int x = 10, y = 20;
printf("交换前: x = %d, y = %d\n", x, y);
swap(&x, &y);
printf("交换后: x = %d, y = %d\n", x, y);
int numbers[] = {3, 7, 1, 9, 5};
int* max_ptr = find_max(numbers, 5);
printf("数组最大值: %d\n", *max_ptr);
return 0;
}4. 结构体与共用体:自定义数据类型
结构体允许我们创建包含不同类型数据的复合数据类型。
结构体定义与使用
c
#include <stdio.h>
#include <string.h>
// 定义结构体
struct Student {
int id;
char name[50];
int age;
float score;
};
// 使用typedef简化结构体使用
typedef struct {
char title[100];
char author[50];
float price;
int pages;
} Book;
int main() {
// 结构体变量声明和初始化
struct Student student1 = {1001, "张三", 20, 85.5};
// 逐个成员初始化
struct Student student2;
student2.id = 1002;
strcpy(student2.name, "李四");
student2.age = 21;
student2.score = 92.0;
// 访问结构体成员
printf("学生信息:\n");
printf("ID: %d\n", student1.id);
printf("姓名: %s\n", student1.name);
printf("年龄: %d\n", student1.age);
printf("成绩: %.1f\n", student1.score);
// 结构体数组
Book library[3] = {
{"C程序设计", "谭浩强", 39.8, 400},
{"数据结构", "严蔚敏", 45.0, 380},
{"算法导论", "Thomas", 128.0, 800}
};
printf("\n图书馆藏书:\n");
for (int i = 0; i < 3; i++) {
printf("《%s》 - %s - ¥%.1f - %d页\n",
library[i].title, library[i].author,
library[i].price, library[i].pages);
}
return 0;
}结构体指针
c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int x, y;
} Point;
int main() {
// 结构体变量
Point p1 = {10, 20};
// 结构体指针
Point* ptr = &p1;
// 访问结构体成员(通过指针)
printf("通过指针访问: (%d, %d)\n", ptr->x, ptr->y);
printf("等价写法: (%d, %d)\n", (*ptr).x, (*ptr).y);
// 动态分配结构体内存
Point* dynamic_point = (Point*)malloc(sizeof(Point));
if (dynamic_point != NULL) {
dynamic_point->x = 30;
dynamic_point->y = 40;
printf("动态分配的点: (%d, %d)\n",
dynamic_point->x, dynamic_point->y);
free(dynamic_point);
}
return 0;
}共用体和枚举
c
#include <stdio.h>
// 共用体:多个成员共享同一内存空间
union Data {
int i;
float f;
char str[20];
};
// 枚举:定义命名常量
enum Color { RED, GREEN, BLUE };
enum Week { MONDAY = 1, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY };
int main() {
// 共用体使用
union Data data;
data.i = 10;
printf("data.i: %d\n", data.i);
data.f = 220.5;
printf("data.f: %f\n", data.f);
// 注意:此时data.i的值已经被覆盖
printf("data.i after f assignment: %d\n", data.i);
// 枚举使用
enum Color favorite_color = RED;
enum Week today = WEDNESDAY;
printf("最喜欢的颜色: %d\n", favorite_color);
printf("今天是星期: %d\n", today);
// 枚举与switch结合使用
switch (favorite_color) {
case RED:
printf("红色是热情的颜色\n");
break;
case GREEN:
printf("绿色是自然的颜色\n");
break;
case BLUE:
printf("蓝色是宁静的颜色\n");
break;
}
return 0;
}5. 实践项目
学生成绩管理系统
c
#include <stdio.h>
#include <string.h>
#define MAX_STUDENTS 100
typedef struct {
int id;
char name[50];
float chinese;
float math;
float english;
float average;
} Student;
// 计算平均分
void calculate_average(Student* student) {
student->average = (student->chinese + student->math + student->english) / 3.0;
}
// 添加学生
int add_student(Student students[], int count) {
if (count >= MAX_STUDENTS) {
printf("学生数量已达上限!\n");
return count;
}
Student new_student;
printf("请输入学生ID: ");
scanf("%d", &new_student.id);
printf("请输入学生姓名: ");
scanf("%s", new_student.name);
printf("请输入语文成绩: ");
scanf("%f", &new_student.chinese);
printf("请输入数学成绩: ");
scanf("%f", &new_student.math);
printf("请输入英语成绩: ");
scanf("%f", &new_student.english);
calculate_average(&new_student);
students[count] = new_student;
printf("学生添加成功!\n");
return count + 1;
}
// 显示所有学生
void display_students(Student students[], int count) {
if (count == 0) {
printf("暂无学生信息!\n");
return;
}
printf("\n%-5s %-10s %-8s %-8s %-8s %-8s\n",
"ID", "姓名", "语文", "数学", "英语", "平均分");
printf("--------------------------------------------------------\n");
for (int i = 0; i < count; i++) {
printf("%-5d %-10s %-8.1f %-8.1f %-8.1f %-8.1f\n",
students[i].id, students[i].name,
students[i].chinese, students[i].math,
students[i].english, students[i].average);
}
}
// 按平均分排序
void sort_by_average(Student students[], int count) {
for (int i = 0; i < count - 1; i++) {
for (int j = 0; j < count - 1 - i; j++) {
if (students[j].average < students[j + 1].average) {
Student temp = students[j];
students[j] = students[j + 1];
students[j + 1] = temp;
}
}
}
printf("按平均分排序完成!\n");
}
int main() {
Student students[MAX_STUDENTS];
int count = 0;
int choice;
while (1) {
printf("\n=== 学生成绩管理系统 ===\n");
printf("1. 添加学生\n");
printf("2. 显示所有学生\n");
printf("3. 按平均分排序\n");
printf("0. 退出\n");
printf("请选择: ");
scanf("%d", &choice);
switch (choice) {
case 1:
count = add_student(students, count);
break;
case 2:
display_students(students, count);
break;
case 3:
sort_by_average(students, count);
display_students(students, count);
break;
case 0:
printf("再见!\n");
return 0;
default:
printf("无效选择,请重新输入!\n");
}
}
return 0;
}字符串处理工具
c
#include <stdio.h>
#include <string.h>
#include <ctype.h>
// 字符串反转
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;
}
}
// 统计单词数
int count_words(const char* str) {
int count = 0;
int in_word = 0;
for (int i = 0; str[i] != '\0'; i++) {
if (isspace(str[i])) {
in_word = 0;
} else if (!in_word) {
in_word = 1;
count++;
}
}
return count;
}
// 字符串转大写
void to_uppercase(char* str) {
for (int i = 0; str[i] != '\0'; i++) {
str[i] = toupper(str[i]);
}
}
// 字符串转小写
void to_lowercase(char* str) {
for (int i = 0; str[i] != '\0'; i++) {
str[i] = tolower(str[i]);
}
}
int main() {
char text[200];
printf("请输入一段文本: ");
fgets(text, sizeof(text), stdin);
// 移除换行符
text[strcspn(text, "\n")] = '\0';
printf("原始文本: %s\n", text);
// 字符串反转
char reversed[200];
strcpy(reversed, text);
reverse_string(reversed);
printf("反转后: %s\n", reversed);
// 单词统计
printf("单词数: %d\n", count_words(text));
// 大小写转换
char upper[200], lower[200];
strcpy(upper, text);
strcpy(lower, text);
to_uppercase(upper);
to_lowercase(lower);
printf("大写: %s\n", upper);
printf("小写: %s\n", lower);
return 0;
}总结
本章节介绍了C语言的核心特性:
- 函数的定义、声明和参数传递
- 数组的定义、初始化和访问
- 指针的基本概念和使用方法
- 结构体、共用体和枚举的使用
- 实际项目中的应用示例
掌握这些核心特性后,你已经具备了编写复杂C程序的能力。函数让你能够模块化代码,数组和指针提供了高效的数据处理方式,结构体让你能够创建复杂的自定义数据类型。
在下一章节中,我们将学习C语言的高级特性,包括指针的高级应用、预处理命令、标准库的深入使用等。
记住,指针是C语言的核心难点,需要多加练习。多编写涉及指针的程序,理解内存布局,这样才能真正掌握C语言的精髓。结构体和函数的结合使用是构建大型程序的基础,熟练掌握这些概念将为你的C语言学习之路打下坚实的基础。