C语言中级demo

Demo目录

  • 导语
  • 序章
  • 实战一:程序流程
    • 练习一:输入三个实数,判能否构成三角形
    • 练习二:简单四则运算
    • 练习三:猴子吃桃问题
    • 练习四:猴子吃桃拓展
  • 实战二:递归及应用
    • 练习一:递归猴子吃桃问题
    • 练习二:汉诺塔问题
  • 实战三:项目组织
  • 实战四:数组及应用
    • 练习一:约瑟夫问题(数组)
    • 练习二:字符串排序问题
    • 练习三:字符串分类统计
  • 实战五:结构体及应用
    • 练习一:学生信息登记管理(数组结构体)
    • 练习二:火车订票系统
  • 实战六:指针及其应用
    • 练习一:约瑟夫问题(指针版)
    • 练习二:学生信息登记管理(结构体+链表)
    • 练习三:贪吃蛇游戏
  • 实战七:文件操作及应用
    • 练习一:简单的计数器
    • 练习二:学生学籍管理系统(结构体+文件)
  • 结语

导语

这是C语言中级demo,它的难度会依次递增,但也不会用到复杂的算法。想对C语言语法更深入学习的朋友可以阅读,这次demo有一些经典的例子,比如:递归实现汉诺塔贪吃蛇小游戏指针的运用文件的运用(本来有数据库的demo的,但是一些原因,数据库没了),这些例子有一定难度,但不要怕,建议先自己思考,再看我的解法。总的来说,这次的demo的覆盖十分全面。需要源码的同学,我也在结语中给出了下载地址。

测试平台:Visual Studio 2017。(随着它版本更新,会出现有些库找不到的情况,可以自行百度解决

序章

首先简单说明以下,所有的demo分布在不同的文件中,最后是用一个字符界面的菜单通过输入数字来选择想使用的demo,同时有些demo使用到了外部库文件,这对于新手来说调试起来比较麻烦,但是可以当作一个挑战尝试正确运行出demo。具体的结构如下:
C语言中级demo_第1张图片
C语言中级demo_第2张图片
演示进入一次菜单:
C语言中级demo_第3张图片
演示进入二级菜单:
C语言中级demo_第4张图片

实战一:程序流程

本实战主要练习C语言的基本语法、变量使用等基础知识。有基础的可以跳过此实战。
导航菜单设计:

int Practice1DisplayMenu()
{
	system("cls");
	int key;
	printf("******************实战1功能菜单****************\n");
	printf("*****        1. 项目1->三角形相关判断     *****\n");
	printf("*****        2. 项目2->简单四则运算       *****\n");
	printf("*****        3. 项目3->猴子吃桃           *****\n");
	printf("*****        4. 项目4->其他拓展项目       *****\n");
	printf("*****        5.  返回上一级菜单           *****\n");
	printf("请输入功能号:");
	scanf("%d", &key);
	return key;
}

练习一:输入三个实数,判能否构成三角形

要求:

  1. 判断是否是三角形
  2. 判断是否是等腰三角形
  3. 判断断是否是等边三角形
  4. 计算三角形的面积
    实现:
#include "stdio.h"
#include "math.h"
#include "stdlib.h"
#include "conio.h"

int TriangleJudgmentDisplayMnue();

void practice1project1()
{
	    float a, b, c;
		printf("请输入三条边(以空格隔开):");
		scanf("%f%f%f", &a, &b, &c);
		if ((a + b) < c || (a + c) < b || (b + c) < a)
		{
			printf("不能构成三角形,,按任意键继续...\n");
			getch();
		}
	    else
		{
			printf("能构成三角形\n");
			//让c最大
			float temp;
			if (a>b)//找到a b中最大的
			{
				temp = b;
				b = a;
				a = temp;
			}
			if (b > c)//再找到b c中最大的
			{
				temp = c;
				c = b;
				b = temp;
			}
			int key;
			for (;;)
			{
				key = TriangleJudgmentDisplayMnue();
				switch (key)
				{
				case 1:
					if ((a*a + b * b) == c * c)
						printf("直角三角形,按任意键继续...\n");
					else
						printf("不是直角三角形,按任意键继续...\n");
					getch();
					break;
				case 2:
					if (a == b)
						printf("等腰三角形,按任意键继续...\n");
					else
						printf("不是等腰三角形,按任意键继续...\n");
					getch();
					break;
				case 3:
					if (a == b && a == c && b == c)
						printf("等边三角形,按任意键继续...\n");
					else
						printf("不是等边三角形,按任意键继续...\n");
					getch();
					break;
				case 4:
					temp = (a + b + c) / 2;
					printf("面积为:%f,按任意键继续...", sqrt(temp*(temp - a)*(temp - b)*(temp - c)));
					getch();
					break;
				case 5:
					key = 0;
					break;
				default:
					printf("输入错误!请按任意键继续.....");
					getch();
					break;
				}
				if (key == 0)
					break;
			}
		}
}
int TriangleJudgmentDisplayMnue()
{
	system("cls");
	int key;
	printf("******************实战1->项目1*****************\n");
	printf("*****        1. 判断是否是直角三角形      *****\n");
	printf("*****        2. 判断是否是等腰三角形      *****\n");
	printf("*****        3. 判断是否是等边三角形      *****\n");
	printf("*****        4. 计算三角形的面积          *****\n");
	printf("*****        5.  返回上一级菜单           *****\n");
	printf("请输入功能号:");
	scanf("%d", &key);
	return key;
}

练习二:简单四则运算

要求:

  1. 用程序实现一个简单的四则运算的功能,要求驶入类似a+b然后回车输出a+c=c的形式,a,b,c都是整数。
    实现:
#include "stdio.h"
#include "conio.h"
#include "stdlib.h"
#include "math.h"

void practice1project2()
{
	float a, b;
	char mm, y;
	printf("--------简单计算器-----------\n");
	do
	{
		setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区  
		printf("是否进行高级运算(y/n)");
		char x = getchar();
		if (x == 'n')
		{
			printf("请输入两个操作数和运算符:");
			scanf("%f%c%f", &a, &mm, &b);
			switch (mm)
			{
			case '+':
				printf("%f+%f=%.2f\n", a, b, a + b);
				break;
			case '-':
				printf("%f-%f=%.2f\n", a, b, a - b);
				break;
			case '*':
				printf("%f*%f=%.2f\n", a, b, a*b);
				break;
			case '/':
				if (b == 0)
				{
					printf("被除数不能为零\n");
					break;
				}
				printf("%f/%f=%.2f\n", a, b, a / b);
				break;
			default:
				printf("输入有错");
			}
			getchar();
			printf("按“y”继续,按其他键结束");
			scanf("%c", &y);
		}
		else
		{
			setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区
			printf("请选择你要进行的运算:");
			printf("开平方根按:s ;求倒:d ;幂次方:f ;");
			char xx = getchar();

			switch (xx)
			{
			case 's':
				printf("请输入被开方数:");
				scanf("答案为:%f", &a);
				b = sqrt(a);
				printf("%.4f", b);
				break;
			case 'd':
				printf("请输入要求倒的数:");
				scanf("答案为:%f", &a);
				if (0 == a)
				{
					printf("输入错误!");
					break;
				}
				b = 1 / a;
				printf("%.4f", b);
				break;
			case 'f':
				printf("请输入底和幂:");
				scanf("%f%f", &a, &b);
				printf("答案为:%.4f", pow(a, b));
				break;
			default:
				printf("输入错误!");
			}
			setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区  
			printf("按“y”继续,按其他键结束");
			y = getch();
			//setbuf(stdin, NULL);//使stdin输入流由默认缓冲区转为无缓冲区  
		}
	} while (y == 'y');
}

练习三:猴子吃桃问题

要求:

  1. 有一只猴子第一天摘下了若干个桃子,当即吃掉了一半,觉得不过瘾又多吃了一个;第二天又将剩下的桃子吃了一半,还不过瘾又多吃了一个;按照这个吃法每天都会吃掉前一天剩下的一半多一个。到了第10天,就剩下一个桃子了。问:这只猴子第一天摘了多少个桃子?

实现:

#include "stdio.h"
#include "conio.h"
#include "stdlib.h"
#include "math.h"


//猴子吃桃
void practice1project3()
{
	int mun=1;
	int day;
	printf("请输入第几天剩下一个桃子:");
	scanf("%d", &day);
	day--;
	for (; day > 0; day--)
	{
		mun = (mun + 1) * 2;
		printf("第%d天剩下%d个桃子\n", day, mun);
	}
	getch();
}

练习四:猴子吃桃拓展

要求

  1. 如果改变游戏玩法:猴子第一天摘了   x \ x  x个桃子,当即吃掉了些桃子,剩下 x \sqrt{x} x 个桃子还不过瘾,又多吃了一个,剩下   y \ y  y个;第二天又吃掉了一些,剩下 y \sqrt{y} y 个桃子,又多吃一个;按照这吃法,到了第十天只剩下了一个桃子。问:猴子第一天摘下了几个桃子?

实现:

#include "stdio.h"
#include "conio.h"
#include "stdlib.h"
#include "math.h"

int mc(long n, long i)
{
	if (n == i)
		return 1;
	else
		return (mc(n + 1, i) + 1)*(mc(n + 1, i) + 1);
}

void practice1project4()
{
	int i;
	printf("请输入吃完的时间:");
	scanf("%ld", &i);
	printf("猴子摘了%d个", mc(0, i));
	getch();
}

实战二:递归及应用

本实战主要让大家了解递归的思想刚开始可能会比较难,但是多练习就可以更加深入的理解。
这里给大家推荐一个我当时理解递归用到的视频。点这里(如果链接失效,请百度关键字:C程序设计进阶 北京大学)

导航菜单设计:

#include "stdio.h"
#include "stdlib.h"
#include "conio.h"

#include "practice2project1.h"
#include "practice2project2.h"
#include "practice2project3.h"
int Practice2DisplayMenu();
void practice2()
{
	int key;
	for (;;)
	{
		key = Practice2DisplayMenu();//打开实战1的额功能菜单
		switch (key)
		{
		case 1:
			practice2project1();
			break;
		case 2:
			practice2project2();
			break;
		case 3:
			practice2project3();
			break;
		case 4:
			key = 0;
			break;		
		default:
			printf("输入错误!请按任意键继续.....");
			getch();
			break;
		}
		if (key == 0)
			break;
	}

}
int Practice2DisplayMenu()
{
	system("cls");
	int key;
	printf("******************实战2功能菜单****************\n");
	printf("*****        1. 项目1->猴子吃桃问题       *****\n");
	printf("*****        2. 项目2->汉诺塔问题         *****\n");
	printf("*****        3. 项目3->拓展项目猴子吃桃   *****\n");
	printf("*****        4.  返回上一级菜单           *****\n");
	printf("请输入功能号:");
	scanf("%d", &key);
	return key;
}

练习一:递归猴子吃桃问题

要求

  1. 有一只猴子第一天摘下了若干个桃子,当即吃掉了一半,觉得不过瘾又多吃了一个;第二天又将剩下的桃子吃了一半,还不过瘾又多吃了一个;按照这个吃法每天都会吃掉前一天剩下的一半多一个。到了第10天,就剩下一个桃子了。问:这只猴子第一天摘了多少个桃子?(用递归编程思想实现)

实现:

#include "stdio.h"
#include "math.h"
#include "stdlib.h"
#include "conio.h"

int moeat(int n, int k)
{
	int sum;
	if (n == k)
		sum = 1;
	else
		sum = 2 * (moeat(n + 1, k) + 1);
	return sum;
}


int moeat2(int n, int k)
{
	if (n == k)
		return 1;
	else
		return (moeat2(n + 1, k) + 1)*(moeat2(n + 1, k) + 1);
}

void practice2project1()
{
	//猴子吃桃问题
	int k = 10, sum = 0;
	printf("请输入猴子吃桃的天数k=");
	scanf("%d", &k);
	sum = moeat(1, k);
	printf("猴子第一天摘桃子为=%d", sum);
	getch();
}

练习二:汉诺塔问题

tips:第一次看不懂没关系,代码记下来,回过头再看。
要求:

  1. 普通版:古代有个梵塔,塔内有A,B,C共三座,座A上有64个大小不等的盘子,大的在下面,小的在上面,有一个和尚想把这64个盘子从座A移动到座C,在移动过程中可以借用座A,座B,座C,但每次移动只允许移动一个盘子,并且不允许大盘放在小盘的上面。问:每一步改如何移动?总共要移动多少不?
  2. 加强版:如果改变游戏的玩法:不允许直接从最左(右)移动到最右(左),即每次移动一定是移动到中间或者从中间移除,也不允许大盘放到小盘上面。问题与普通版相同。

实现:

#include "stdio.h"
#include "math.h"
#include "stdlib.h"
#include "conio.h"

int n = 0;
//汉诺塔问题
void hanoi(int mun, char a, char b, char c)
{
	if (mun == 1)
		printf("step %3d:%c-->%c\n", ++n, a, c);
	else
	{
		hanoi(mun - 1, a, c, b);
		printf("Step %3d: %c--> %c\n", ++n, a, c);
		hanoi(mun - 1, b, a, c);
	}
}
void hanoi2(int m, char a, char b, char c)
{
	if (m == 1)
	{
		if (abs(a - c) == 1)
		{
			n++;
			printf("step %-3d:%c-->%c\n", n, a, c);
		}
		if ((abs(a - c) == 2))
		{
			n++;
			printf("step %-3d:%c-->%c\n", n, a, b);
			n++;
			printf("Step %-3d:%c-->%c\n", n, b, c);
		}
	}
	else
	{
		hanoi2(m - 1, a, b, c);
		hanoi2(1, a, c, b);
		hanoi2(m - 1, c, b, a);
		hanoi2(1, b, a, c);
		hanoi2(m - 1, a, b, c);
	}
}
void practice2project2()
{
	n = 0;
	printf("请输入盘子数:");
	int mun;
	scanf("%d", &mun);
	printf("请选择要解决那种汉诺塔问题?\n");
	printf("1.普通汉诺塔\n");
	printf("2.加强汉诺塔(每次只能移动到相邻的柱上)");
	int key;
	scanf("%d", &key);
	if (key == 1)
		hanoi(mun, 'A', 'B', 'C');
	else if (key == 2)
		hanoi2(mun, 'A', 'B', 'C');
	else
		printf("输入错误!");
	printf("请按任意键继续...");
	getch();
}

实战三:项目组织

将所有的这demo组织成一个菜单。

实战四:数组及应用

本实战主要练习语言的数组使用。有:约瑟夫环、字符串处理等。

导航菜单设计:

#include "stdio.h"
#include "stdlib.h"
#include "conio.h"

#include "practice4project1.h"
#include "practice4project2.h"
#include "practice4project3.h"
#include "practice4project4.h"
int Practice4DisplayMenu();
void practice4()
{
	int key;
	for (;;)
	{
		key = Practice4DisplayMenu();//打开实战4的额功能菜单
		switch (key)
		{
		case 1:
			practice4project1();
			break;
		case 2:
			practice4project2();
			break;
		case 3:
			practice4project3();
			break;
		case 4:
			practice4project4();
			getch();
			break;
		case 5:
			key = 0;
			break;
		default:
			printf("输入错误!请按任意键继续.....");
			getch();
			break;
		}
		if (key == 0)
			break;
	}

}
int Practice4DisplayMenu()
{
	system("cls");
	int key;
	printf("******************实战4功能菜单****************\n");
	printf("*****        1. 项目1->约瑟夫问题         *****\n");
	printf("*****        2. 项目2->字符串排序问题     *****\n");
	printf("*****        3. 项目3->字符串分类统计     *****\n");
	printf("*****        4. 项目4->拓展项目           *****\n");
	printf("*****        5.  返回上一级菜单           *****\n");
	printf("请输入功能号:");
	scanf("%d", &key);
	return key;
}

练习一:约瑟夫问题(数组)

(这个问题的来源很有趣,这里就不谈故事了,直接上题)
问题:N个人围成一圈,从第一个人开始报数,数到第k个人时那个人出队;下一个人再从1开始报数,依次循环,直到最后一个人。
实现:

#include "stdio.h"
#include "stdlib.h"
#include "conio.h"
#include "string.h"
#define N 5
#define LEN 10
 struct List
{
	char name[10];
	struct List *next;
};
 struct List2
 {
	 int num;
	 struct List2 *next;
 };

void JosephProblem1(char ary[][LEN], int);
void JosephProblem2();
void JosephProblem3();
int Practice4project1DisplayMenu();

void practice4project1()
{
	int key;
	for (;;)
	{
		system("cls");
		key = Practice4project1DisplayMenu();
		switch (key)
		{
		case 1:
			char name[N][LEN];
			int i, k;//k表示数到第K个人是即出队
			printf("请依次输入%d个人名(每个人名不超过10个字):\n", N);
			for (i = 0; i < N; i++)
				scanf("%s", &name[i]);
			printf("\n请输入数到第几个人退出:");
			scanf("%d", &k);
			JosephProblem1(name, k);
			getch();
			break;
		case 2:
			JosephProblem2();
			getch();
			break;
		case 3:
			JosephProblem3();
			getch();
			break;
		case 4:
			break;
		default:
			printf("输入错误!");
			break;
		}
		if (key == 4)
			break;
	}
}
int Practice4project1DisplayMenu()
{
	system("cls");
	int key;
	printf("******************实战4项目1功能菜单***********\n");
	printf("*****        1. 功能1->普通约瑟夫问题     *****\n");
	printf("*****        2. 功能2->链表约瑟夫问题     *****\n");
	printf("*****        3. 功能3->约瑟夫“密码问题” *****\n");
	printf("*****        4.  返回上一级菜单           *****\n");
	printf("请输入功能号:");
	scanf("%d", &key);
	return key;
}
void JosephProblem1(char ary[][LEN], int k)
{
	//普通约瑟夫
	int out = 0;//第几个人出局
	int couter = 0;//数到conter==n时退出
	int idx = -1;
	while (out < N)
	{
		idx++;
		if (idx == N)
			idx = 0;
		if (strcmp(ary[idx], "\0") == 0)
			continue;
		else
		{
			couter++;
			if (couter == k)
			{
				out++;
				printf("第个%d人退出:%s\n", out, ary[idx]);
				strcpy(ary[idx], "\0");
				couter = 0;
			}
		}
	}
}
void JosephProblem2()
{
		char k;
		int num = 0;
		struct List *p = NULL;
		struct List *q = NULL;
		struct List *head = NULL;
		do
		{
			if (head == NULL)
			{
				num++;
				head = (struct List*)malloc(sizeof(struct List));//初始化链表				
				printf("请输入人名:");
				fflush(stdin);
				scanf("%s", head->name);
				head->next = NULL;
				q = head;
			}
			else
			{
				num++;
				p= (struct List*)malloc(sizeof(struct List));
				p->next = NULL;
				q->next= p;//上一个节点连接到这个节点				
				printf("\n请输入人名:");
				fflush(stdin);
				scanf("%s", p->name);
				q = p;
			}
			printf("添加成功,现在有%d个人。按y/Y继续添加,按其他键完成:",num);
			k = getch();
		} while (k=='y'||k=='Y');
		q->next = head;
		struct List *star;
		star = head;
		int key = 0;
		printf("\n游戏开始:\n");
		while (num!=0)
		{
			if (star->name != "\0")
			{
				key++;
				if (key == 3)
				{
					num--;
					printf("\n%s被杀死了", star->name);
					strcpy(star->name, "\0");
					key = 0;
				}
				star = star->next;
			}
			else
				star = star->next;				
		}
}

void JosephProblem3()
{
	char k;
	int num = 0;
	struct List2 *p = NULL;
	struct List2 *q = NULL;
	struct List2 *head = NULL;
	do
	{
		if (head == NULL)
		{
			num++;
			head = (struct List2*)malloc(sizeof(struct List2));//初始化链表				
			printf("请输入数字:");
			fflush(stdin);
			scanf("%d", &head->num);
			head->next = NULL;
			q = head;
		}
		else
		{
			num++;
			p = (struct List2*)malloc(sizeof(struct List2));
			p->next = NULL;
			q->next = p;//上一个节点连接到这个节点				
			printf("\n请输入数字:");
			fflush(stdin);
			scanf("%d", &p->num);
			q = p;
		}
		printf("添加成功,现在有%d个数字。按y/Y继续添加,按其他键完成:", num);
		k = getch();
	} while (k == 'y' || k == 'Y');

	q->next = head;//循环链表
	struct List2 *star;
	star = head;
	int key = 0;
	int target = star->num;


	printf("\n密码是:\n");
	while (num != 0)
	{
		if (star->num !=-1)
		{
			key++;
			if (key == target)
			{
				num--;
				printf("%d  ", star->num);
				target = star->num;
				key = 0;
				star->num = -1;
				
			}
			star = star->next;
		}
		else
			star = star->next;
	}
}

练习二:字符串排序问题

要求:

  1. 任意输入N个单词,对这些单词进行排序

实现:

#include "stdio.h"
#include "stdlib.h"
#include "conio.h"
#include "string"

#define N 50 //单词数上限
#define M 26 //单词长度上限

int Practice4project2DisplayMenu();
void print(const char word[][M], int);
void stringsort1(char word[][M], int n);
void stringsort2(char word[][M], int n);
void stringsort3(char word[][M], int n);
void practice4project2()
{
	int key;
	for (;;)
	{
		system("cls");
		key = Practice4project2DisplayMenu();
		     
		char word[N][M];
		int m = M - 1;
		int count = N;
		int n = 0, i;
		switch (key)
		{
		case 1:
			//控制输入的单词数在1-50之间
			while (n < 1 || n>50)
			{
				printf("请输入你将要输入的单词数:(1-%d)\n", count);
				scanf("%d", &n);
			}
			printf("请输入%d个单词,以空格分开\n(单词长度不超过%d,若超出,程序会自动忽略超出部分)\n", n, m);
			for (i = 0; i < n; i++)
			{
				scanf("%s", &word[i]);
				word[i][M - 1] = '\0';
			}
			stringsort1(word, n);
			printf("排序结果为:\n");
			print(word, n);
			getch();
			break;
		case 2:
			//控制输入的单词数在1-50之间
			while (n < 1 || n>50)
			{
				printf("请输入你将要输入的单词数:(1-%d)\n", count);
				scanf("%d", &n);
			}
			printf("请输入%d个单词,以空格分开\n(单词长度不超过%d,若超出,程序会自动忽略超出部分)\n", n, m);
			for (i = 0; i < n; i++)
			{
				scanf("%s", &word[i]);
				word[i][M - 1] = '\0';
			}
			stringsort2(word, n);
			stringsort1(word, n);
			printf("排序结果为:\n");
			print(word, n);
			getch();
			break;
		case 3:
			//控制输入的单词数在1-50之间
			while (n < 1 || n>50)
			{
				printf("请输入你将要输入的单词数:(1-%d)\n", count);
				scanf("%d", &n);
			}
			printf("请输入%d个单词,以空格分开\n(单词长度不超过%d,若超出,程序会自动忽略超出部分)\n", n, m);
			for (i = 0; i < n; i++)
			{
				scanf("%s", &word[i]);
				word[i][M - 1] = '\0';
			}
			stringsort3(word, n);
			printf("排序结果为:\n");
			print(word, n);
			getch();
			break;
		case 4:
			;
		default:
			printf("输入错误!");
			break;

		}
		if (key == 4)
			break;
	}
}

int Practice4project2DisplayMenu()
{
	system("cls");
	int key;
	printf("******************实战4项目2功能菜单*************\n");
	printf("*****        1. 功能1->字符串排序问题       *****\n");
	printf("*****        2. 功能2->大小写不敏感字符排序 *****\n");
	printf("*****        3. 功能3->单词进行排序(非插入) *****\n");
	printf("*****        4.  返回上一级菜单             *****\n");
	printf("请输入功能号:");
	scanf("%d", &key);
	return key;
}

void stringsort1(char word[][M], int n)
{
	char key[M];
	int i, j;
	for (i = 1; i < n; i++)
	{
		strcpy(key, word[i]);
		j = i;
		while (j >= 1 && 1 == strcmp(word[j - 1], key))
		{
			strcpy(word[j], word[j - 1]);
			j--;
		}
		strcpy(word[j], key);
	}
}

void stringsort2(char word[][M],int n)
{
	char key[M];
	//大写换成小写
	for (int i = 0; i < n; i++) 
	{
		strcpy(key, word[i]);	
			for (int k = 0; word[i][k] != '\0'; k++)
				if (word[i][k] >= 'A'&&word[i][k] <= 'Z')
			                word[i][k] += 32;
	}
	int len;
	for (int i=0; i < n; i++)
	{
		len = strlen(word[i]);
		if (!(word[i][len - 1] >= 'a'&&word[i][len - 1] <= 'z'))
			word[i][len - 1] = '\0';
	}
}

void stringsort3(char word[][M], int n)
{
	char key[M];
	int i, j,c;
	for (i = 0; i < n - 1; i++)
	{
		strcpy(key, word[i]);
		for(j=i;j<n;j++)
			if (strcmp(key, word[j])>0)//key 大
			{
				c = j;
				strcpy(key, word[j]);
			}
		strcpy(word[c], word[i]);
		strcpy(word[i], key);
		
	}
}
void print(const char word[][M], int n)
{
	int i;
	for (i = 0; i < n; i++)
		printf("%s\n", word[i]);	
}

练习三:字符串分类统计

要求:

  1. 输入一字符串,统计其中的大写字母、小写字母、数字、空格和其他字符各多少个。

实现:

#include "stdio.h"
#include "stdlib.h"
#include "conio.h"
#include "string.h"

#define LEN 100
int lc = 0,uc = 0,d = 0, s = 0, o = 0;
void count(char ary[]);
//字符串统计
void practice4project3()
{
	char ary[LEN + 1];
	printf("请输入100个以内的任意字符\n");
	printf("程序将按大小写字母、数字、空格和其他字符进行统计。\n");
	printf("如果超出100个字符,程序将只对前100个字符进行统计:\n");
	char ch;
	while ((ch = getchar()) != EOF && ch != '\n')
	{
		;
	}
	gets_s(ary);
	puts(ary);
	count(ary);
	printf("小写字母:%d\n", lc);
	printf("大写字母:%d\n", uc);
	printf("0-9数字:%d\n", d);
	printf("空格:%d\n", s);
	printf("其他字符:%d\n", o);
	printf("按任意键退出...");
	getchar();

}
void count(char ary[])
{
	int i = 0;
	char c;
	while (ary[i])
	{
		c = ary[i];
		if (c >= '0'&& c <= '9')
			d++;
		else if (c >= 'a' && c <= 'z')
			lc++;
		else if (c >= 'A' &&c <= 'Z')
			uc++;
		else if (c == ' ')
			s++;
		else
			o++;
		i++;
	}
}

实战五:结构体及应用

本实战,你将学会如何使用结构体,构建复杂的数据类型。
(以后就不在添上导航菜单的代码,具体的可以在我的github上下载完成demo集合)

练习一:学生信息登记管理(数组结构体)

要求:
有学生成绩登记表如图:

学号 姓名 年龄 年龄 C语言 英语 高数 平均成绩
201210409601 刘子栋 19 92 85 86 87.7
201210409602 童雨嘉 19 88 72 82 80.7
201210409603 杨欣悦 19 78 93 74 81.7
201210409604 王子豪 19 67 77 75 73
··· ··· ··· ··· ··· ··· ··· ···

其中:学号是长度12的数字字符组成:姓名最大长度为10字符:性别最多允许4个字符:年龄为整数:成绩包含(C语言、英语、高数),均为整数,平均分允许一位小数。

  1. 现某班有N名学生(程序运行时N为确定的值)。
  2. 用户分别输入N个学生的信息。
  3. “平均成绩”项应该通过计算获得,不从键盘输入。
  4. 输入完成后,给出操作菜单让用户选择操作,菜单如下:
请选择排序字段
--------------------------------------------------------------
1.学号		2.姓名		3.性别		4.年龄
5.C语言		6.英语		7.高数		8.平均分
9.显示全部信息		0.退出程序
--------------------------------------------------------------
  1. 当用户正确选择排序字段后,进一步请用户选择排序方向,如下:
请选择排序方向:
--------------------------------------------------------------
1.升序		2.降序		0.退出程序
--------------------------------------------------------------
  1. 排序操作可以反复进行直到用户选择“退出程序”

实现:

#include "stdio.h"
#include "stdlib.h"
#include "conio.h"
#include "string.h"

#define N 3

typedef struct Subject
{
	float C_langeuage;
	float Engelish;
	float Math;

};

typedef struct Student
{
	int id;
	char name[10];
	char sex[4];
	int age;
	Subject subject;
	float averagescore;

};

int DisplayMenu(int n);
void InputStudent(Student stu[], Student stucpy[]);
void SortStudnet(Student stu[], Student stucpy[],int k ,int n);//k是按什么排序,n=1升序,n=0降序
void OutputStudent(Student stu[]);
void copy(Student *stu, Student *stucpy,int c,int num);
//子入口
void practice5project1()
{
	Student stu[N],stucpy[N];
	InputStudent(stu, stucpy);
	int key;
	int key2;
	while (true)
	{
		key = DisplayMenu(1);//那种排序
		if(key!=0&&key!=9)
		   key2 = DisplayMenu(2);//怎么排序
		switch (key)
		{
		case 1://学号
			Student temp;
			SortStudnet(stu, stucpy, key, key2);
			getch();
			break;
		case 2://姓名
			SortStudnet(stu, stucpy, key, key2);
			getch();
			break;
		case 3://性别
			SortStudnet(stu, stucpy, key, key2);
			getch();
			break;
		case 4://年龄
			SortStudnet(stu, stucpy, key, key2);
			getch();
			break;
		case 5://C语言
			SortStudnet(stu, stucpy, key, key2);
			getch();
			break;
		case 6://英语
			SortStudnet(stu, stucpy, key, key2);
			getch();
			break;
		case 7://高数
			SortStudnet(stu, stucpy, key, key2);
			getch();
			break;
		case 8://平均分
			break;
		case 9:
			OutputStudent(stu);
		case 0:
			break;
		default:
				printf("输入错误!");
		}
		if (key == 0)
			break;
	}
}

//显示菜单
int DisplayMenu(int n)
{
	system("cls");
	switch (n)
	{
	case 1:
		printf("-----------------------------------------------------------------\n");
		printf("请选择排序字段:\n");
		printf("1.学号             2.姓名                3.性别              4年龄\n");
		printf("5.C语言            6.英语                7.高数              8.平均分\n");
		printf("9.显示全部原始信息                       0.退出程序\n");
		printf("-----------------------------------------------------------------\n");
		break;
	case 2:
		printf("-----------------------------------------------------------------\n");
		printf("1.升序                   2.降序                     0.退出程序   \n");
		printf("-----------------------------------------------------------------\n");
		break;
	default:
		printf("输入错误!\n");
		break;
	}
	int k;
	scanf("%d", &k);
	return k;
}
//输入学生的信息
void InputStudent(Student stu[], Student stucpy[]){
	for (int i = 0; i < N; i++)
	{
		printf("请输入第%d/%d个学生信息:\n",i+1,N);
		printf("------------------------------------------------------------\n");
		printf("学号:");
		scanf("%d", &stu[i].id);
		printf("姓名(10个字符内):");
		scanf("%s", &stu[i].name);
		printf("性别(四个字符内):");
		scanf("%s",&stu[i].sex);
		printf("年龄(整数):");
		scanf("%d", &stu[i].age);
		printf("《C语言》成绩(整数):");
		scanf("%f", &stu[i].subject.C_langeuage);
		printf("《英语》成绩(整数):");
		scanf("%f", &stu[i].subject.Engelish);
		printf("《高数》成绩(整数):");
		scanf("%f", &stu[i].subject.Math);
		printf("------------------------------------------------------------\n");
		stu[i].averagescore = (stu[i].subject.C_langeuage + stu[i].subject.Engelish + stu[i].subject.Math) / 2;
	}
	stucpy = stu;
}
//输出学生的信息
void OutputStudent(Student stu[])
{
	printf("====================================================================================\n");
	printf("学生全部信息:\n");
	printf("学号      姓名    性别       年龄       C语言     英语      数学      平均分\n");
	for (int i = 0; i < N; i++)
	{
		printf("%-10d", stu[i].id);
		printf("%-10s", stu[i].name);
		printf("%-10s",stu[i].sex);
		printf("%-10d", stu[i].age);
		printf("%-10.2f", stu[i].subject.C_langeuage);
		printf("%-10.2f", stu[i].subject.Engelish);
		printf("%-10.2f", stu[i].subject.Math);
		printf("%-10.2f", stu[i].averagescore);
		putchar('\n');
	}
	getch();
}
//两个结构体复制
void copy(Student *stu, Student *stucpy,int c,int num)
{
	/*int id;
	char name[10];
	char sex[4];
	int age;
	Subject subject;
	float averagescore;*/

	stucpy[c].id = stucpy[num].id;
	stucpy[c].age = stu[num].age;
	stucpy[c].averagescore = stu[num].averagescore;
	
	stucpy[c].subject.C_langeuage = stu[num].subject.C_langeuage;
	stucpy[c].subject.Engelish = stu[num].subject.Engelish;
	stucpy[c].subject.Math = stu[num].subject.Math;
	
	strcpy(stucpy[c].name, stu[num].name);
	strcpy(stucpy[c].sex, stu[num].sex);

}
//根据选择排序
void SortStudnet(Student stu[], Student stucpy[],int k,int n)
{
	//注意排序方式n==1是升序,==0是降序
	Student temp;
	switch (k)
	{
	case 1://学号
	{
		//冒泡排序
		if (n == 1)
		{
			for (int i = 0; i<N; i++)
				for (int j = 0; j < N - 1 - i; j++)
					if (stu[j].id > stu[j + 1].id)
					{
						temp = stu[j];
						stu[j] = stu[j + 1];
						stu[j + 1] = temp;
					}
		}
		else//降序
		{
			for (int i = 0; i<N; i++)
				for (int j = 0; j < N - 1 - i; j++)
					if (stu[j].id < stu[j + 1].id)
					{
						temp = stu[j];
						stu[j] = stu[j + 1];
						stu[j + 1] = temp;
					}
		}
		//显示排序结果:
		OutputStudent(stu);
		break;
	}
	case 2://姓名
		if (n == 1)
		{
			for (int i = 0; i<N; i++)
				for (int j = 0; j < N - 1 - i; j++)
					if (strcmp(stu[j].name,stu[j+1].name)>0)
					{
						temp = stu[j];
						stu[j] = stu[j + 1];
						stu[j + 1] = temp;
					}
		}
		else

		{
			for (int i = 0; i<N; i++)
				for (int j = 0; j < N - 1 - i; j++)
					if (strcmp(stu[j].name, stu[j + 1].name)<0)
					{
						temp = stu[j];
						stu[j] = stu[j + 1];
						stu[j + 1] = temp;
					}
		}
		//显示排序结果:
		OutputStudent(stu);
		break;
	case 3://性别
		if (n == 1)
		{
			for (int i = 0; i<N; i++)
				for (int j = 0; j < N - 1 - i; j++)
					if (strcmp(stu[j].sex, stu[j + 1].sex)>0)
					{
						temp = stu[j];
						stu[j] = stu[j + 1];
						stu[j + 1] = temp;
					}
		}
		else

		{
			for (int i = 0; i<N; i++)
				for (int j = 0; j < N - 1 - i; j++)
					if (strcmp(stu[j].sex, stu[j + 1].sex)<0)
					{
						temp = stu[j];
						stu[j] = stu[j + 1];
						stu[j + 1] = temp;
					}
		}
		//显示排序结果:
		OutputStudent(stu);
		break;
	case 4://年龄
		if (n == 1)
		{
			for (int i = 0; i<N; i++)
				for (int j = 0; j < N - 1 - i; j++)
					if (stu[j].age > stu[j + 1].age)
					{
						temp = stu[j];
						stu[j] = stu[j + 1];
						stu[j + 1] = temp;
					}
		}
		else

		{
			for (int i = 0; i<N; i++)
				for (int j = 0; j < N - 1 - i; j++)
					if (stu[j].age < stu[j + 1].age)
					{
						temp = stu[j];
						stu[j] = stu[j + 1];
						stu[j + 1] = temp;
					}
		}
		//显示排序结果:
		OutputStudent(stu);
		break;
	case 5://C语言
		if (n == 1)
		{
			for (int i = 0; i<N; i++)
				for (int j = 0; j < N - 1 - i; j++)
					if (stu[j].subject.C_langeuage > stu[j + 1].subject.C_langeuage)
					{
						temp = stu[j];
						stu[j] = stu[j + 1];
						stu[j + 1] = temp;
					}
		}
		else
		{
			for (int i = 0; i<N; i++)
				for (int j = 0; j < N - 1 - i; j++)
					if (stu[j].subject.C_langeuage < stu[j + 1].subject.C_langeuage)
					{
						temp = stu[j];
						stu[j] = stu[j + 1];
						stu[j + 1] = temp;
					}
		}
		//显示排序结果:
		OutputStudent(stu);
		break;
	case 6://英语
		if (n == 1)
		{
			for (int i = 0; i<N; i++)
				for (int j = 0; j < N - 1 - i; j++)
					if (stu[j].subject.Engelish > stu[j + 1].subject.Engelish)
					{
						temp = stu[j];
						stu[j] = stu[j + 1];
						stu[j + 1] = temp;
					}
		}
		else
		{
			for (int i = 0; i<N; i++)
				for (int j = 0; j < N - 1 - i; j++)
					if (stu[j].subject.Engelish < stu[j + 1].subject.Engelish)
					{
						temp = stu[j];
						stu[j] = stu[j + 1];
						stu[j + 1] = temp;
					}
		}
		//显示排序结果:
		OutputStudent(stu);
		break;
	case 7://数学
		if (n == 1)
		{
			for (int i = 0; i<N; i++)
				for (int j = 0; j < N - 1 - i; j++)
					if (stu[j].subject.Engelish > stu[j + 1].subject.Engelish)
					{
						temp = stu[j];
						stu[j] = stu[j + 1];
						stu[j + 1] = temp;
					}
		}
		else
		{
			for (int i = 0; i<N; i++)
				for (int j = 0; j < N - 1 - i; j++)
					if (stu[j].subject.Math < stu[j + 1].subject.Math)
					{
						temp = stu[j];
						stu[j] = stu[j + 1];
						stu[j + 1] = temp;
					}
		}
		//显示排序结果:
		OutputStudent(stu);
		break;
	case 8://平均分
		if (n == 1)
		{
			for (int i = 0; i<N; i++)
				for (int j = 0; j < N - 1 - i; j++)
					if (stu[j].averagescore > stu[j + 1].averagescore)
					{
						temp = stu[j];
						stu[j] = stu[j + 1];
						stu[j + 1] = temp;
					}
		}
		else
		{
			for (int i = 0; i<N; i++)
				for (int j = 0; j < N - 1 - i; j++)
					if (stu[j].averagescore < stu[j + 1].averagescore)
					{
						temp = stu[j];
						stu[j] = stu[j + 1];
						stu[j + 1] = temp;
					}
		}
		//显示排序结果:
		OutputStudent(stu);
		break;
	default:
		break;
	}
}

练习二:火车订票系统

火车订票系统功能需求如下:

  1. 查询功能:查询车票信息、包括起始地、车次、余票和票价。
  2. 订票功能:车票预定。
  3. 修改功能:修改订票信息。
  4. 录入管理功能:输入车票的基本信息。
  5. 显示功能:将查询到的信息显示出来,供用户查看。

实现:
因为这个练习本身难度在于系统的逻辑结构,结构体运用在练习一已经展示了,避免冗余,就不再附上代码了,如果你想参考我的实现,建议下载源码自行查看。

实战六:指针及其应用

由于指针与内存、地址密切相关,所以也给很多初学者带来了很大的困难。这个实战通过几个简单例子,帮助你们理解和掌握C语言指针的基本应用。

练习一:约瑟夫问题(指针版)

在前面的实战中,已经涉及到了与瑟夫问题,这次我们用指针来解决它

实现:

#include "stdio.h"
#include "stdlib.h"
#include "conio.h"

struct List2
{
	int num;
	char name[11];
	struct List2 *next;
};

void JosephProblem3();
int p6p1Display();
void look(List2 *head,int num);//遍历
void restar(List2 *head,int num);//重新输入
void play(List2 *head,int num);
void practice6project1()
{
	char k;
	int num = 0;
	struct List2 *p = NULL;
	struct List2 *q = NULL;
	struct List2 *head = NULL;

	printf("开始:\n");
	do
	{
		if (head == NULL)
		{
			num++;
			head = (struct List2*)malloc(sizeof(struct List2));//初始化链表				
			printf("名字和密码:");
			fflush(stdin);
			scanf("%s%d", &head->name, &head->num);
			head->next = NULL;
			q = head;
		}
		else
		{
			num++;
			p = (struct List2*)malloc(sizeof(struct List2));
			p->next = NULL;
			q->next = p;//上一个节点连接到这个节点		
			printf("\n名字和密码:");
			fflush(stdin);
			scanf("%s%d", &p->name, &p->num);
			q = p;
		}
		printf("添加成功,现在有%d个人。按y/Y继续添加,按其他键完成:", num);
		k = getch();
	} while (k == 'y' || k == 'Y');
	q->next = head;//循环链表
	fflush(stdin);
	List2 * h1 = head;
	List2 * h2 = head;
	List2 * h3 = head;
	int key;
	while (true)
	{
		system("cls");
		key = p6p1Display();
		switch (key)
		{
		case 1:
			
			look(h1, num);
			break;
		case 2:
			
			restar(h2,num);
			break;
		case 3:
			
			play(h3,num);
			break;
		case 4:
			break;
		default:
			printf("输入错误!");
			getch();
			break;
		}
		if (key == 4)
			break;
	}
}


int p6p1Display()
{
	int k;
	printf("==========================================\n");
	printf("1.显示信息\n");
	printf("2.重新输入密码\n");
	printf("3.开始“数N退出”\n");
	printf("4.返回上一级菜单\n");
	printf("==========================================\n");
	printf("请选择:");
	scanf("%d", &k);
	return k;
}

void look(List2 *head,int num)//显示数据
{
	printf("数据如下:\n");
	for (int i = 0; i < num; i++)
	{
		printf("%s\t%d\n", head->name, head->num);
		head = head->next;
	}
	getch();
}

void restar(List2 *head,int num)//重新输入密码
{
	printf("开始重新输入:\n");
	printf("===============================================\n");
	for (int i = 0; i < num; i++)
	{
		printf("%s\t", head->name);
		scanf("%d", &head->num);
		head = head->next;
	}
	printf("输入完成!");
	getch();
}



void play(List2 *head,int num)//开始游戏
{
	char k;
	struct List2 *star;
	star = head;
	int key = 0;
	int target = star->num;


	printf("\n游戏开始:\n");
	while (num != 0)
	{
		if (star->num != -1)
		{
			key++;
			if (key == target)
			{
				num--;
				printf("%s\t%d\n", star->name, star->num);
				target = star->num;
				key = 0;
				star->num = -1;

			}
			star = star->next;
		}
		else
			star = star->next;
	}
	getch();
}

练习二:学生信息登记管理(结构体+链表)

在前面我们已经讨论了这问题,现在我们用更加符合现实的情况来实现这个练习,也就是:在程序运行前学生人数时不确定的,所以数组这个方法就不再适用了。通过这个练习你可以知道指针的强大之处。
实现:

#include "stdio.h"
#include "stdlib.h"
#include "conio.h"
#include "string.h"
int num=0;
int key2;//怎么排序
//数据定义
typedef struct data
{
	char id[13];
	char name[11];
	char sex[5];
	int old;
	int C_Language;
	int English;
	int Math;
	float average;
};
typedef struct Student
{
	data student;
	Student *prev;
	Student *next;
};

Student *start();//初始化链表
int p6Display(int n);//菜单
void show1(Student *head);//原始数据展示
void show2(data target[]);//排序顺序显示

void sort1(Student *head);
void sort2(Student *head);
void sort3(Student *head);
void sort4(Student *head);
void sort5(Student *head);
void sort6(Student *head);
void sort7(Student *head);
void sort8(Student *head);


void practice6project2()
{
	Student  *head=start();
	int key1;//1是一级菜单  2是二级菜单
	while (true)
	{
		key1= p6Display(1);
		if(key1!=9&&key1!=0)
		    key2= p6Display(2);
		switch (key1)
		{
		case 1:
			sort1(head);
			break;
		case 2:
			sort2(head);
			break;
		case 3:
			sort3(head);
			break;
		case 4:
			sort4(head);
			getch();
			break;
		case 5:
			sort5(head);
			break;
		case 6:
			sort6(head);
			break;
		case 7:
			sort7(head);
			break;
		case 8:
			sort8(head);
			break;
		case 9:
			show1(head);
			break;
		case 0:
			break;
		default:
			printf("输入错误!");
			break;
		}
		if (key1 == 0)
			break;
	}
}

//初始化链表
Student *start()
{
	Student *head=NULL;
	Student *p = NULL;
	Student *q = NULL;
	char k;
	printf("请输入学生信息:");
	do
	{
		if (head == NULL)
		{
			num++;
			head = (Student*)malloc(sizeof(Student));
			printf("请添加一下信息:");
			printf("学号:");
			scanf("%s", &head->student.id);
			printf("姓名:");
			scanf("%s", &head->student.name);
			printf("性别:");
			scanf("%s", &head->student.sex);
			printf("年龄:");
			scanf("%d", &head->student.old);
			printf("C语言:");
			scanf("%d", &head->student.C_Language);
			printf("英语:");
			scanf("%d", &head->student.English);
			printf("数学:");
			scanf("%d", &head->student.Math);
			head->student.average = (head->student.Math + head->student.English + head->student.C_Language)/3;
			head->next = NULL;
			head->prev = NULL;
			q = head;
		}
		else
		{
			num++;
			p= (Student*)malloc(sizeof(Student));
			printf("\n请添加一下信息:");
			printf("学号:");
			scanf("%s", &p->student.id);
			printf("姓名:");
			scanf("%s", &p->student.name);
			printf("性别:");
			scanf("%s", &p->student.sex);
			printf("年龄:");
			scanf("%d", &p->student.old);
			printf("C语言:");
			scanf("%d", &p->student.C_Language);
			printf("英语:");
			scanf("%d", &p->student.English);
			printf("数学:");
			scanf("%d", &p->student.Math);
			p->student.average = (p->student.Math + p->student.English + p->student.C_Language)/3;
			//完成节点链接
			p->prev = q;//这个节点指向上个节点
			q->next = p;//上个节点指向这个节点
			q = p;
		}
		fflush(stdin);
		printf("添加成功!现在有%d个人。按y/Y继续添加,按其他键完成:",num);
		k = getch();
	} while (k == 'y' || k == 'Y');
	return head;
}

//菜单
int p6Display(int n)
{
	int key;
	system("cls");
	switch (n)
	{
	case 1:
	{
		printf("\n");
		printf("选择排序方式:\n");
		printf("-----------------------------------------------------------------\n");
		printf("1.学号\t2.姓名\t3.性别\t4.年龄\n");
		printf("5.C语言\t6.英语\t7.高数\t8.平均分\n");
		printf("9.显示原始数据\t0.返回上一级菜单\n");
		printf("-----------------------------------------------------------------\n");
		break;
	}
	case 2:
	{
		printf("\n");
		printf("-----------------------------------------------------------------\n");
		printf("1.升序\t\t2.降序\t\t0.返回上一级菜单\n");
		printf("-----------------------------------------------------------------\n");
	}
	default:
		break;
	}
	scanf("%d", &key);
	return key;
}

//显示原始数据
void show1(Student *head)
{
	Student * start = head;
	printf("学号\t姓名\t性别\t年龄\tC语言\t英语\t高数\t平均分\n");
		for (int i = 0; i <num; i++)
		{
			printf("%-8s%-8s%-8s%-8d%-8d%-8d%-8d%-8f\n", start->student.id, start->student.name,
				start->student.sex, start->student.old, start->student.C_Language,
				start->student.English, start->student.Math, start->student.average);
			start = start->next;
		}
	getch();
}

//显示排序后的数据
void show2(data target[])
{
	printf("学号\t姓名\t性别\t年龄\tC语言\t英语\t高数\t平均分\n");
	if (key2 == 1)
		for (int i = 0; i < num; i++)
		{
			printf("%-8s%-8s%-8s%-8d%-8d%-8d%-8d%-8f\n", target[i].id, target[i].name,
				target[i].sex, target[i].old, target[i].C_Language, target[i].English,
				target[i].Math, target[i].average);
		}
	else
		for (int i = num-1; i >=0; i--)
		{
			printf("%-8s%-8s%-8s%-8d%-8d%-8d%-8d%-8f\n", target[i].id, target[i].name,
				target[i].sex, target[i].old, target[i].C_Language, target[i].English,
				target[i].Math, target[i].average);
		}
	getch();
}

//学号
void sort1(Student *head)
{
	Student * start = head;
	data *target = (data*)malloc(sizeof(data)*num);
	data temp;
	for (int i = 0; i < num; i++)
	{
		target[i] = start->student;
		start = start->next;
	}
	for(int i=0;i<num;i++)
		for (int j = 0; j < num - 1 - i; j++)
			if (target[j].id > target[j + 1].id)
			{
				temp = target[j];
				target[j] = target[j + 1];
				target[j + 1] = temp;
			}
	show2(target);//显示数据	
	free(target);
}

//姓名
void sort2(Student *head)
{
	Student * start = head;
	data *target = (data*)malloc(sizeof(data)*num);
	data temp;
	for (int i = 0; i < num; i++)
	{
		target[i] = start->student;
		start = start->next;
	}
	for (int i = 0; i<num; i++)
		for (int j = 0; j < num - 1 - i; j++)
			if (strcmp(target[j].name,target[j + 1].name)>0)
			{
				temp = target[j];
				target[j] = target[j + 1];
				target[j + 1] = temp;
			}
	show2(target);//显示数据
	free(target);
}
void sort3(Student *head)//性别
{
	Student * start = head;
	data *target = (data*)malloc(sizeof(data)*num);
	data temp;
	for (int i = 0; i < num; i++)
	{
		target[i] = start->student;
		start = start->next;
	}
	for (int i = 0; i<num; i++)
		for (int j = 0; j < num - 1 - i; j++)
			if (strcmp(target[j].sex, target[j + 1].sex)>0)
			{
				temp = target[j];
				target[j] = target[j + 1];
				target[j + 1] = temp;
			}
	show2(target);//显示数据
	free(target);
}
void sort4(Student *head)//年龄
{
	Student * start = head;
	data *target = (data*)malloc(sizeof(data)*num);
	data temp;
	for (int i = 0; i <num; i++)
	{
		target[i] = start->student;
		start = start->next;
	}
	for (int i = 0; i<num; i++)
		for (int j = 0; j < num - 1 - i; j++)
			if (target[j].old > target[j + 1].old)
			{
				temp = target[j];
				target[j] = target[j + 1];
				target[j + 1] = temp;
			}
	show2(target);//显示数据
	free(target);
}
void sort5(Student *head)//C语言
{
	Student * start = head;
	data *target = (data*)malloc(sizeof(data)*num);
	data temp;
	for (int i = 0; i <num; i++)
	{
		target[i] = start->student;
		start = start->next;
	}
	for (int i = 0; i<num; i++)
		for (int j = 0; j < num - 1 - i; j++)
			if (target[j].C_Language> target[j + 1].C_Language)
			{
				temp = target[j];
				target[j] = target[j + 1];
				target[j + 1] = temp;
			}
	show2(target);//显示数据
	free(target);
}
void sort6(Student *head)//英语
{
	Student * start = head;
	data *target = (data*)malloc(sizeof(data)*num);
	data temp;
	for (int i = 0; i <num; i++)
	{
		target[i] = start->student;
		start = start->next;
	}
	for (int i = 0; i<num; i++)
		for (int j = 0; j < num - 1 - i; j++)
			if (target[j].C_Language > target[j + 1].C_Language)
			{
				temp = target[j];
				target[j] = target[j + 1];
				target[j + 1] = temp;
			}
	show2(target);//显示数据
	free(target);
}
void sort7(Student *head)//高数
{
	Student * start = head;
	data *target = (data*)malloc(sizeof(data)*num);
	data temp;
	for (int i = 0; i <num; i++)
	{
		target[i] = start->student;
		start = start->next;
	}
	for (int i = 0; i<num; i++)
		for (int j = 0; j < num - 1 - i; j++)
			if (target[j].Math > target[j + 1].Math)
			{
				temp = target[j];
				target[j] = target[j + 1];
				target[j + 1] = temp;
			}
	show2(target);//显示数据
	free(target);
}
void sort8(Student *head)//平均分
{
	Student * start = head;
	data *target = (data*)malloc(sizeof(data)*num);
	data temp;
	for (int i = 0; i <num; i++)
	{
		target[i] = start->student;
		start = start->next;
	}
	for (int i = 0; i<num; i++)
		for (int j = 0; j < num - 1 - i; j++)
			if (target[j].average > target[j + 1].average)
			{
				temp = target[j];
				target[j] = target[j + 1];
				target[j + 1] = temp;
			}
	show2(target);//显示数据
	free(target);
}

练习三:贪吃蛇游戏

是不是有点激动?当时我看到这题目时我真的激动了,我终于可以自己写游戏了,真的很有成就感!
tips:这里我使用了easyx库,具体请访问它们们的官网:点这里.
实现:

#include "stdio.h"
#include "stdlib.h"
#include "conio.h"
#include "string.h"
#include 
#include "math.h"
#include       // 引用图形库头文件

#define SNAKEADD 15
#define SIDE 15

TCHAR snakehead[] = _T("■");
TCHAR snakebody[] = _T("□");
TCHAR snakfood[] = _T("@");
typedef struct Snake
{
	int x;
	int y;
	Snake *prev;
	Snake *next;
};

typedef struct Food
{
	int x;
	int y;
};
void food(int num[]);//重新食物
void addlength(Snake *head);//添加蛇身

void practice6project3()
{
	initgraph(600, 600);//初始化图形界面
	//画出边框
	POINT pts[] = { { 4, 4 },{ 591, 4 },{ 591,591 },{ 4, 591 } };
	polygon(pts, 4);
	//初始化链表
	//*****************************************************
	Snake *head = NULL;
	Snake *p = NULL;
	Snake *q = NULL;
	head = (Snake*)malloc(sizeof(Snake));
	head->x = 300;
	head->y = 300;
	head->next = NULL;
	head->prev = NULL;
	q = head;
	//*********************************************************

	Snake *start = head;
	char c = 'a',c2='a';//蛇的移动方向控制
	int key1 = 0;//判断蛇撞墙
	int key2 = 0;//判断蛇撞到自己
	int hx, hy;//收集蛇头移动后的位置,判断是否撞到自己
	int prex, prey;//收集蛇头移动前的位置
	int temp[4];//收收集蛇身位置
	int eat = 1;//蛇是否吃到食物
	int eat2 = 0;
	int num[2];//食物的位置
	int distamce1;//蛇头吃到自己
	int distamce2;//蛇头与食物的距离

				 //food(num);//第一次出现食物

				 //主循环
	while (true)
	{
		clearrectangle(5, 5, 590, 590);//清空

		if (eat == 1)
		{
			if (eat2 == 1)
				addlength(head);
			food(num);
			eat = 0;
			eat2 = 0;
		}
		//画出食物
		outtextxy(num[0], num[1], snakfood);
		//蛇移动
		start = head;//找到头指针

	  //蛇没有撞墙
		if (start->x <585 && start->x>5 && start->y<585 && start->y>5)
		{
			//记录蛇头旧位置
			prex = start->x;
			prey = start->y;
			//**************************************************************************************
			//接收键盘消息并处理
			{
				if (kbhit())//是否换方向
					c2 = getch();
				//去掉错误的行走放向
				switch (c2)
				{
				case 'w':
					if (c == 's')
						;
					else
						c = c2;
					break;
				case 'a':
					if (c == 'd')
						;
					else
						c = c2;
					break;
				case 's':
					if (c == 'w')
						;
					else
						c = c2;
					break;
				case 'd':
					if (c == 'a')
						;
					else
						c = c2;
					break;
				}
				//改变方向
				switch (c)
				{
				case 'w':
					head->y -= SNAKEADD;
					break;
				case 'a':
					head->x -= SNAKEADD;
					break;
				case 's':
					head->y += SNAKEADD;
					break;
				case 'd':
					head->x += SNAKEADD;
					break;
				default:
					break;
				}
			}
			//**************************************************************************************
			
			hx = start->x;
			hy = start->y;
			//******************************************************
			//在这里判断蛇吃到自己			
			//while (start->next != NULL)
			//{
			//	if (hx == start->x& hy == start->y)
			//	{
			//		TCHAR bb[] = _T("游戏结束!");
			//		outtextxy(300, 300, bb);
			//		key2 = -1;
			//	}
			//	start = start->next;
			//}
			//******************************************************
			distamce2 = (int)sqrt(((int)pow(((num[0] * 2 + 15) / 2 - (head->x * 2 + 15) / 2), 2)) + ((int)pow(((num[1] * 2 + 15) / 2 - (head->y * 2 + 15) / 2), 2)));
			//是否吃到食物
			if (distamce2 <= 15)
			{
				eat = 1;
				eat2 = 1;
			}
			//*****************************************************************
			//蛇没有撞墙且蛇没有撞到自己的情况下移动蛇身
			if (key2 != -1)
			{
				start->x = prex;//让蛇头还原到上一个位置
				start->y = prey;
				temp[0] = start->x;
				temp[1] = start->y;
				start = start->next;
				while (start != NULL)//有蛇身 就换数据
				{
					//先把自己的数据存好
					temp[2] = start->x;
					temp[3] = start->y;

					//把上个节点数据下放
					start->x = temp[0];
					start->y = temp[1];

					temp[0] = temp[2];
					temp[1] = temp[3];
					start = start->next;
				}
				//回复蛇头到移动后的位置
				start = head;
				start->x = hx;
				start->y = hy;
			}

			//*****************************************************************
			//画出蛇
			if (key2 != -1)
			{
				outtextxy(start->x, start->y, snakehead);
				start = start->next;
				while (start != NULL)
				{
					outtextxy(start->x, start->y, snakebody);
					start = start->next;
				}
			}
			//*****************************************************************
		}
		//蛇撞墙
		else
		{
			TCHAR aa[] = _T("游戏结束!");
			outtextxy(300, 300, aa);
			key1 = -1;
		}

		//游戏要出口
		if (key1 == -1 || key2 == -1)
			break;
		Sleep(200);
	}
	_getch();              // 按任意键继续
	closegraph();          // 关闭绘图窗口
}

//食物在范围内
void food(int num[])
{
	srand((unsigned)time(NULL));
	do
	{
		num[0] = rand() % 590;
		num[1] = rand() % 590;
	} while (!(num[0]<580 && num[0]>10 && num[1]<580 && num[1]>10));
}
//添加蛇身
void addlength(Snake *head)
{
	Snake *start = head;
	while (start->next != NULL)
		start = start->next;
	Snake *n = (Snake*)malloc(sizeof(Snake));
	n->next = NULL;

	n->prev = start;//链接前一个节点
	start->next = n;

}

实战七:文件操作及应用

本实战告诉你如何用C语言对文件进行读写,几个简单练习,你就可以掌握它。然后你可以自己写点好玩的东西,整蛊你室友。

练习一:简单的计数器

要求:

  1. 程序运行时,打开磁盘的数据文件,读取已经运行的次数。
  2. 再内存中计算本次程序运行的次数。
  3. 现实该程序本次运行的次数。
  4. 程序结束前,保存运行次数到磁盘数据文件中。
    实现:
#include "stdio.h"
#include "stdlib.h"
#include "conio.h"

void practice7project1()
{
	int count = 1;
	int key = 0;
	FILE *fp;
	if ((fp = fopen("practice7project1.dat", "r")) != NULL)//文件已经存在,进行count++
	{
		//读出数据
		fscanf(fp, "%d", &count);
		fclose(fp);//关闭只读
		//启动写入数据
		fp = fopen("practice7project1.dat", "w");
		count++;
		fprintf(fp, "%d", count);
		fclose(fp);
	}
	else if ((fp = fopen("practice7project1.dat", "w+")) == NULL)//第一次打开文件
	{
		printf("程序出错");
		getch();
		key = -1;
		if (key != -1)
		{
			fprintf(fp, "%d", count);
		}
	}
	if (key !=-1)
	{
		printf("这个程序运行%d次", count);
		getch();
	}
}

练习二:学生学籍管理系统(结构体+文件)

要求:

  1. 学生信息保存再磁盘文件:studentInfo.dat中。
  2. 学生学习管理系统可以完成对学生成绩信息的增、删、该、查操作。
  3. “平均成绩”项应该通过计算获得,不从键盘输入。
  4. 第一次使用噶系统时,可以从键盘输入初始数据,并建立初始学生信息磁盘文件:stendentInfo.dat。
  5. 退出系统前,要求把当前系统内的数据保存到文件中。
  6. 系统启动后,给出主操作菜单让用户选择操作,主菜单如下:
请选择排序字段
----------------------------------------------------------------------
1.现实所有学生信息			2.查询单个学生信息
3.修改学生信息			4.删除学生信息
5.增加学生信息			6.保存修改
0.退出系统
----------------------------------------------------------------------

实现(我可能偷懒了,没有按照要求来,但是核心功能实现了的):

#include "stdio.h"
#include "stdlib.h"
#include "conio.h"
typedef struct Student

{
	int id;
	char name[9];
	char sex[3];
	int old;
	float C_language;
	float Engkish;
	float Math;
	float average;
	Student *next;
};
int number;
//studentInfo.dat
//增加 删除 修改,查;
int  p72Display();
int input(Student* &head);//输入数据
int output(Student* head);//输出数据到文件
int  read(Student* &head);//从文件读取数据

void show(Student* head);//浏览数据
void addstudent(Student* &head);//添加元素
void delatestudent(Student* &head);//删除元素
void changestudent(Student* &head);//修改数据

//入口
void practice7project2()
{
	Student *head;
	head = NULL;
	int key;
	FILE *fp;
	printf("是否是第一次运行本程序:1.是\t2.不是\t3.不清楚\n");
	scanf("%d", &key);

	//原始提取
	while (true)
	{
		switch (key)
		{
		case 1://输入数据原始数据并写入文件
		{
			number = input(head);
			if (output(head))
				printf("写入文件成功!\n");
			else
				printf("写入文件失败");
			getch();
			break;
		}
		case 2://读取数据
			number= read(head);
			break;
		case 3://检查是否有数据,根据结果选择操作
		{
			if ((fp = fopen("practice7project2.dat", "r")) == NULL)
			{
				printf("检查到没有这个文件,现在请输入信息:\n");
				number = input(head);
				if (output(head))//将数据写入文件
					printf("写入文件成功!\n");
				else
					printf("写入文件失败");
				getch();
			}
			else
			{
				printf("检查到文件\n");
				number = read(head);
				if (number != 0)
					printf("文件读取成功!\n");
				else
					printf("文件读取失败!\n");
			}
			getch();
			break;
		}
		default:
			printf("输入错误");
			break;
		}
		if (key == 1 || key == 2 || key == 3)
			break;
	}
	//数据处理
	while (true)
	{
		system("cls");
		key = p72Display();
		switch (key)
		{
		case 1://查询数据
			show(head);
			break;
		case 2://添加数据
			addstudent(head);
			break;
		case 3://删除数据
			delatestudent(head);
			break;
		case 4://修改数据
			changestudent(head);
			break;
		case 5:
			break;
		default:
			printf("输入错误1");
			break;
		}
		if (key == 5)
			break;
	}
}

int p72Display()
{
	int key;
	printf("============================================================\n");
	printf("\t1.查询数据\n");
	printf("\t2.添加数据\n");
	printf("\t3.删除数据\n");
	printf("\t4.修改程序\n");
	printf("\t5.返回上一级菜单\n");
	printf("============================================================\n");
	scanf("%d", &key);
	return key;
}


//输入数据
int input(Student* &head)
{
	int num;
	Student *p = NULL;
	Student *q =NULL;
	printf("\n\n请输入你要输入的学生个人数:");
	scanf("%d",&num);
	for (int i = 0; i < num; i++)
	{
		if (head == NULL)
		{
			head = (Student*)malloc(sizeof(Student));
			head->next = NULL;
			printf("==========================================================================\n");
			printf("请输入学号:");
			scanf("%d", &head->id);
			printf("请输入姓名:");
			scanf("%s", &head->name);
			printf("请输入性别:");
			scanf("%s", &head->sex);
			printf("请输入年龄:");
			scanf("%d", &head->old);
			printf("请输入C语言:");
			scanf("%f", &head->C_language);
			printf("请输入英语:");
			scanf("%f", &head->Engkish);
			printf("请输入数学:");
			scanf("%f", &head->Math);
			head->average = (head->Math + head->C_language + head->Engkish) / 3;
			q = head;
		}
		else
		{
			p = (Student*)malloc(sizeof(Student));
			p->next = NULL;
			q->next = p;
			printf("==========================================================================\n");
			printf("请输入学号:");
			scanf("%d", &p->id);
			printf("请输入姓名:");
			scanf("%s", &p->name);
			printf("请输入性别:");
			scanf("%s", &p->sex);
			printf("请输入年龄:");
			scanf("%d", &p->old);
			printf("请输入C语言:");
			scanf("%f", &p->C_language);
			printf("请输入英语:");
			scanf("%f", &p->Engkish);
			printf("请输入数学:");
			scanf("%f", &p->Math);
			p->average = (p->Math + p->C_language + p->Engkish) / 3;
			q = p;
		}
	}
	printf("输入结束,按任意键继续...");
	getch();
	return num;
}

//输出数据到文件
int output(Student* head)
{
	int num=0;
	FILE *ff;
	if ((ff = fopen("practice7project2.dat", "w")) == NULL)
		printf("文件打开失败!\n");
	else
	{
		while (head != NULL)
		{
			num += fwrite(head, sizeof(Student), 1, ff);
			head = head->next;
		}
	}
	fclose(ff);
	return num;
}
//从文件读取数据
int  read(Student* &head)
{
	int num=0;
	FILE *ff;
	if ((ff = fopen("practice7project2.dat", "r")) == NULL)
		printf("文件打开失败!");
	else
	{
		Student *p = NULL;
		Student *q = NULL;
		while (!feof(ff))
		{
			if (head == NULL)
			{
				head = (Student*)malloc(sizeof(Student));
				fread(head, 1, sizeof(Student), ff);
				num++;
				q = head;
			}
			else
			{
				p = (Student*)malloc(sizeof(Student));
				if (fread(p, 1, sizeof(Student), ff) > 2)
				{
					num++;
					p->next = NULL;
					q->next = p;
					q = p;
				}
				else
				{
					free(p);
				}
			}
		}
	}
	return num;
}

//浏览数据
void show(Student* head)
{
	printf("学号\t姓名\t性别\t年龄\tC语言\t英语\t数学\t平均分\n");
	while (head!=NULL)
	{
		printf("%-4d\t%-4s\t%-4s\t%-4d\t%-4.2f\t%-4.2f\t%-4.2f\t%-4.2f\n",head->id, head->name, head->sex, head->old,head->C_language,head->Engkish,head->Math,head->average );
		head = head->next;
	}
	getch();
}

//添加元素
void addstudent(Student* &head)
{
	Student *oldhead=head;
	int num;
	printf("请输入你要添加的学生个数:");
	scanf("%d", &num);
	number += num;
	while (head->next!=NULL)
	{
		head = head->next;
	}
	Student *p = NULL;
	Student *q = NULL;

	q = head;
	for (int i = 0; i < num; i++)
	{
		p = (Student*)malloc(sizeof(Student));
		p->next = NULL;
		q->next = p;
		printf("==========================================================================\n");
		printf("请输入学号:");
		scanf("%d", &p->id);
		printf("请输入姓名:");
		scanf("%s", &p->name);
		printf("请输入性别:");
		scanf("%s", &p->sex);
		printf("请输入年龄:");
		scanf("%d", &p->old);
		printf("请输入C语言:");
		scanf("%f", &p->C_language);
		printf("请输入英语:");
		scanf("%f", &p->Engkish);
		printf("请输入数学:");
		scanf("%f", &p->Math);
		p->average = (p->Math + p->C_language + p->Engkish) / 3;
		q = p;
	}
	printf("输入结束,按任意键继续...");
	getch();
	head = oldhead;
	if (output(head) > 1)
		printf("写入文件成功!\n");
	else
		printf("写入文件失败!\n");
	getch();

}

//删除元素
void delatestudent(Student* &head)
{
	int num;
	Student *cp, *star = head;
	printf("请输入你想删除学生的学号:");
	scanf("%d", &num);
	while (star!=NULL)
	{
		if (star->id == num)
			break;
		cp = star;
		star = star->next;
	}
	if (cp==NULL)//删除第一个节点
	{
		cp = head;
		 head= head->next;
		free(cp);
	}
	else
		cp->next = star->next;

	//在把修改后的数据写入文件
	if (output(head) > 1)
		printf("删除成功!\n");
	else
		printf("删除失败!\n");
	number--;
	getch();
}

//修改数据
void changestudent(Student* &head)
{
	int num;
	Student *star = head;
	printf("请输入你想修改学生的学号:");
	scanf("%d", &num);
	while (star != NULL)
	{
		if (star->id == num)
			break;
		star = star->next;
	}
	printf("请输入修改的内容:\n");
	printf("==========================================================================\n");
	printf("请输入学号:");
	scanf("%d", &star->id);
	printf("请输入姓名:");
	scanf("%s", &star->name);
	printf("请输入性别:");
	scanf("%s", &star->sex);
	printf("请输入年龄:");
	scanf("%d", &star->old);
	printf("请输入C语言:");
	scanf("%f", &star->C_language);
	printf("请输入英语:");
	scanf("%f", &star->Engkish);
	printf("请输入数学:");
	scanf("%f", &star->Math);
	star->average = (star->Math + star->C_language + star->Engkish) / 3;

	//写入到文件
	if (output(head) > 1)
		printf("修改成功!\n");
	else
		printf("修改失败!\n");
	getch();
}

结语

所有的代码都是我在学习中自己积累,很多题目的实现现在看起来都很幼稚,但我很高兴,对于我来所我这个课程完成的不错。最后附上完整demo的地址: 点这里.

你可能感兴趣的:(C/C++)