C语言程序设计教程
第一章:初识C语言
1 什么是C语言?
C语言是一种通用的、过程式的编程语言,它由丹尼斯·里奇于1972年在贝尔实验室为开发Unix操作系统而设计,C语言以其高效、灵活和接近硬件的特性而闻名,是许多现代编程语言(如C++, Java, C#)的基础。
为什么学习C语言?
- 基础性强:理解C语言能让你更好地理解计算机内存、指针等底层概念。
- 性能高:C语言生成的程序运行效率高,广泛应用于操作系统、嵌入式系统、游戏引擎等领域。
- 影响力广:掌握了C,学习其他语言会事半功倍。
2 开发环境准备
在开始编写代码之前,你需要一个开发环境,通常包括两个部分:
- 文本编辑器:用来编写源代码(VS Code, Sublime Text, Notepad++)。
- 编译器:将你写的C代码(
.c文件)转换成计算机可以执行的程序(GCC, Clang, MSVC)。
对于初学者,我们推荐使用 集成开发环境,它将编辑器和编译器以及其他工具整合在一起,使用更方便。
- Windows平台:Visual Studio (社区版免费)、Dev-C++、MinGW-w64。
- macOS平台:Xcode、Clang (命令行工具)。
- Linux平台:GCC (通常已预装)、Code::Blocks。
3 你的第一个C程序:Hello, World!
这是一个传统,也是所有程序员的起点,让我们创建一个简单的程序,在屏幕上打印 "Hello, World!"。
步骤:
- 打开你的文本编辑器或IDE。
- 输入以下代码:
#include <stdio.h> // 引入标准输入输出库
int main() {
// printf 函数用于在屏幕上打印文本
printf("Hello, World!\n");
return 0; // main 函数的返回值,表示程序正常结束
}
代码解析:
#include <stdio.h>:这是一个预处理指令。stdio.h是一个标准库文件,包含了用于输入和输出的函数(如printf),没有它,我们就无法使用printf。int main():这是程序的主函数,每个C程序都必须有一个main函数,它是程序执行的起点。- 花括号用于定义一个代码块,这里是
main函数的主体。 printf("Hello, World!\n");:调用printf函数,将双引号内的字符串打印到控制台。\n是一个转义字符,表示“换行”。return 0;:main函数执行完毕后,返回一个整数值0给操作系统,表示程序成功运行,这是一种约定。
编译与运行:
- 将文件保存为
hello.c。 - 打开终端或命令提示符,进入文件所在的目录。
- 使用GCC编译器进行编译:
gcc hello.c -o hello - 运行生成的程序:
./hello(在Linux/macOS) 或hello.exe(在Windows)。
你将在屏幕上看到:
Hello, World!
第二章:基本数据类型与变量
1 关键字与标识符
- 关键字:C语言中具有特殊含义的单词,不能用作变量名。
int,float,if,else,for,while等。 - 标识符:程序员自己定义的名称,用于变量、函数等,命名规则:
- 只能由字母、数字、下划线
_组成。 - 不能以数字开头。
- 不能是关键字。
- 区分大小写(
myVar和myvar是两个不同的变量)。
- 只能由字母、数字、下划线
2 基本数据类型
C语言使用不同的数据类型来表示不同类型的数据。
| 类型 | 关键字 | 描述 | 示例 |
|---|---|---|---|
| 整型 | int |
用于存储整数(没有小数部分) | 10, -100, 0 |
| 浮点型 | float |
用于存储单精度浮点数(小数) | 14f, -0.5f |
| 双精度浮点型 | double |
用于存储双精度浮点数(比 float 更精确) |
1415926, -0.555 |
| 字符型 | char |
用于存储单个字符 | 'A', 'b', '1', |
3 变量与常量
变量:在程序运行期间,其值可以改变的量,它像一个带标签的盒子,用来存放数据。
声明变量:
int age; // 声明一个整型变量 age float price; // 声明一个单精度浮点型变量 price char grade; // 声明一个字符型变量 grade
初始化变量:
int age = 25; // 声明并初始化 float price = 19.99f; char grade = 'A';
赋值:
int score; score = 100; // 将值 100 赋给变量 score
常量:在程序运行期间,其值不能改变的量,使用 const 关键字声明。
const int MAX_AGE = 150; // MAX_AGE 的值不能被修改 // MAX_AGE = 160; // 这行代码会编译错误!
第三章:运算符与表达式
运算符用于对变量和值进行操作。
1 算术运算符
| 运算符 | 描述 | 示例 |
|---|---|---|
| 加法 | a + b |
|
| 减法 | a - b |
|
| 乘法 | a * b |
|
| 除法 | a / b (注意:整数除法会截断小数部分) |
|
| 取模(求余数) | a % b (仅适用于整数) |
|
| 自增 | a++ (a = a + 1) |
|
| 自减 | a-- (a = a - 1) |
示例:
int a = 10, b = 3;
printf("a + b = %d\n", a + b); // 输出: 13
printf("a - b = %d\n", a - b); // 输出: 7
printf("a * b = %d\n", a * b); // 输出: 30
printf("a / b = %d\n", a / b); // 输出: 3 (整数除法)
printf("a %% b = %d\n", a % b); // 输出: 1 (注意 %% 用于打印 %)
2 赋值运算符
, , , , , 等。
int x = 10; x += 5; // 等价于 x = x + 5; x 现在是 15
3 关系运算符
用于比较两个值,结果为 1 (真) 或 0 (假)。
| 运算符 | 描述 |
|---|---|
| 等于 | |
| 不等于 | |
> |
大于 |
< |
小于 |
>= |
大于等于 |
<= |
小于等于 |
示例:
int age = 18;
printf("%d\n", age >= 18); // 输出 1 (真)
printf("%d\n", age == 20); // 输出 0 (假)
4 逻辑运算符
用于连接多个关系表达式。
| 运算符 | 描述 | 示例 |
|---|---|---|
&& |
逻辑与 (AND) | (a > 5) && (b < 10) |
| 逻辑或 (OR) | (a > 5) \|\| (b < 10) |
|
| 逻辑非 (NOT) | !(a > 5) |
第四章:流程控制
1 条件语句
if-else 语句:根据条件执行不同的代码块。
#include <stdio.h>
int main() {
int score;
printf("请输入你的分数: ");
scanf("%d", &score); // 从键盘读取一个整数
if (score >= 90) {
printf("优秀!\n");
} else if (score >= 60) {
printf("及格,\n");
} else {
printf("不及格,\n");
}
return 0;
}
scanf 函数:用于从标准输入(键盘)读取数据。&score 是取 score 变量的地址,scanf 需要知道把读到的数据存放在哪里。
switch 语句:用于多路分支,基于一个表达式的值来选择执行哪个代码块。
#include <stdio.h>
int main() {
char grade;
printf("请输入你的等级 (A, B, C): ");
scanf(" %c", &grade); // 注意 %c 前的空格,用于跳过空白字符
switch (grade) {
case 'A':
printf("做得非常好!\n");
break; // break 必须有,否则会继续执行下一个 case
case 'B':
printf("做得不错,\n");
break;
case 'C':
printf("需要努力,\n");
break;
default: // 如果没有匹配的 case,则执行 default
printf("无效的等级,\n");
}
return 0;
}
2 循环语句
for 循环:在循环次数已知时最常用。
#include <stdio.h>
int main() {
// 打印 1 到 5
for (int i = 1; i <= 5; i++) {
printf("%d ", i);
}
// 输出: 1 2 3 4 5
return 0;
}
// for 循环结构: for (初始化; 条件; 更新)
while 循环:在循环次数未知,但循环条件已知时使用。
#include <stdio.h>
int main() {
int count = 1;
while (count <= 5) {
printf("%d ", count);
count++; // 别忘记更新条件,否则会无限循环
}
// 输出: 1 2 3 4 5
return 0;
}
do-while 循环:至少执行一次循环体,然后再检查条件。
#include <stdio.h>
int main() {
int number;
do {
printf("请输入一个大于 0 的数字: ");
scanf("%d", &number);
} while (number <= 0); // 如果输入的数字 <= 0,则继续循环
printf("你输入的数字是: %d\n", number);
return 0;
}
第五章:函数
函数是一块可以重复使用的代码块,它接收输入(参数),执行特定任务,并可以返回一个结果(返回值)。
1 函数的定义与调用
语法:
返回值类型 函数名(参数列表) {
// 函数体
return 返回值; // 如果返回值类型是 void,则可以省略 return
}
示例:计算两个数中的较大值
#include <stdio.h>
// 函数声明(可选,如果函数定义在 main 之后)
int max(int a, int b);
// 函数定义
int max(int a, int b) {
if (a > b) {
return a;
} else {
return b;
}
}
int main() {
int x = 10, y = 20;
int result = max(x, y); // 函数调用
printf("较大的数是: %d\n", result); // 输出: 较大的数是: 20
return 0;
}
main 函数也是一个函数,是程序的入口。
第六章:数组
数组是一种用于存储相同类型的多个元素的数据结构。
1 一维数组
声明与初始化:
int scores[5]; // 声明一个可以存放5个整数的数组
scores[0] = 95; // 数组索引从 0 开始
scores[1] = 88;
int numbers[5] = {1, 2, 3, 4, 5}; // 声明并初始化
int numbers2[] = {1, 2, 3}; // 编译器会自动确定数组大小为3
遍历数组(使用循环):
#include <stdio.h>
int main() {
int numbers[] = {10, 20, 30, 40, 50};
int size = sizeof(numbers) / sizeof(numbers[0]); // 计算数组元素个数
for (int i = 0; i < size; i++) {
printf("numbers[%d] = %d\n", i, numbers[i]);
}
return 0;
}
第七章:指针
指针是C语言的灵魂,也是初学者最难理解的部分。
1 什么是指针?
指针是一个变量,它存储的是另一个变量的内存地址。
&(取地址运算符):获取一个变量的内存地址。- *`` (解引用/间接寻址运算符)**:通过指针访问它所指向地址的值。
2 指针的基本用法
#include <stdio.h>
int main() {
int score = 100; // 一个整型变量
int *ptr_to_score; // 声明一个整型指针,用于存放整型变量的地址
ptr_to_score = &score; // 将 score 的地址赋给指针 ptr_to_score
printf("score 的值: %d\n", score); // 输出 100
printf("score 的地址: %p\n", &score); // 输出 score 的内存地址
printf("ptr_to_score 存储的地址: %p\n", ptr_to_score); // 输出与 &score 相同的地址
printf("通过指针访问的值: %d\n", *ptr_to_score); // 输出 100 (解引用)
// 通过指针修改值
*ptr_to_score = 95;
printf("修改后 score 的值: %d\n", score); // 输出 95
return 0;
}
为什么需要指针?
- 动态内存分配:在程序运行时申请内存。
- 高效传递大型数据:避免复制整个数据结构,只需传递其地址。
- 实现复杂数据结构:如链表、树、图等。
第八章:结构体
结构体允许你将不同类型的数据组合成一个单一的、自定义的类型。
1 定义和使用结构体
#include <stdio.h>
#include <string.h>
// 1. 定义一个结构体类型 Student
struct Student {
int id; // 学号
char name[50]; // 姓名
float score; // 分数
};
int main() {
// 2. 声明一个结构体变量
struct Student student1;
// 3. 访问和赋值结构体的成员
student1.id = 1001;
strcpy(student1.name, "张三"); // 使用 strcpy 函数复制字符串
student1.score = 92.5f;
// 4. 访问结构体成员并打印
printf("学号: %d\n", student1.id);
printf("姓名: %s\n", student1.name);
printf("分数: %.2f\n", student1.score); // %.2f 保留两位小数
return 0;
}
第九章:文件操作
C语言提供了丰富的文件操作函数,用于将数据持久化存储到硬盘上。
| 函数 | 描述 |
|---|---|
fopen() |
打开一个文件,返回一个 FILE* 指针 |
fclose() |
关闭一个文件 |
fgetc() |
从文件中读取一个字符 |
fputc() |
向文件中写入一个字符 |
fgets() |
从文件中读取一行 |
fputs() |
向文件中写入一行 |
fscanf() |
从文件中格式化读取 |
fprintf() |
向文件中格式化写入 |
示例:向文件写入并读取
#include <stdio.h>
int main() {
// --- 写入文件 ---
FILE *write_file = fopen("mydata.txt", "w"); // "w" 表示写入模式,如果文件不存在则创建
if (write_file == NULL) {
printf("无法打开文件!\n");
return 1;
}
fprintf(write_file, "Hello, File!\n");
fprintf(write_file, "This is a test.\n");
fclose(write_file); // 关闭文件
printf("数据已写入 mydata.txt\n");
// --- 读取文件 ---
FILE *read_file = fopen("mydata.txt", "r"); // "r" 表示读取模式
if (read_file == NULL) {
printf("无法打开文件!\n");
return 1;
}
char buffer[100];
printf("\n从文件读取的内容:\n");
while (fgets(buffer, sizeof(buffer), read_file) != NULL) {
printf("%s", buffer);
}
fclose(read_file);
return 0;
}
学习路径建议
- 基础语法:掌握前六章的内容,这是编写任何C程序的基础。
- 进阶核心:深入理解指针和内存管理(
malloc,free),这是从C新手到高手的必经之路。 - 实践项目:尝试做一些小项目来巩固所学知识,
- 学生成绩管理系统
- 简单的计算器
- 通讯录
- 文本文件处理工具
- 学习标准库:熟悉C标准库中的常用函数,如
string.h,stdlib.h,math.h等。 - 阅读优秀代码:阅读一些开源的、小型的C语言项目代码,学习他人的编程风格和技巧。
这份教程涵盖了C语言的核心概念,学习编程最重要的是多动手、多练习、多思考,祝你学习顺利!
