C 语言基础语法及数据类型
发布时间: 2024-03-06 03:45:25 阅读量: 40 订阅数: 25
# 1. C 语言入门介绍
## 1.1 什么是C语言
C语言是一种通用的、过程化的计算机编程语言,广泛用于系统软件、应用软件、驱动程序、网络/协议软件等领域。
## 1.2 C语言的历史和发展
C语言由美国计算机科学家丹尼斯·里奇在20世纪70年代初在贝尔实验室设计出来,是一种被广泛使用的编程语言。
## 1.3 为什么学习C语言
学习C语言对于理解计算机底层原理、编写高效的系统程序、提高编程能力等方面都具有重要意义。
## 1.4 环境搭建和第一个C程序
第一个C程序示例:
```c
#include <stdio.h>
int main() {
printf("Hello, World!\n");
return 0;
}
```
代码总结:以上程序是一个简单的C语言程序,包含了头文件引用、main函数和输出语句。可以通过编译器将其编译为可执行程序。
结果说明:运行该程序将在控制台输出"Hello, World!"的内容。
# 2. 基本语法与运算符
在这一章节,我们将深入探讨C语言中的基本语法和运算符的应用。
### 2.1 变量和常量
在C语言中,变量是用来存储数据的标识符,常量是固定的数值。我们可以通过以下代码来定义变量和常量:
```c
#include <stdio.h>
int main() {
int num1 = 10; // 定义整型变量 num1,并初始化为 10
const float PI = 3.14; // 定义一个常量 PI
printf("num1 的值为:%d\n", num1);
printf("PI 的值为:%f\n", PI);
return 0;
}
```
**代码场景说明:** 上述代码演示了如何定义一个整型变量 `num1` 和一个浮点型常量 `PI`,并通过 `printf` 函数分别输出它们的值。
**代码总结:** 变量用于存储数据,常量是值固定的标识符。在C语言中,使用 `int` 声明整型变量,使用 `const` 声明常量。
**结果说明:** 运行程序后,输出结果为:
```
num1 的值为:10
PI 的值为:3.140000
```
### 2.2 输入输出函数
C语言提供了输入函数 `scanf` 和输出函数 `printf` 用于与用户交互。以下是一个简单的示例:
```c
#include <stdio.h>
int main() {
int num;
printf("请输入一个整数:");
scanf("%d", &num); // 从用户输入中读取整数
printf("您输入的整数为:%d\n", num);
return 0;
}
```
**代码场景说明:** 以上代码中,首先提示用户输入一个整数,然后通过 `scanf` 函数读取用户输入的整数,并通过 `printf` 函数输出该整数。
**代码总结:** `scanf` 用于输入,`printf` 用于输出。需要注意的是,在 `scanf` 函数中,`&` 用于获取变量的地址。
**结果说明:** 运行程序后,用户会看到提示输入整数,输入后程序会将该整数打印出来。
### 2.3 运算符和表达式
在C语言中,有各种运算符和表达式,包括算术运算符、关系运算符、逻辑运算符等。下面是一个简单的示例:
```c
#include <stdio.h>
int main() {
int a = 10, b = 20;
int sum, sub, mul, div;
sum = a + b;
sub = a - b;
mul = a * b;
div = a / b;
printf("和:%d\n", sum);
printf("差:%d\n", sub);
printf("积:%d\n", mul);
printf("商:%d\n", div);
return 0;
}
```
**代码场景说明:** 上述代码展示了如何使用算术运算符计算两个变量的和、差、积和商,并通过 `printf` 打印结果。
**代码总结:** C语言中的运算符包括算术运算符(`+`, `-`, `*`, `/`)、关系运算符(`==`, `!=`, `<`, `>`, `<=`, `>=`)、逻辑运算符(`&&`, `||`)等。
**结果说明:** 运行程序后,会输出两个变量的和、差、积、商的计算结果。
### 2.4 控制语句:if、else、switch等
控制语句在C语言中用于控制程序的执行流程。常见的控制语句包括 `if`、`else` 和 `switch`。以下是一个简单的示例:
```c
#include <stdio.h>
int main() {
int num = 5;
if (num > 0) {
printf("%d 是正数\n", num);
} else if (num < 0) {
printf("%d 是负数\n", num);
} else {
printf("%d 是零\n", num);
}
return 0;
}
```
**代码场景说明:** 以上代码演示了如何使用 `if-else` 控制语句根据不同情况输出不同的信息。
**代码总结:** `if-else` 结构用于根据条件判断执行不同的代码块。`switch` 则用于多重条件的判断。
**结果说明:** 运行程序后,会输出变量 `num` 的情况,这里输出的是 `5 是正数`。
# 3. 数据类型和存储类
在本章中,我们将学习C语言中的数据类型和存储类相关的知识。数据类型是指变量所能存储的数据的类型,而存储类则决定了变量或函数的作用域和生命周期。这是C语言中非常重要的基础知识之一。
#### 3.1 基本数据类型
C语言中的基本数据类型包括整型、浮点型、字符型和空类型。我们可以使用关键字来声明不同类型的变量,例如`int`用于整型、`float`用于浮点型、`char`用于字符型。
```c
#include <stdio.h>
int main() {
int integerVar; // 声明整型变量
float floatVar; // 声明浮点型变量
char charVar; // 声明字符型变量
integerVar = 100; // 为整型变量赋值
floatVar = 3.14; // 为浮点型变量赋值
charVar = 'A'; // 为字符型变量赋值
printf("整型变量: %d\n", integerVar);
printf("浮点型变量: %f\n", floatVar);
printf("字符型变量: %c\n", charVar);
return 0;
}
```
**代码说明:** 上述代码演示了声明不同类型的变量,并对其赋值及打印输出的过程。
**运行结果:**
```
整型变量: 100
浮点型变量: 3.140000
字符型变量: A
```
#### 3.2 枚举、结构体和共用体
除了基本数据类型外,C语言还支持枚举、结构体和共用体这三种用户自定义的数据类型。枚举用于定义一些符号常量,结构体用于存储不同类型的数据,共用体则可存储不同类型的数据,但同一时间只能使用其中的一种数据类型。
```c
#include <stdio.h>
// 声明枚举类型
enum Weekday {Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday};
// 声明结构体类型
struct Student {
char name[20];
int age;
float score;
};
// 声明共用体类型
union Data {
int i;
float f;
char str[20];
};
int main() {
enum Weekday today = Wednesday;
printf("今天是星期%d\n", today + 1);
struct Student stu;
strcpy(stu.name, "John");
stu.age = 20;
stu.score = 89.5;
printf("学生姓名:%s,年龄:%d,成绩:%f\n", stu.name, stu.age, stu.score);
union Data data;
data.i = 10;
printf("整型数据:%d\n", data.i);
data.f = 3.14;
printf("浮点型数据:%f\n", data.f);
strcpy(data.str, "Hello");
printf("字符串:%s\n", data.str);
return 0;
}
```
**代码说明:** 上述代码展示了枚举、结构体和共用体的声明和使用。
**运行结果:**
```
今天是星期4
学生姓名:John,年龄:20,成绩:89.500000
整型数据:10
浮点型数据:3.140000
字符串:Hello
```
#### 3.3 存储类
在C语言中,存储类用于描述变量或函数的作用域和生命周期。常用的存储类包括`auto`、`extern`、`static`、`register`等。
```c
#include <stdio.h>
// 外部链接的全局变量
extern int externVar;
int main() {
// 自动变量,函数内的局部变量
auto int autoVar = 10;
// 静态变量,函数内的局部静态变量
static int staticVar = 20;
// 寄存器变量,存储在寄存器中,访问速度快
register int registerVar = 30;
printf("外部链接的全局变量: %d\n", externVar);
printf("自动变量: %d\n", autoVar);
printf("静态变量: %d\n", staticVar);
printf("寄存器变量: %d\n", registerVar);
return 0;
}
// 外部链接的全局变量定义
int externVar = 100;
```
**代码说明:** 上述代码演示了不同存储类的变量声明和使用以及外部链接的全局变量的定义与使用。
**运行结果:**
```
外部链接的全局变量: 100
自动变量: 10
静态变量: 20
寄存器变量: 30
```
#### 3.4 内存分配与指针概念
在C语言中,我们可以使用`malloc`和`free`函数进行动态内存分配和释放,并且指针在C语言中具有非常重要的作用,我们可以通过指针来访问和操作内存地址。
```c
#include <stdio.h>
#include <stdlib.h>
int main() {
int *ptr;
// 动态分配内存
ptr = (int *)malloc(sizeof(int));
if (ptr == NULL) {
printf("内存分配失败\n");
exit(1);
}
*ptr = 123; // 写入值
printf("动态分配的内存中的值:%d\n", *ptr);
// 释放内存
free(ptr);
return 0;
}
```
**代码说明:** 上述代码演示了使用`malloc`函数进行动态内存分配,并通过指针操作内存中的值,最后使用`free`函数释放内存。
**运行结果:**
```
动态分配的内存中的值:123
```
本章节内容涵盖了C语言中的数据类型和存储类的基本知识,以及枚举、结构体、共用体的使用,同时也介绍了动态内存分配和指针的概念。对于C语言初学者来说,掌握这些知识是非常重要的。
# 4. 函数与数组
### 4.1 函数定义与调用
在C语言中,函数是一段完成特定任务的代码块,可以被重复调用。函数的定义包括函数名、参数列表、返回类型和函数体。下面是一个简单的函数定义和调用的示例:
```c
#include <stdio.h>
// 函数定义
int add(int a, int b) {
return a + b;
}
int main() {
int result = add(3, 5); // 函数调用
printf("3 + 5 = %d\n", result);
return 0;
}
```
**代码说明:**
- 定义了一个名为add的函数,参数为a和b,返回类型为int,函数体内返回a和b的和。
- 在main函数中调用了add函数,并将返回值赋给result,然后打印出来。
### 4.2 递归函数
在C语言中,函数可以调用自身,这种函数称为递归函数。递归函数通常用于处理问题的分解和规模缩减,下面是一个简单的递归函数示例:
```c
#include <stdio.h>
// 递归函数求阶乘
int factorial(int n) {
if (n == 1) {
return 1;
} else {
return n * factorial(n-1);
}
}
int main() {
int result = factorial(5); // 调用递归函数
printf("5的阶乘 = %d\n", result);
return 0;
}
```
**代码说明:**
- 定义了一个名为factorial的递归函数,用于求解阶乘。
- 在main函数中调用了factorial函数,并将返回值打印出来。
### 4.3 数组概念和定义
数组是一组相同数据类型的元素集合,每个元素在内存中是连续存储的。下面是一个简单的数组定义和赋值的示例:
```c
#include <stdio.h>
int main() {
int arr[5]; // 定义一个包含5个元素的整型数组
arr[0] = 1; // 赋值
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;
for (int i = 0; i < 5; i++) {
printf("%d ", arr[i]); // 打印数组元素
}
return 0;
}
```
**代码说明:**
- 定义了一个包含5个整型元素的数组arr,并进行赋值操作。
- 使用for循环遍历数组,并将每个元素打印出来。
### 4.4 多维数组和指针数组
在C语言中,可以定义多维数组和指针数组。多维数组是元素为数组的数组,指针数组是元素为指针的数组。下面是一个简单的多维数组和指针数组的示例:
```c
#include <stdio.h>
int main() {
// 多维数组
int multiArr[2][3] = {{1, 2, 3}, {4, 5, 6}};
printf("%d\n", multiArr[1][2]); // 访问多维数组元素
// 指针数组
int a = 1, b = 2, c = 3;
int *ptrArr[3] = {&a, &b, &c}; // 定义包含3个指针的数组
for (int i = 0; i < 3; i++) {
printf("%d ", *ptrArr[i]); // 打印指针数组元素所指向的值
}
return 0;
}
```
**代码说明:**
- 定义了一个2行3列的多维数组multiArr,并访问了其中的一个元素。
- 定义了一个包含3个指针的数组ptrArr,利用for循环打印出指针数组元素所指向的值。
通过以上章节内容,读者可以了解C语言中的函数定义与调用,递归函数,数组的概念和定义,以及多维数组和指针数组的使用方法。
# 5. 字符串和指针
在本章中,我们将深入探讨C语言中的字符串和指针的相关知识,包括字符串处理函数、字符串数组、指针概念和运用,以及指针和数组的关系。
#### 5.1 字符串处理函数
字符串在C语言中以字符数组的形式进行存储和处理,常见的字符串处理函数包括:
```c
#include <stdio.h>
#include <string.h>
int main() {
char str1[] = "Hello";
char str2[] = "World";
char result[20];
// 字符串拼接
strcpy(result, str1); // 将str1拷贝到result
strcat(result, str2); // 将str2拼接到result后面
printf("拼接结果:%s\n", result);
// 字符串比较
if (strcmp(str1, str2) == 0) {
printf("str1 和 str2 相同\n");
} else {
printf("str1 和 str2 不同\n");
}
// 字符串长度
printf("str1 的长度:%d\n", strlen(str1));
return 0;
}
```
这段代码演示了常见的字符串处理函数,通过注释和输出结果可以清晰地看到每个函数的作用和结果。
#### 5.2 字符串数组
字符串数组是由一组字符串组成的数组,可以用于存储多个字符串。
```c
#include <stdio.h>
int main() {
char names[3][10] = {"Alice", "Bob", "Cathy"};
for (int i=0; i<3; i++) {
printf("Name %d: %s\n", i+1, names[i]);
}
return 0;
}
```
以上代码定义了一个包含3个字符串的字符串数组,并使用循环遍历输出了每个字符串。
#### 5.3 指针概念和运用
指针是C语言中的重要概念,可以用于操作内存地址和实现高效的数据处理。以下是一个简单的指针示例:
```c
#include <stdio.h>
int main() {
int num = 10;
int *ptr;
ptr = # // 指针ptr指向num的地址
printf("num 的值:%d\n", *ptr); // 通过指针访问 num 的值
return 0;
}
```
在这个示例中,我们定义了一个指针ptr,将其指向变量num的地址,并通过指针访问了num的值。
#### 5.4 指针和数组的关系
指针和数组在C语言中有着密切的关系,数组名本身就是一个指向数组首元素的指针。
```c
#include <stdio.h>
int main() {
int arr[5] = {1, 2, 3, 4, 5};
int *ptr = arr; // 数组名 arr 就是指向arr[0]的指针
for (int i=0; i<5; i++) {
printf("arr[%d] 的值:%d\n", i, *ptr);
ptr++; // 指针移动到下一个元素
}
return 0;
}
```
在这个示例中,我们通过指针遍历了数组的所有元素并输出了它们的值。
通过本章内容的学习,读者可以深入了解C语言中字符串和指针的相关知识,并且掌握了它们在实际开发中的应用。
# 6. 高级数据类型和文件操作
在本章中,我们将深入探讨C语言中的高级数据类型和文件操作。了解这些内容将有助于我们更灵活地处理数据和文件,提升编程效率。
### 6.1 动态内存分配
动态内存分配允许我们在程序运行时动态地分配内存空间,从而灵活地管理内存资源。C语言提供了以下几个函数来实现动态内存分配:
- **malloc()**:用于动态分配指定字节数的内存空间。
- **calloc()**:用于动态分配指定数量、指定大小的内存空间,并将其初始化为 0。
- **realloc()**:用于重新调整之前分配的内存空间的大小。
- **free()**:用于释放之前动态分配的内存空间。
下面是一个简单的示例,演示了如何使用`malloc()`和`free()`函数动态分配和释放内存:
```c
#include <stdio.h>
#include <stdlib.h>
int main() {
int n = 5;
int *ptr;
ptr = (int*)malloc(n * sizeof(int));
if (ptr == NULL) {
printf("内存分配失败\n");
return 1;
}
for (int i = 0; i < n; i++) {
ptr[i] = i + 1;
}
printf("动态分配的数组元素为:");
for (int i = 0; i < n; i++) {
printf("%d ", ptr[i]);
}
free(ptr);
return 0;
}
```
**运行结果:**
```
动态分配的数组元素为:1 2 3 4 5
```
**代码总结:** 在本示例中,我们使用`malloc()`函数动态分配了长度为5的整型数组,并对其进行了赋值和打印操作。最后,通过`free()`函数释放了动态分配的内存空间。
### 6.2 结构体指针和函数指针
结构体指针和函数指针是C语言中非常重要且常用的概念。结构体指针可以方便地访问结构体中的成员,函数指针则允许我们传递函数地址,实现函数的动态调用。
下面是一个示例,展示了结构体指针和函数指针的用法:
```c
#include <stdio.h>
// 定义一个结构体
struct Person {
char name[20];
int age;
};
// 定义一个函数,用于打印人员信息
void printInfo(struct Person *p) {
printf("姓名:%s,年龄:%d\n", p->name, p->age);
}
int main() {
// 初始化一个结构体变量
struct Person person = {"Alice", 25};
// 定义一个结构体指针,并指向person
struct Person *ptr = &person;
// 通过结构体指针调用函数
printInfo(ptr);
// 定义一个函数指针,并指向printInfo函数
void (*funcPtr)(struct Person *) = printInfo;
// 通过函数指针调用函数
funcPtr(ptr);
return 0;
}
```
**运行结果:**
```
姓名:Alice,年龄:25
姓名:Alice,年龄:25
```
**代码总结:** 在本示例中,我们定义了一个结构体`Person`,并在`main()`函数中使用结构体指针和函数指针分别访问结构体成员和调用函数。
### 6.3 文件操作函数
C语言提供了丰富的文件操作函数,可以轻松实现文件的读写、复制、删除等操作。常见的文件操作函数包括`fopen()`、`fclose()`、`fread()`、`fwrite()`等。
下面是一个简单的示例,演示了如何打开文件、写入数据并关闭文件:
```c
#include <stdio.h>
int main() {
FILE *fp;
char data[50] = "Hello, this is a file operation example.";
// 打开一个名为example.txt的文本文件,以写入模式
fp = fopen("example.txt", "w");
if (fp == NULL) {
printf("文件打开失败\n");
return 1;
}
// 写入数据到文件
fwrite(data, sizeof(char), sizeof(data), fp);
printf("数据已成功写入文件\n");
// 关闭文件
fclose(fp);
return 0;
}
```
**代码总结:** 在本示例中,我们使用`fopen()`函数打开一个名为`example.txt`的文本文件,并以写入模式写入数据。最后使用`fclose()`函数关闭文件。
### 6.4 二进制文件读写操作技巧
除了文本文件外,C语言也支持对二进制文件进行读写操作。通过二进制文件的读写,我们可以更加灵活地处理各种数据。
下面是一个示例,展示了如何将数据以二进制形式写入文件,并从文件中读取数据:
```c
#include <stdio.h>
struct Student {
char name[20];
int age;
};
int main() {
FILE *fp;
struct Student student1 = {"Bob", 22};
struct Student student2;
// 以二进制形式打开文件
fp = fopen("students.dat", "wb");
if (fp == NULL) {
printf("文件打开失败\n");
return 1;
}
// 将结构体以二进制形式写入文件
fwrite(&student1, sizeof(struct Student), 1, fp);
// 关闭文件
fclose(fp);
// 以二进制形式打开文件,用于读取数据
fp = fopen("students.dat", "rb");
// 从文件中读取数据到结构体
fread(&student2, sizeof(struct Student), 1, fp);
// 关闭文件
fclose(fp);
// 打印读取的数据
printf("姓名:%s,年龄:%d\n", student2.name, student2.age);
return 0;
}
```
**运行结果:**
```
姓名:Bob,年龄:22
```
**代码总结:** 在本示例中,我们定义了一个`Student`结构体,将其数据以二进制形式写入文件,并通过二进制形式读取文件中的数据。
0
0