C语言学习笔记

C语言程序结构

hello world!

1
2
3
4
5
6
7
8
9
10
#include<stdio.h>   
/*预处理,头文件,引入外部函数(多行注释)。预处理即可在程序整体编译之前进行处理,包括验证编译平台等*/

int main() //主函数
{
printf("Hello World\n);
//调用函数输出字符串,函数是处理代码逻辑的最小单元。\n转义符号,下一段

return 0; //返回值
}

预处理

#define 宏名 字符串

类似一种预替换。

1
2
#define M(y) y*y+3*y  //带形参的宏定义
k=M(5); //宏调用

数据类型与格式化输出

基本数据类型

  • 整型 int
  • 字符型 char
  • 实型(单精、双精) float/double

构造数据类型

  • 枚举类型
  • 数组类型 // 数据类型 数组名称[长度];
  • 结构体类型
  • 共用体类型

指针类型

空类型四大类

格式化输出

printf("普通字符输出格式符", 输出项);

  • %d 整数
  • %c 单个字符
  • %s 字符串
  • %f 实数

常量

#define POCKETMONEY 10 //定义常量及常量值

定义方式为 #define 标识符 常量值

强制类型转换

(数据类型) (表达式)

(int)(x/2+y)

运算

常见表达式

运算表达式 说明
++a 先自加,再取值
a– 取值后自减
a+=5 a = a+5,即先加再赋值
== 判断符号
&&
! 非。如!(5>8)为真

位运算

运算符 说明 详细
& 按位与 9&5在内存中解为二进制,仅1与1为1
| 按位或 如上,有1则1
^ 按位异或 如上。不同为1,相同为0
~ 取反 取反
<< 左移 二进制左移,丢高位,低位补0
>> 右移 丢地位,高位按高位内容补

三目运算

表达式1 ? 表达式2 : 表达式3;

意为先判断表达式1的值是否为真,如果是真的话执行表达式2;如果是假的话执行表达式3

程序结构

判断体

if判断结构

1
2
3
4
5
6
7
8
9
10
11
12
if(表达式1)
{
执行代码块1;
if(表达式2)
{
执行代码块2;
}
}
else
{
执行代码块2;
}

switch语句

1
2
3
4
5
6
switch(){
case 常量表达式1: 执行代码1 break;
case 常量表达式2: 执行代码2 break;
case 常量表达式3: 执行代码3 break;
default: 执行代码n break; //其他常量
}

循环体

for循环

1
2
3
4
for(执行1;判断1;每次循环句)
{
执行代码块;
}

while循环

1
2
3
4
while(为“真”即循环)
{
执行代码块;
}

do-while循环

1
2
3
4
do
{
执行代码块;
}while(表达式); //至少执行一次。

break和continue循环中断

break跳出当前一层循环;
continue结束本次循环开始下次。

定义函数

函数声明及调用

1
2
3
4
5
6
7
8
[数据类型说明] 函数名称([参数]);  //类型用void
{
执行代码块;
return(表达式); //返回值
}

函数名([参数]);
//调用函数,形参只有使用时才分配内存,实参可以是变量、常量、表达式……

指针

指针的本质就是一个保存变量数据存储地址的变量,即内存编号,是一个以十六进制表示的整数,可以加减运算。

int a=10,*pa=&a;

&可用于取变量地址。

如果一个指针指向的是另外一个指针,我们就称它为二级指针,或者指向指针的指针。

int a=100,*p1=&a,*p2=&p1; //禁止套娃

结构体与枚举

结构体

结构体是存储不同类型数据的集合,又被称为复杂数据类型。作为一种数据类型,即可用于定义变量,甚至数组、指针。其数据在内存中如数组一样,也是连续的。

1
2
3
4
5
6
7
8
9
10
struct stu{  //stu是结构体名称
char *name; //姓名
int num; //学号
int age; //年龄
char group; //所在学习小组
float score; //成绩
};

struct stu stu1, stu2; //通过已定义结构体stu创建两个变量。
stu1.name = "Tom"; //结构体成员赋值。

共用体(很少用)

共用体与结构体类似,但占用的内存为相同【不好理解】,而不像结构体那样,生成的变量占用的内存互不干扰。

1
2
3
4
5
6
union data{
int n;
char ch;
double f;
};
union data a, b, c;

枚举

枚举默认给其中的内容按顺序赋值,也可以指定值。

enum typeName{ valueName1, valueName2, valueName3, ...... };

如:

enum week{ Mon = 1, Tues = 2, Wed = 3, Thurs = 4, Fri = 5, Sat = 6, Sun = 7 }

经典c语言程序

c语言2048(来自网络)

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
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
/*
* Copyright (C) 2014-2018 Judge Young
* E-mail: yjjtc@126.com
* Version: 2.0
* DateTime: 2018-08-01 23:18
*/

#include <time.h> /* 包含设定随机数种子所需要的time()函数 */
#include <stdio.h> /* 包含C的IO读写功能 */
#include <stdlib.h> /* 包含C标准库的功能 */

#ifdef _WIN32

/* 包含Windows平台相关函数,包括控制台界面清屏及光标设定等功能 */
#include <conio.h>
#include <windows.h>
#include <io.h>
#include <direct.h>
#include <Shlobj.h>

#else

/* 包含Linux平台相关函数,包括控制台界面清屏及光标设定等功能 */
#include <termio.h>
#include <unistd.h>
#include <bits/signum.h>
#include <signal.h>

#define KEY_CODE_UP 0x41
#define KEY_CODE_DOWN 0x42
#define KEY_CODE_LEFT 0x44
#define KEY_CODE_RIGHT 0x43
#define KEY_CODE_QUIT 0x71

struct termios old_config; /* linux下终端属性配置备份 */

#endif

static char config_path[4096] = {0}; /* 配置文件路径 */

static void init_game(); /* 初始化游戏 */
static void loop_game(); /* 游戏循环 */
static void reset_game(); /* 重置游戏 */
static void release_game(int signal); /* 释放游戏 */

static int read_keyboard();

static void move_left(); /* 左移 */
static void move_right(); /* 右移 */
static void move_up(); /* 上移 */
static void move_down(); /* 下移 */

static void add_rand_num(); /* 生成随机数,本程序中仅生成2或4,概率之比设为9:1 */
static void check_game_over(); /* 检测是否输掉游戏,设定游戏结束标志 */
static int get_null_count(); /* 获取游戏面板上空位置数量 */
static void clear_screen(); /* 清屏 */
static void refresh_show(); /* 刷新界面显示 */

static int board[4][4]; /* 游戏数字面板,抽象为二维数组 */
static int score; /* 游戏得分 */
static int best; /* 游戏最高分 */
static int if_need_add_num; /* 是否需要生成随机数标志,1表示需要,0表示不需要 */
static int if_game_over; /* 是否游戏结束标志,1表示游戏结束,0表示正常 */
static int if_prepare_exit; /* 是否准备退出游戏,1表示是,0表示否 */

/* main函数 函数定义 */
int main(int argc, char *argv[]) {
init_game();
loop_game();
release_game(0);
return 0;
}

/* 读取键盘 函数定义 */
int read_keyboard() {
#ifdef _WIN32
return _getch();
#else
int key_code;
if (read(0, &key_code, 1) < 0) {
return -1;
}
return key_code;
#endif
}

/* 开始游戏 函数定义 */
void loop_game() {
while (1) {
int cmd = read_keyboard(); /* 接收标准输入流字符命令 */

/* 判断是否准备退出游戏 */
if (if_prepare_exit) {
if (cmd == 'y' || cmd == 'Y') {
/* 退出游戏,清屏后退出 */
clear_screen();
return;
} else if (cmd == 'n' || cmd == 'N') {
/* 取消退出 */
if_prepare_exit = 0;
refresh_show();
continue;
} else {
continue;
}
}

/* 判断是否已经输掉游戏 */
if (if_game_over) {
if (cmd == 'y' || cmd == 'Y') {
/* 重玩游戏 */
reset_game();
continue;
} else if (cmd == 'n' || cmd == 'N') {
/* 退出游戏,清屏后退出 */
clear_screen();
return;
} else {
continue;
}
}

if_need_add_num = 0; /* 先设定不默认需要生成随机数,需要时再设定为1 */

#ifdef _WIN32
/* 命令解析,w,s,a,d字符代表上下左右命令,q代表退出 */
switch (cmd) {
case 'a':
case 75:move_left();
break;
case 's':
case 80:move_down();
break;
case 'w':
case 72:move_up();
break;
case 'd':
case 77:move_right();
break;
case 'q':
case 27:if_prepare_exit = 1;
break;
default:continue;
}
#else
/* 命令解析,上下左右箭头代表上下左右命令,q代表退出 */
switch (cmd) {
case 'a':
case KEY_CODE_LEFT:move_left();
break;
case 's':
case KEY_CODE_DOWN:move_down();
break;
case 'w':
case KEY_CODE_UP:move_up();
break;
case 'd':
case KEY_CODE_RIGHT:move_right();
break;
case KEY_CODE_QUIT:if_prepare_exit = 1;
break;
default:continue;
}
#endif
/* 打破得分纪录 */
if (score > best) {
best = score;
FILE *fp = fopen(config_path, "w");
if (fp) {
fwrite(&best, sizeof(best), 1, fp);
fclose(fp);
}
}

/* 默认为需要生成随机数时也同时需要刷新显示,反之亦然 */
if (if_need_add_num) {
add_rand_num();
refresh_show();
} else if (if_prepare_exit) {
refresh_show();
}
}
}

/* 重置游戏 函数定义 */
void reset_game() {
score = 0;
if_need_add_num = 1;
if_game_over = 0;
if_prepare_exit = 0;

/* 了解到游戏初始化时出现的两个数一定会有个2,所以先随机生成一个2,其他均为0 */
int n = rand() % 16;
int i;
for (i = 0; i < 4; ++i) {
int j;
for (j = 0; j < 4; ++j) {
board[i][j] = (n-- == 0 ? 2 : 0);
}
}

/* 前面已经生成了一个2,这里再生成一个随机的2或者4,概率之比9:1 */
add_rand_num();

/* 在这里刷新界面并显示的时候,界面上已经默认出现了两个数字,其他的都为空(值为0) */
refresh_show();
}

/* 生成随机数 函数定义 */
void add_rand_num() {
srand((unsigned int) time(0));
int n = rand() % get_null_count(); /* 确定在何处空位置生成随机数 */
int i;
for (i = 0; i < 4; ++i) {
int j;
for (j = 0; j < 4; ++j) {
/* 定位待生成的位置 */
if (board[i][j] == 0 && n-- == 0) {
board[i][j] = (rand() % 10 ? 2 : 4); /* 生成数字2或4,生成概率为9:1 */
return;
}
}
}
}

/* 获取空位置数量 函数定义 */
int get_null_count() {
int n = 0;
int i;
for (i = 0; i < 4; ++i) {
int j;
for (j = 0; j < 4; ++j) {
board[i][j] == 0 ? ++n : 1;
}
}
return n;
}

/* 检查游戏是否结束 函数定义 */
void check_game_over() {
int i;
for (i = 0; i < 4; ++i) {
int j;
for (j = 0; j < 3; ++j) {
/* 横向和纵向比较挨着的两个元素是否相等,若有相等则游戏不结束 */
if (board[i][j] == board[i][j + 1] || board[j][i] == board[j + 1][i]) {
if_game_over = 0;
return;
}
}
}
if_game_over = 1;
}

/*
* 如下四个函数,实现上下左右移动时数字面板的变化算法
* 左和右移动的本质一样,区别仅仅是列项的遍历方向相反
* 上和下移动的本质一样,区别仅仅是行项的遍历方向相反
* 左和上移动的本质也一样,区别仅仅是遍历时行和列互换
*/

/* 左移 函数定义 */
void move_left() {
/* 变量i用来遍历行项的下标,并且在移动时所有行相互独立,互不影响 */
int i;
for (i = 0; i < 4; ++i) {
/* 变量j为列下标,变量k为待比较(合并)项的下标,循环进入时k<j */
int j, k;
for (j = 1, k = 0; j < 4; ++j) {
if (board[i][j] > 0) /* 找出k后面第一个不为空的项,下标为j,之后分三种情况 */
{
if (board[i][k] == board[i][j]) {
/* 情况1:k项和j项相等,此时合并方块并计分 */
score += board[i][k++] *= 2;
board[i][j] = 0;
if_need_add_num = 1; /* 需要生成随机数和刷新界面 */
} else if (board[i][k] == 0) {
/* 情况2:k项为空,则把j项赋值给k项,相当于j方块移动到k方块 */
board[i][k] = board[i][j];
board[i][j] = 0;
if_need_add_num = 1;
} else {
/* 情况3:k项不为空,且和j项不相等,此时把j项赋值给k+1项,相当于移动到k+1的位置 */
board[i][++k] = board[i][j];
if (j != k) {
/* 判断j项和k项是否原先就挨在一起,若不是则把j项赋值为空(值为0) */
board[i][j] = 0;
if_need_add_num = 1;
}
}
}
}
}
}

/* 右移 函数定义 */
void move_right() {
/* 仿照左移操作,区别仅仅是j和k都反向遍历 */
int i;
for (i = 0; i < 4; ++i) {
int j, k;
for (j = 2, k = 3; j >= 0; --j) {
if (board[i][j] > 0) {
if (board[i][k] == board[i][j]) {
score += board[i][k--] *= 2;
board[i][j] = 0;
if_need_add_num = 1;
} else if (board[i][k] == 0) {
board[i][k] = board[i][j];
board[i][j] = 0;
if_need_add_num = 1;
} else {
board[i][--k] = board[i][j];
if (j != k) {
board[i][j] = 0;
if_need_add_num = 1;
}
}
}
}
}
}

/* 上移 函数定义 */
void move_up() {
/* 仿照左移操作,区别仅仅是行列互换后遍历 */
int i;
for (i = 0; i < 4; ++i) {
int j, k;
for (j = 1, k = 0; j < 4; ++j) {
if (board[j][i] > 0) {
if (board[k][i] == board[j][i]) {
score += board[k++][i] *= 2;
board[j][i] = 0;
if_need_add_num = 1;
} else if (board[k][i] == 0) {
board[k][i] = board[j][i];
board[j][i] = 0;
if_need_add_num = 1;
} else {
board[++k][i] = board[j][i];
if (j != k) {
board[j][i] = 0;
if_need_add_num = 1;
}
}
}
}
}
}

/* 下移 函数定义 */
void move_down() {
/* 仿照左移操作,区别仅仅是行列互换后遍历,且j和k都反向遍历 */
int i;
for (i = 0; i < 4; ++i) {
int j, k;
for (j = 2, k = 3; j >= 0; --j) {
if (board[j][i] > 0) {
if (board[k][i] == board[j][i]) {
score += board[k--][i] *= 2;
board[j][i] = 0;
if_need_add_num = 1;
} else if (board[k][i] == 0) {
board[k][i] = board[j][i];
board[j][i] = 0;
if_need_add_num = 1;
} else {
board[--k][i] = board[j][i];
if (j != k) {
board[j][i] = 0;
if_need_add_num = 1;
}
}
}
}
}
}

/* 清屏 */
void clear_screen() {
#ifdef _WIN32
/* 重设光标输出位置清屏可以减少闪烁,system("cls")为备用清屏命令,均为Windows平台相关*/
COORD pos = {0, 0};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), pos);
CONSOLE_CURSOR_INFO info = {1, 0};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
#else
printf("\033c"); /* linux下的清屏命令 */
printf("\033[?25l"); /* linux下的隐藏输入光标 */
#endif
}

/* 刷新界面 函数定义 */
void refresh_show() {
clear_screen();

printf("\n\n\n\n");
printf(" GAME: 2048 SCORE: %05d BEST: %06d\n", score, best);
printf(" --------------------------------------------------");

/* 绘制方格和数字 */
printf("\n\n ┌────┬────┬────┬────┐\n");
int i;
for (i = 0; i < 4; ++i) {
printf(" │");
int j;
for (j = 0; j < 4; ++j) {
if (board[i][j] != 0) {
if (board[i][j] < 10) {
printf(" %d │", board[i][j]);
} else if (board[i][j] < 100) {
printf(" %d │", board[i][j]);
} else if (board[i][j] < 1000) {
printf(" %d│", board[i][j]);
} else if (board[i][j] < 10000) {
printf("%4d│", board[i][j]);
} else {
int n = board[i][j];
int k;
for (k = 1; k < 20; ++k) {
n = n >> 1;
if (n == 1) {
printf("2^%02d│", k); /* 超过四位的数字用2的幂形式表示,如2^13形式 */
break;
}
}
}
} else printf(" │");
}

if (i < 3) {
printf("\n ├────┼────┼────┼────┤\n");
} else {
printf("\n └────┴────┴────┴────┘\n");
}
}
printf("\n");
printf(" --------------------------------------------------\n");
printf(" [W]:UP [S]:DOWN [A]:LEFT [D]:RIGHT [Q]:EXIT");

if (get_null_count() == 0) {
check_game_over();

/* 判断是否输掉游戏 */
if (if_game_over) {
printf("\r GAME OVER! TRY THE GAME AGAIN? [Y/N]: \b\b\b\b");
#ifdef _WIN32
CONSOLE_CURSOR_INFO info = {1, 1};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
#else
printf("\033[?25h"); /* linux下的显示输入光标 */
#endif
}
}

/* 判断是否准备退出游戏 */
if (if_prepare_exit) {
printf("\r DO YOU REALLY WANT TO QUIT THE GAME? [Y/N]: \b\b");
#ifdef _WIN32
CONSOLE_CURSOR_INFO info = {1, 1};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
#else
printf("\033[?25h"); /* linux下的显示输入光标 */
#endif
}

fflush(0); /* 刷新输出缓冲区 */
}

/* 初始化游戏 */
void init_game() {
#ifdef _WIN32
system("cls");

/* 获取游戏存档路径,Windows下放在C:\Users\UserName\AppData\Local\2048目录下 */
char m_lpszDefaultDir[MAX_PATH];
char szDocument[MAX_PATH] = {0};
memset(m_lpszDefaultDir, 0, _MAX_PATH);
LPITEMIDLIST pidl = NULL;
SHGetSpecialFolderLocation(NULL, CSIDL_LOCAL_APPDATA, &pidl);
if (pidl && SHGetPathFromIDList(pidl, szDocument)) {
GetShortPathName(szDocument, m_lpszDefaultDir, _MAX_PATH);
}
sprintf(config_path, "%s\\2048", m_lpszDefaultDir);
if (_access(config_path, 0) == -1) {
_mkdir(config_path);
}
sprintf(config_path, "%s\\2048\\2048.dat", m_lpszDefaultDir);
#else
/* 获取游戏存档路径,Linux下放在当前用户主目录下 */
sprintf(config_path, "%s/.2048", getenv("HOME"));

tcgetattr(0, &old_config); /* 获取终端属性 */
struct termios new_config = old_config; /* 创建新的终端属性 */
new_config.c_lflag &= ~ICANON; /* 设置非正规模式 */
new_config.c_lflag &= ~ECHO; /* 关闭输入回显 */
new_config.c_cc[VMIN] = 1; /* 设置非正规模式下的最小字符数 */
new_config.c_cc[VTIME] = 0; /* 设置非正规模式下的读延时 */
tcsetattr(0, TCSANOW, &new_config); /* 设置新的终端属性 */

printf("\033[?25l");

signal(SIGINT, release_game);
#endif

/* 读取游戏最高分数 */
FILE *fp = fopen(config_path, "r");
if (fp) {
fread(&best, sizeof(best), 1, fp);
fclose(fp);
} else {
best = 0;
fp = fopen(config_path, "w");
if (fp) {
fwrite(&best, sizeof(best), 1, fp);
fclose(fp);
}
}

reset_game();
}

/* 释放游戏 */
void release_game(int signal) {
#ifdef _WIN32
system("cls");
CONSOLE_CURSOR_INFO info = {1, 1};
SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &info);
#else
if (signal == SIGINT) {
printf("\n");
}
tcsetattr(0, TCSANOW, &old_config); /* 还原回旧的终端属性 */
printf("\033[?25h");
#endif
exit(0);
}

c语言学生信息管理系统(来自网络)

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
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h> /*I/O函数*/
#include<stdlib.h> /*其它说明*/
#include<string.h> /*字符串函数*/

#define LEN 15 /* 学号和姓名最大字符数,实际请更改*/
#define N 50 /* 最大学生人数,实际请更改*/

int k = 1, n = 0, m = 0;/* n代表当前记录的学生人数*/

//函数声明
void readfile();
void seek();
void modify();
void insert();
void del();
void display();
void save();
void menu();

//结构体保存学生信息
struct student{
char StudentId[LEN+1];
char StudentName[LEN+1];
int StudentAge;
char StudentSex;
float score[3];
}stu[N];

//主函数
int main()
{
while (k)
{
menu();
}
system("pause");
return 0;
}

//系统帮助函数
void help()
{
printf("\n0.欢迎使用系统帮助!\n");
printf("\n1.初次进入系统后,请先选择增加学生信息;\n");
printf("\n2.按照菜单提示键入数字代号;\n");
printf("\n3.增加学生信息后,切记保存;\n");
printf("\n4.谢谢您的使用!\n");
}

//刷新文件
int flush(){
char filename[LEN + 1];
int i = 0;
printf("请输入要刷新学生信息的文件名:\n");
scanf("%s", filename);
int j = 0;
FILE * fp;
if ((fp = fopen(filename, "r")) == NULL) return 0;
//从文件读取信息
while (fscanf(fp, "%s %s %s %d %d %d %d ", &stu[j].StudentId, &stu[j].StudentName, &stu[j].StudentAge, &stu[j].StudentSex, &stu[j].score[0], &stu[j].score[1], &stu[j].score[2]) == 7) {
j++;
}
n = j;
printf("刷新成功!!!");
return n;
}

//查找学生信息
void seek() /*查找*/
{
int i, item, flag;
char s1[21]; /* 以姓名和学号最长长度+1为准*/
printf("------------------\n");
printf("-----1.按学号查询-----\n");
printf("-----2.按姓名查询-----\n");
printf("-----3.退出本菜单-----\n");
printf("------------------\n");
while (1)
{
printf("请选择子菜单编号:");
scanf("%d", &item);
flag = 0;
switch (item)
{
case 1:
printf("请输入要查询的学生的学号:\n");
scanf("%s", s1);
for (i = 0; i<n; i++)
if (strcmp(s1,stu[i].StudentId) == 0)
{
flag = 1;
printf("学生学号\t学生姓名\t年龄\t性别\tC语言成绩\t高等数学\t大学英语成绩\n");
printf("--------------------------------------------------------------------\n");
printf("%s\t%s\t%d\t%6\t%.1f\t%.1f\t%.1f\n", stu[i].StudentId,stu[i].StudentName,stu[i].StudentAge,stu[i].StudentSex,stu[i].score[0],stu[i].score[1],stu[i].score[2]);
}
if (0 == flag)
printf("该学号不存在!\n"); break;
case 2:
printf("请输入要查询的学生的姓名:\n");
scanf("%s", s1);
for (i = 0; i<n; i++)
if (strcmp(stu[i].StudentName, s1) == 0)
{
flag = 1;
printf("学生学号\t学生姓名\t年龄\t性别\tC语言成绩\t高等数学\t大学英语成绩\n");
printf("--------------------------------------------------------------------\n");
printf("%s\t%s\t%d\t%c\t%.1f\t%.1f\t%.1f\n", stu[i].StudentId, stu[i].StudentName, stu[i].StudentAge, stu[i].StudentSex, stu[i].score[0], stu[i].score[1], stu[i].score[2]);
}
if (0 == flag)
printf("该姓名不存在!\n"); break;
case 3:return;
default:printf("请在1-3之间选择\n");
}
}
}

//修改学生信息
void modify() /*修改信息*/
{
int i, item, num = -1;
char sex1, s1[LEN + 1], s2[LEN + 1]; /* 以姓名和学号最长长度+1为准*/
float score1;
printf("请输入要要修改的学生的学号:\n");
scanf("%s", s1);
for (i = 0; i < n; i++){
if (strcmp(stu[i].StudentId, s1) == 0){/*比较字符串是否相等*/
num = i;
printf("------------------\n");
printf("1.修改姓名\n");
printf("2.修改年龄\n");
printf("3.修改性别\n");
printf("4.修改C语言成绩\n");
printf("5.修改高等数学成绩\n");
printf("6.修改大学英语成绩\n");
printf("7.退出本菜单\n");
printf("------------------\n");
while (1)
{
printf("请选择子菜单编号:");
scanf("%d", &item);
switch (item)
{
case 1:
printf("请输入新的姓名:\n");
scanf("%s", s2);
strcpy(stu[num].StudentName, s2);
break;
case 2:
printf("请输入新的年龄:\n");
scanf("%d", stu[num].StudentAge);
break;
case 3:
printf("请输入新的性别:\n");
scanf("%s", &sex1);
stu[i].StudentSex = sex1;
break;
case 4:
printf("请输入新的C语言成绩:\n");
scanf("%f", &score1);
stu[num].score[0] = score1;
break;
case 5:
printf("请输入新的高等数学成绩:\n");
scanf("%f", &score1);
stu[num].score[1] = score1;
break;
case 6:
printf("请输入新的大学英语成绩:\n");
scanf("%f", &score1);
stu[num].score[2] = score1;
break;
case 7: return;
default:printf("请在1-7之间选择\n");
}
}
printf("修改完毕!请及时保存!\n");
}
else{
printf("没有该学生学号!!!");
}
}
}

void sort()//按学号排序
{
int i, j, k, *p, *q, s;
char temp[LEN + 1], ctemp;
float ftemp;
for (i = 0; i<n - 1; i++)
{
for (j = n - 1; j>i; j--)
if (strcmp(stu[j - 1].StudentId, stu[j].StudentId)>0)
{
strcpy(temp, stu[j - 1].StudentId);
strcpy(stu[j - 1].StudentId, stu[j].StudentId);
strcpy(stu[j].StudentId, temp);
strcpy(temp, stu[j - 1].StudentName);
strcpy(stu[j - 1].StudentName, stu[j].StudentName);
strcpy(stu[j].StudentName, temp);
ctemp = stu[j - 1].StudentSex;
stu[j - 1].StudentSex = stu[j].StudentSex;
stu[j].StudentSex = ctemp;
p = &stu[j - 1].StudentAge;
q = &stu[j].StudentAge;
s = *q;
*q = *p;
*p = s;
for (k = 0; k<3; k++)
{
ftemp = stu[j - 1].score[k];
stu[j - 1].score[k] = stu[j].score[k];
stu[j].score[k] = ftemp;
}
}
}
}

//添加学生信息函数
void insert() /*插入函数*/
{
int i = n, j, flag;
printf("请输入待增加的学生数:\n");
scanf("%d", &m);
if (m > 0){
do
{
flag = 1;
while (flag)
{
flag = 0;
printf("请输入第%d位学生的学号:\n", i + 1);
scanf("%s", stu[i].StudentId);
for (j = 0; j < i; j++){
if (strcmp(stu[i].StudentId, stu[j].StudentId) == 0){
printf("该学号已存在,请重新输入!\n");
flag = 1;
break;
}
}
}
printf("请输入第%d 个学生的姓名:\n", i+1);
scanf("%s", stu[i].StudentName);
printf("请输入第%d 个学生的年龄:\n", i+1);
scanf("%d", &stu[i].StudentAge);
printf("请输入第%d 个学生的性别:\n", i+1);
scanf(" %c", &stu[i].StudentSex);
printf("请输入第%d 个学生的C语言成绩\n",i+1);
scanf("%f", &stu[i].score[0]);
printf("请输入第%d 个学生的高等数学成绩:\n", i+1);
scanf("%f", &stu[i].score[1]);
printf("请输入第%d 个学生的大学英语成绩:\n", i+1);
scanf("%f", &stu[i].score[2]);
if (0 == flag){
i++;
}
} while (i<n + m);
}
n += m;
printf("学生信息增加完毕!!!\n");
system("pause");
}

//删除学生信息函数
void del()
{
int i, j, flag = 0;
char s1[LEN + 1];
printf("请输入要删除学生的学号:\n");
scanf("%s", s1);
for (i = 0; i < n; i++){
if (strcpy(stu[i].StudentId, s1) == 0){
flag = 1;
//要删除学生后面的学生往前移一位
for (j = i; j < n - 1; j++){
stu[j] = stu[j + 1];
}
}
}
//查找失败
if (0 == flag){
printf("该学号不存在!!!\n");
}
if (1 == flag){
printf("删除成功!!!");
//删除成功,学生人数减1
n--;
}
system("pause");
}

//显示全部数据信息
void display()
{
int i;
printf("共有%d位学生的信息:\n", n);
if (0 != n)
{
printf("学生学号 \t学生姓名 \t年龄 \t性别 \tC语言成绩\t高等数学 \t大学英语成绩\n");
printf("--------------------------------------------------------------------\n");
for (i = 0; i<n; i++)
{
printf("%s \t%s \t%d \t%c \t%.1f\t%.1f \t%.1f\n", stu[i].StudentId, stu[i].StudentName, stu[i].StudentAge, stu[i].StudentSex, stu[i].score[0],stu[i].score[1],stu[i].score[2]);
}
}
system("pause");
}

void save(){
int i;
FILE *fp;
char filename[LEN + 1];
printf("请输入要保存的文件名:\n");
scanf("%s", filename);
fp = fopen(filename, "w");
for (i = 0; i < n; i++){
fprintf(fp, "%s%s%d%c%.lf%.lf%.lf\n", stu[i].StudentId, stu[i].StudentName, stu[i].StudentAge, stu[i].StudentSex,
stu[i].score[0], stu[i].score[1], stu[i].score[2]);
}
printf("保存成功!!!\n");
fclose(fp);
system("pause");
}

void menu()/* 界面*/
{
int num;
printf(" \n\n \n\n");
printf(" ******************************************************\n\n");
printf(" * 学生信息管理系统 *\n \n");
printf(" ******************************************************\n\n");
printf("*********************系统功能菜单************************* \n");
printf(" ---------------------- ---------------------- \n");
printf(" ********************************************* \n");
printf(" * 0.系统帮助及说明 * * 1.刷新学生信息 * \n");
printf(" ********************************************* \n");
printf(" * 2.查询学生信息 * * 3.修改学生信息 * \n");
printf(" ********************************************* \n");
printf(" * 4.增加学生信息 * * 5.按学号删除信息 * \n");
printf(" ********************************************* \n");
printf(" * 6.显示当前信息 * * 7.保存当前学生信息* \n");
printf(" ********************** ********************** \n");
printf(" * 8.退出系统 * \n");
printf(" ********************** \n");
printf(" ---------------------- ---------------------- \n");
printf("请选择菜单编号:");
scanf("%d", &num);
switch (num)
{
case 0:help(); break;
case 1:flush(); break;
case 2:seek(); break;
case 3:modify(); break;
case 4:insert(); break;
case 5:del(); break;
case 6:display(); break;
case 7:save(); break;
case 8:
k = 0;
printf("即将退出程序!\n");
break;
default:printf("请在0-8之间选择\n");
}
}
-------------本文结束感谢您的阅读-------------