试听课

5/28/2022 C语言

讲师介绍:软件工程师,阿里云技术专家,《智能前端技术与实践》作者

考试科目:883 《C程序设计》(第五版)谭浩强,清华大学出版社

参考资料:《C程序设计(第五版)》谭浩强

# 前言

C语言是一门面向过程的计算机编程语言,我们可以在遵循C语言规范的情况下写出在嵌入式机器、超级计算机等计算平台上进行编译的C程序,它具有如下特点:

  • 语言简洁、紧凑,使用方便、灵活;

  • 运算符丰富(34种);

  • 数据类型丰富(C语言提供的数据类型包括:整型、浮点型、字符型、数组类型、指针类型、结构体类型和共用体类型);

  • 具有结构化的控制语句(如if...else语句、while语句、do...while语句、switch语句和for语句);

  • 语法限制不太严格,程序设计自由度大(如不对数组越界进行检查);

  • 允许直接访问物理地址,能进行位操作,能实现汇编语言的大部分功能,可以直接对硬件进行操作;

  • 程序可移植性好;

  • 生成目标代码的质量高,程序执行效率高;

C语言还被广泛应用在操作系统、文本编辑器、编译器、数据库、解释器等领域中。

本系列课程由浅入深,作者在前五章中详细介绍了C语言中的数据类型和三种基本结构,包括顺序、选择和循环;在第六章中,作者详细介绍了数组的相关知识,包括一维数组、二维数组和字符数组;在第七章中,作者详细介绍了函数的相关内容;在第八章中,作者详细介绍了C语言的精华「指针」,包括指向单个变量的指针、指向一维数组的指针、指向二维数组的指针、指向字符数组的指针、指向函数的指针以及指向指针的指针;在第九章中,作者详细介绍了结构体和共用体;第十章中,作者详细介绍了C语言中文件的相关操作。

# 目录

  • 课程时长:2小时

    • 第一章 程序设计和C语言
    • 第二章 算法—程序的灵魂
  • 课程时长:6小时

    • 第三章 最简单的C程序设计—顺序程序设计
    • 第四章 选择结构程序设计
    • 第五章 循环结构程序设计
  • 课程时长:9小时

    • 第六章 利用数组批量处理数据
    • 第七章 用函数实现模块化程序设计
    • 第八章 善于利用指针
  • 课程时长:6小时

    • 第九章 用户自己建立数据类型
    • 第十章 对文件的输入输出
  • 课程时长:9小时

    • 案例分享

# 获取课件

为了方便大家学习本课程,我已经将所有课件上传至百度网盘,如下图所示:

「注」:微信公众号后台回复「C语言课件」即可获取!

# 案例展示

  1. 求阶乘
#include<stdio.h>
int main(){
    int num,temp = 1;
    printf("请输入num数值:");
    scanf("%d",&num);
    if(num>=0){
        for(int i = 1;i <= num;i++){
            temp *= i;
        }
        printf("%d的阶乘值为:%d\n",num,temp);
    }else{
        printf("请重新输入num数值!");
    }
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
  1. 判断闰年
#include <stdio.h>
 int main(){
     printf("2000年~2500年中的闰年年份包括:\n");
     for(int a = 2000;a <= 2500;a++){
         if((a%4==0&&a%100!=0)||(a%400==0)){
            printf("%d\n",a);
         }
     }
     return 0;
 }
1
2
3
4
5
6
7
8
9
10
  1. 杨辉三角形
根据上图,我们可以获取一些规律:
  • 每个数等于它上方两数之和;
  • 每行数字左右对称,由1开始逐渐变大;
  • 第n行的数字有n项;
  • ...
#include <stdio.h>
#define NUM 5

int main(){
    int i = 0, j = 0;
    
    int array[NUM][NUM] = {0};
    int k = 0;

    for(i = 0; i < NUM; i++){
        for(j = 0; j <= i; j++){
            if(j == 0 || j == i){
                array[i][j] = 1;
            }
            else{
                array[i][j] = array[i-1][j-1]+ array[i-1][j];
            }
        }
    }

    for(i = 0; i < NUM; i++){
        for(k = 1; k < NUM - i; k++){
            printf("  ");
        }
        for(j = 0; j <= i; j++){
            printf("%3d ", array[i][j]);
        }
        printf("\n");
    }
    return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  1. 链表实战

为了让大家对本系列课程有更为充分的掌握,我在Bilibili上发布了一套实战课程,手把手教大家2小时内通过C语言编写一个学生管理系统,包括学生信息的增删改查等8个功能模块,其所用到的知识点包括指针、结构体、链表等!

➡️ 看视频

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stack>

using namespace std;
struct student{
  int num;//学号
  char name[20];//姓名
  int age;//年龄
  struct student *next;//指向下一个节点的指针
};

struct student *createList();//建立学生信息
void displayList(struct student *head);//按照建立顺序输出学生信息
struct student *reverseList(struct student *head);//与建立顺序相反,逆序顺序输出学生信息
struct student *deleteNodes(struct student *head);//删除某个学生信息
struct student *insertNodes(struct student *head);//插入某个学生的信息
void search_student_info(struct student *head);//查找对应学生信息
void modify_student_info(struct student *head);//修改学生信息
struct student *destroyList(struct student *head);//清空整个链表
struct student *head = NULL;

int main(){
  int select;//根据对应不同select的值,调用不同的函数
  do{
    printf("请输入select的值:");
    scanf("%d",&select);
    switch(select){
      case 1:
        head = createList();
        break;
      case 2:
        displayList(head);
        break;
      case 3:
        head = deleteNodes(head);
        break;
      case 4:
        head = insertNodes(head);
        break;
      case 5:
        search_student_info(head);
        break;
      case 6:
        modify_student_info(head);
        break;
      case 7:
        head = reverseList(head);
//        displayList(head);
        break;
      case 8:
        head = destroyList(head);
        break;
      
    }
  }while(select!=0);
  return 0;
}
//1. 建立学生信息
struct student *createList(){
  struct student *head;//头节点
  struct student *p1;//开辟新节点
  struct student *p2;//与p1连接
  int num1;
  char name1[20];
  int age1;
  head = NULL;
  int count = 1;
  
  printf("请输入第1个学生的学号、姓名、年龄(用空格分隔):");
  scanf("%d%s%d",&num1,&name1,&age1);
  while(age1>0){
    p1 = (struct student*)malloc(sizeof(struct student));
    p1->num = num1;
    strcpy(p1->name,name1);
    p1->age = age1;
    p1->next = NULL;
    if(head == NULL){
      head = p1;
    }else{
      p2->next = p1;
    }
    p2 = p1;
    printf("请输入第%d个学生的学号、姓名、年龄(用空格分隔):",++count);
    scanf("%d%s%d",&num1,&name1,&age1);
  }
  return head;
}

//2. 与建立顺序相同输出学生信息
void displayList(struct student *head){
  struct student *p;
  int n = 0;
  if(head!=NULL){
    printf("顺序输出链表中学生信息如下:\n");
    for(p=head;p!=NULL;p=p->next){
      printf("学号:%-6d 姓名:%-20s 年龄:%-6.1d\n",p->num,p->name,p->age);
      n++;
    }
    printf("学生总数:%d\n",n);
  }else{
    printf("空链表!\n");
  }
}

//3. 根据学号删除对应学生信息
struct student *deleteNodes(struct student *head){
  
  struct student *p1;
  struct student *p2;
  
  int num2;//要删除学生的学号
  printf("请输入要删除学生的学号:");
  scanf("%d",&num2);
  
  if(head == NULL){
    printf("链表为空\n");
    return head;
  }
  p2 = head;
  
  while(num2!=p2->num&&p2->next!=NULL){ //查找要删除的节点
    p1 = p2;
    p2 = p2->next;
  }
  
  if(num2 == p2->num){
    if(p2 == head){ //要删除的是头节点
      head = p2->next;
    }else{ //其他节点
      p1->next = p2->next;
    }
    free(p2);
    printf("删除了学号为%d的学生信息!\n",num2);
  }else{
    printf("该生不存在!\n");
  }
  return head;
}
  
//4. 根据学号的大小插入某个学生的信息
struct student *insertNodes(struct student *head){
  struct student *p;//待插入节点
  struct student *p1;//待插入节点的前驱节点
  struct student *p2;//待插入节点的后继节点
  p2 = head;
  p = (struct student *)malloc(sizeof(struct student));
  printf("请输入要加入学生的学号、姓名、年龄:");
  scanf("%d%s%d",&p->num,&p->name,&p->age);
  if(head == NULL){ //若为空链表,则相当于创建一个新节点
    head = p;
    p->next = NULL;
  }else{
    while(p->num > p2->num&&p2->next!=NULL){ //查找待插入的位置
      p1 = p2;
      p2 = p2->next;
    }
    if(p->num < p2->num){ //头节点和中间任意节点的插入
      if(p2 == head){ //头节点
        head = p;
        p->next = p2;
      }else{ // 中间任意节点
        p1->next = p;
        p->next = p2;
      }
    }else{//尾节点的插入
      p2->next = p;
      p->next = NULL;
    }
  }
   return head;
}

//5. 根据学号查找对应学生的其他信息
void search_student_info(struct student *head){
  struct student *p;
  int num;//要查找对应学生的学号信息
  printf("请输入要查找学生的学号:");
  scanf("%d",&num);
  p = head;
  //非空链表的情况下
  if(head != NULL){
    while(p->num!=num&&p->next!=NULL){
      p=p->next;
    }
    //不满足while循环的第一个条件
    if(p->num==num){
      printf("你所查找的学号为%d的学生信息如下:\n",num);
      printf("学号:%-6d 姓名:%-20s 年龄:%-6.1d\n",p->num,p->name,p->age);
    }else{
      //不满足while循环的最后一个条件
      printf("没有找到学号为%d的学生信息,请确认学号是否正确!\n",num);
    }
  }else{//空链表的情况
    printf("空链表!");
  }
}

//6. 根据学号修改学生信息
void modify_student_info(struct student *head){
  struct student *p;
  int num;
  char name[20];
  int age;
  printf("请输入您要修改学生的学号:");
  scanf("%d",&num);
  p = head;
  if(head!=NULL){
    while(p->num!=num&&p->next!=NULL){
      p = p->next;
    }
    if(p->num==num){
      printf("请输入您要更改后的信息:\n");
      scanf("%d%s%d",&num,&name,&age);
      p->num = num;
      strcpy(p->name,name);
      p->age = age;
    }else{
      printf("没有找到学号为%d的学生信息,请确认学号信息是否正确!\n");
    }
  }else{
    printf("空链表\n");
  } 
}
 
//7. 与建立顺序相反输出学生信息
struct student *reverseList(struct student *head){
  /*
    1. 借助递归
  */
  /*
  struct student *p;
  p = head;
  if(p!=NULL){
    reverseList(p->next);
    printf("学号:%-6d 姓名:%-20s 年龄:%-6.1d\n",p->num,p->name,p->age);
  }
  */
  
  /*
    2. 借助栈
  */
  struct student *p;
  p = head;
  stack<int> s;
  while(p!=NULL){
    s.push(p->num);
    p = p->next;
  }
  while(!s.empty()){
    p = head;
    while(s.top()!=p->num){
      p = p->next;
    }
    if(s.top()==p->num){
      printf("学号:%-6d 姓名:%-20s 年龄:%-6.1d\n",p->num,p->name,p->age);
    }
    s.pop();
  }
  return head;
   
  /*
    3. 改变单链表指针指向
    改变指针指向后,原链表也会被修改
  */
  
  /*
  struct student *pre;
  struct student *post;
  struct student *p;
  pre = NULL;
  post = NULL;
  while(head!=NULL){
    post = head->next;
    head->next = pre;
    pre = head;
    head = post;
  }
  return pre;
  */
  
}
 
//8. 清空整个链表
struct student *destroyList(struct student *head){
  struct student *p;
  p = head;
  if(p==NULL){
    printf("空链表!\n");
  }
  while(p!=NULL&&p->next!=NULL){
    p = p->next;
    free(p);
  }
  printf("信息删除完毕!\n");
  head = NULL;
  return head;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299