南邮C语言期末考试复习+实验报告

目录

实验报告一

实验报告二

实验报告三

实验报告四

实验报告五

实验报告六

模块一:基础知识部分

模块二:三种基本结构及流程控制

模块三:函数

模块四:数据类型

模块五:文件

我自己的疑点:


实验报告一

1.从键盘输入两个整数a和b,计算并输出他们的和sum、
差difference、积product、商quotient和平均值ave(注意ave和商的定义类型)。

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main()
{
	int a, b;
	printf("请从键盘输入整数a和b的值:");
	scanf("%d%d", &a, &b);
	printf("a=%d,b=%d\n", a,b);
	int sum = a + b;
	printf("sum=%d\n", sum);
	int difference = a - b;
	printf("difference=%d\n", difference);
	int product = a * b;
	printf("product=%d\n", product);
	double quotient = (double)a / b;
	printf("quotient=%lf\n", quotient);
	double ave = (a + b) / 2.0;
	printf("ave=%lf", ave);
	return 0;
}

2.实现两个整数a,b的交换,
提示思考:我们在现实生活中,两杯水是怎么交换的。

#include<stdio.h>
int main()
{
	int a, b, c;
	printf("请输入整数a和b的值:\n");
	scanf("%d%d", &a, &b);
	printf("a=%d,b=%d\n", a, b);
	c = a;
	a = b;
	b = c;
	printf("a=%d,b=%d\n", a, b);
	return 0;
}

3.工厂给一圆柱体镀膜,每平方厘米造价10元,
现从键盘上输入圆柱底面的半径radius(厘米)和圆柱的高height(厘米),
求该圆柱体的表面积area(平方厘米)和所需费用,要求输出结果保留两位小数。

#include<stdio.h>
#define PI 3.1415926
int main()
{
	int radius, height;
	printf("请输入radius和height:\n");
	scanf("%d%d", &radius, &height);
	printf("radius=%d,height=%d\n", radius, height);
	double area = PI * radius * radius * 2 + 2 * PI * radius * height;
	double money = area * 10;
	printf("area=%.2lf,money=%.2lf", area, money);
	return 0;
}

4.输入一个3位正整数,计算该数的逆序数,并输出。例如:输入789,输出987;

#include<stdio.h>
int main()
{
	int a;
	printf("请输入一个三位整数:\n");
	scanf("%d", &a);
	printf("原数=%d\n", a);
	int g, s, b;
	g = a % 10;
	s = a % 100 / 10;
	b = a / 100;
	int c = g * 100 + s * 10 + b;
	printf("现在=%d", c);
	return 0;
}

实验报告二

1.读入3个double型变量a, b, c的值,用if语句判断它们能否构成三角形,
如果能构成三角形又是构成的何种三角形
(等边三角形、等腰三角形、直角三角形、等腰直角三角形、一般三角形)?输出各种情况下判断的结果。
(建议参考实验指导教材的流程图4.20,先对a, b, c进行由小到大的排序可以简化代码)

学到的就是程序的分块思想,三角形无非就两种一种直角三角形,一种普通三角形,
在这两大块下在对三角形的种类进行细分

#include<stdio.h>
#include<math.h>
int main()
{
	double a, b, c;
	printf("输入三角形的三边长度a,b,c:\n");
	scanf("%lf%lf%lf", &a, &b, &c);
	if (a + b - c <= 0 || a + c - b <= 0 || b + c - a <= 0 || a < 0 || b < 0 || c < 0)
		printf("不能构成三角形!\n");
	else if (fabs(a * a + b * b - c * c) > 1E-3)
	{
		if (a == b && b == c)
			printf("这是一个等边三角形!\n");
		else if ((a == b && b != c) || (a == c && a != b) || (b == c && a != b))
			printf("这是一个等腰三角形!\n");
		else
			printf("这是一个一般三角形!\n");
	}
	else if (fabs(a * a + b * b - c * c) <= 1E-3)
	{
		if (a == b || b == c || a == c)
			printf("这是一个等腰直角三角形!\n");
		else
			printf("这是一个直角三角形!\n");
	}
	return 0;
}

2.利用while、for、do…while循环语句计算求和问题:S = 2 / 1 - 3 / 2 + 5 / 3 - 8 / 5 + ……
求前1000项之和

#include<stdio.h>
int main()
{
	int i,sign=1;
	double sum=0;
	double a = 2, b = 1;
	for (i = 0; i < 1000; i++)
	{
		sum += sign*1.0*a / b;
		a = a + b;
		b = a - b;
		sign = -sign;
	}
	printf("sum=%lf", sum);
	return 0;
}

3.先用一层循环判断从键盘读入的正整数x是否为质数,并输出判断结果。
在此基础上改写,再加上外层循环,找出规定范围(a, b)内的所有质数,并按每行5个的格式输出。
(这里a,b变量从键盘输入并且范围为:10≤a≤b≤1000)

F1:

#include<stdio.h>
#include<math.h>
void judgeprime(int a, int b)
{
	int c,k,count=0;
	for (int i = a; i < b; i++)
	{
		k = (int)sqrt(i);
		for (c = 2; c <= k; c++)
		{
			if (i % c == 0)
				break;
		}
		if (c > k)
		{
			printf("%5d", i);
			count++;
			if (count % 5 == 0)
				printf("\n");
		}
	}
}
int main()
{
	int a, b;
	printf("请输入所要判断质数的区间范围a-b(a>=10,b<=1000):\n");
	scanf("%d%d", &a, &b);
	if (a > b || a < 10 || b>1000 || b < 10 || a>1000)
		printf("输入错误!\n");
	else
		judgeprime(a, b);
	return 0;
}

F2:

#include<stdio.h>
#include<math.h>
int main()
{
	int a, b, i,k,c,count=0;
	printf("请输入要判断质数的区间a-b(a>=10,b<=1000):\n");
	scanf("%d%d", &a, &b);
	if (a<10||b>1000||b<10||a>1000)
		printf("输入错误!\n");
	else
		for (i = a; i < b; i++)
		{
			k = (int)sqrt(i);
			for (c = 2; c <= k; c++)
			{
				if (i % c == 0)
					break;
			}
			if (c > k)
			{
				printf("%5d", i);
				count++;
				if (count % 5 == 0)
					printf("\n");
			}
		}
	return 0;
}

4.利用循环嵌套输出一个菱形。
        *         8
      * * *       6
    * * * * *     4
  * * * * * * *   2
    * * * * *     4
      * * *       6
        *         8
尝试在上面程序的基础上作一定修改,分别输出:上三角形、下三角形、
左一半三角形、右一半三角形,主要需要修改的语句是控制什么的语句?

#include<stdio.h>
int main()
{
	int i, j;
	for (i = 0; i < 4; i++)
	{
		for (j = 0; j < 8 - 2 * i; j++)
			printf(" ");
		for (j = 0; j < 2 * i + 1; j++)
		{
			printf(" *");
		}
		printf("\n");
	}
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 2 * i + 4; j++)
			printf(" ");
		for (j = 0; j < 5 - 2 * i; j++)
			printf(" *");
		printf("\n");
	}
	return 0;
}

上下半边比较简单,就不演示了

左半边:

#include<stdio.h>
int main()
{
	int i, j;
	for (i = 0; i < 4; i++)
	{
		for (j = 0; j < 8 - 2 * i; j++)
			printf(" ");
		for (j = 0; j < i + 1; j++)
			printf(" *");
		printf("\n");
	}
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 2 * i + 4; j++)
			printf(" ");
		for (j = 0; j < 3 - i; j++)
			printf(" *");
		printf("\n");
	}
	return 0;
}

右半边:

#include<stdio.h>
int main()
{
	int i, j;
	for (i = 0; i < 4; i++)
	{
		printf("        ");
		for (j = 0; j < i + 1; j++)
		{
			printf(" *");
		}
		printf("\n");
	}
	for (i = 0; i < 3; i++)
	{
		printf("        ");
		for (j = 0; j < 3 - i; j++)
		{
			printf(" *");
		}
		printf("\n");
	}
	return 0;
}

实验报告三

1.巧用函数调用,打印不同行数和字符构成的等腰三角形。
具体要求:定义一个函数原型void DrawTriangle(int n, char c); ,
实现功能为打印一个n行的由字符c组成的等腰三角形。
主程序调用该函数,实现打印5行“ '* ' ”、10行“ '# ' ”的等腰三角形。

#include<stdio.h>
void DrawTriangle(int n, char c)
{
	int i,j;
	for (i = 0; i < n; i++)
	{
		for (j=0;j<n-i;j++)
			printf(" ");//这个打印的空格数没有想到
		for (j = 0; j < 2 * i + 1; j++)
			printf("%c", c);
		printf("\n");
	}
}
int main()
{
	DrawTriangle(5, '*');
	printf("\n");
	DrawTriangle(10, '#');
	return 0;
}

2.验证歌德巴赫猜想:2000以内的正偶数(不包括2)都能够分解为两个质数之和。
(算法提示:将整数分解为两个整数,然后判断它们是否均为质数。
若是,则满足题意并输出;否则重新进行分解和判断。
其中,判断一个整数是否为质数采用函数实现。
每个偶数只要得到一种分解就停止,不必要求出该偶数的所有质数和组合)。

#include<stdio.h>
#include<math.h>
int judgeprime(int n)
{
	int i, k;
	int judge = 1;
	if (n == 1)
		judge = 0;
	k = (int)sqrt(n);
	for (i = 2; judge && i <= k; i++)//<=哦
		if (n % i == 0)
			judge = 0;
	return judge;
}
int main()
{
	int x, m, n;
	for (x = 4; x <= 2000; x += 2)
	{
		for (n = 2; n < x ; n ++)
		{
			m = x - n;
			if (judgeprime(m) && judgeprime(n))
			{
				printf("%d=%d+%d\n", x, m, n);
				break;
			}
		}
	}
	return 0;
}

3.用递归方法实现求解两个整数的最大公约数,
并与迭代方法作比较。

递归

#include<stdio.h>
int fun(int x, int y)
{
	if (x % y == 0)
		return y;
	else
		return fun(y, x % y);
}
int main()
{
	int x,y,z;
	scanf("%d%d", &x, &y);
	z = fun(x, y);
	printf("%d", z);
	return 0;
}

 迭代

#include<stdio.h>
int main()
{
	int x, y, z;
	scanf("%d%d", &x, &y);
	z = x % y;
	while (z)
	{
		x = y;
		y = z;
		z = x % y;
	}
	printf("%d", y);
	return 0;
}

4.用调试器观察程序exp4_8.c的运行过程,并记录各种变量在每一步执行时的变化情况,
在表格中填写每一个跟踪步每个变量对应的值。

#include<stdio.h>
int a = 1;
int f(int a)
{
	int b = 2;
	static int c = 3;
	a = a + 1;
	b = b + 1;
	c = c + 1;
	return (a + b + c);
}
int main()
{
	int i;
	for (i = 0; i < 3; i++)
	{
		a = a + 2;
		printf("%d\n", f(a));
	}
	return 0;
}

自己狂按F10就可以了

实验报告四

1.在主函数中定义一维数组int array[10],自定义以下函数:
输入数组元素,输出数组元素、求数组元素平均值、
输出数组元素最大值、输出数组元素最小值、查找某数值元素是否存在(若存在,请输出下标)、
给数组元素排序,要求在主函数中对各子函数进行调用和测试。

#include<stdio.h>

void input(int a[],int n)
{
	int i;
	for (i = 0; i < n; i++)
	{
		scanf("%d", &a[i]);
	}
}

void printf(int a[], int n)
{
	int i;
	for (i = 0; i < n; i++)
	{
		printf("%3d", a[i]);
	}
	printf("\n");
}

double average(int a[], int n)
{
	double average, sum=0;
	int i;
	for (i = 0; i < n; i++)
	{
		sum += a[i];
	}
	average = sum / n;
	return average;
}

int max(int a[],int n)
{
	int i, max;
	max = a[0];
	for (i = 1; i < n; i++)
	{
		if (max < a[i])
			max = a[i];
	}
	return max;
}

int min(int a[], int n)
{
	int i;
	int min = a[0];
	for (i = 1; i < n; i++)
	{
		if (min > a[i])
			min = a[i];
	}
	return min;
}

void search(int a[],int n)
{
	int i, z, x = 0;
	printf("输入要查找的数字:");
	scanf_s("%d", &z);
	printf("查找的数字在数组中下标是:");
	for (i = 0; i < n; i++)
		if (z == a[i])
		{
			x++;
			printf("%d ", i);
		}
	if (x == 0)
		printf("不存在");
	printf("\n");
}
void BubbleSort(int a[], int n)
{
	int i, j, temp;
	for(i=0;i<n-1;i++)
		for(j=0;j<n-1-i;j++)
			if (a[j] > a[j + 1])
			{
				temp = a[j + 1];
				a[j + 1] = a[j];
				a[j] = temp;
			}
}
int main()
{
	int i,n,X;
	int array[10];
	do
	{
		scanf("%d", &n);
		printf("请输入%d个元素:\n", n);
	} while (n < 1 || n>10);
	input(array, n);
	printf("数组的元素是:\n");
	printf(array, n);
	printf("数组元素的平均值是:");
	double ave=average(array, n);
	printf("%lf\n", ave);
	int Max = max(array, n);
	printf("数组中的最大值是:%d\n", Max);
	int Min = min(array, n);
	printf("数组中的最小值是:%d\n", Min);
	search(array, n);
	BubbleSort(array, n);
	printf("排序后的数组是:\n");
	printf(array, n);
	return 0;
}

2.定义一个3 * 3的矩阵,要求实现读入矩阵、输出矩阵、
矩阵转置、输出矩阵主对角线元素之和,所有功能均采用子函数实现。

#include<stdio.h>
#define N 10
int input(int a[][N], int n)
{
	int i, j;
	for(i=0;i<n;i++)
		for (j = 0; j < n; j++)
		{
			scanf("%d", &a[i][j]);
		}
	return a[i][j];
}

int printf(int a[][N], int n)
{
	int i, j;
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < n; j++)
		{
			printf("%5d", a[i][j]);
		}
		printf("\n");
	}
	return 0;
}

void transposition(int a[][N],int b[][N],int n)
{
	int i, j;
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < n; j++)
			b[i][j] = a[j][i];
		printf("\n");
	}
	for (i = 0; i < n; i++)
	{
		for (j = 0; j < n; j++)
			printf("%5d", b[i][j]);
		printf("\n");
	}
}

int sum_diag(int a[][N], int n)
{
	int sum = 0,i;
	for (i = 0; i < n; i++)
		sum += a[i][i];
	return sum;
}

int main()
{
	int n;
	int a[N][N], b[N][N];
	printf("请输入n:(1<=n<=10)\n");
	scanf("%d", &n);
	printf("请输入%d个数\n", n * n);
	input(a, n);
	printf("数组是:\n");
	printf(a, n);
	printf("转置后的矩阵是:\n");
	transposition(a, b, n);
	printf("数组的对角线之和是:");
	int sum = sum_diag(a, n);
	printf("%d", sum);
	return 0;
}

3.输出一个N阶螺旋方阵
N=4的时候的矩阵
 1  2  3    4
12 13 14 5
11 16 15 6
10  9  8   7 

#include<stdio.h>
int main()
{
	int i,n,h,l,x=1;
	int a[100][100];
	printf("请输入一个整数n\n");
	scanf("%d", &n);
	h = 0;//行
	l = n - 1;//列
	do
	{
		for (i = n - 1 - l; i <= l; i++)//第一行n个
			a[h][i] = x++;
		for (i = h + 1; i <= (n - 1 - h); i++)//最后一列n-1个
			a[i][l] = x++;
		for (i = l - 1; i >= (n - 1 - l); i--)//最后一行n-1个
			a[n - 1 - h][i] = x++;
		h++;
		for (i = (n - 1 - h); i >= h; i--)
			a[i][n - 1 - l] = x++;
		l--;
	} while (x <= n * n);
	for (i = 0; i < n; i++)
	{
		for (h = 0; h < n; h++)
			printf("%5d", a[i][h]);
		printf("\n");
	}
	return 0;
}

4.请判断花瓶是谁打碎的。教师花瓶碎了,班级只有四个小同学,
老师询问小同学,已知是其中1人打碎的,还知道4人中每个人要么是诚实的,要么总是说谎的。
小同学回答老师的问题是:
甲说:“乙没有打碎,是丁打碎的。”
乙说:“我没有打碎,是丙打碎的。”
丙说:“甲没有打碎,是乙打碎的。”
丁说:“我没有打碎。”
根据四人回答判断谁打碎了花瓶。

#include<stdio.h>
int main()
{
	int array[4] = { 0 }, i, j;
	for (i = 0; i < 4; i++)
	{
		array[i] = 1;
		if (array[3] + array[1] == 1 && array[2] + array[1] == 1
 && array[0] + array[1] == 1)//因为甲乙丙所说的都是一个人打碎了一个人没有
			//所以它们的逻辑值和为1,只有当a[1]=1时可以使条件成立
		{
			printf("打碎花瓶的是:");
			for (j = 0; j <= 3; j++)
			{
				if (array[j])
					printf("%d\n", j);
			}
		}
		array[i] = 0;
	}
	printf("(0,1,2,3分别代表 甲,乙,丙,丁)\n");
	return 0;
}

实验报告五

1.现有整型变量x,y,调用交换函数以期实现两个值的交换。

#include<stdio.h>

void swap1(int a, int b)
{
	int temp = a;
	a = b;
	b = temp;
}//形参的值进行了交换,但是对实参没有影响

void swap2(int *a, int b)
{
	int temp = *a;
	*a = b;
	b = temp;
}//改变了x的地址,所以x的之发生了变化,但对y没有影响

void swap3(int *a, int *b)
{
	int temp = *a;
	*a = *b;
	*b = temp;
}//x,y的地址都发生了变化,所以值都产生了变化

void swap4(int *a, int *b)
{
	int *temp = a;
	a = b;
	b = temp;
}//只是对指针本身进行了修改,它的值没有发生变化

int main()
{
	int x = 1, y = 2;
	printf("原先x=%d,y=%d\n", x, y);
	printf("请输入i(1<=i<=4):");
	int i;
	scanf("%d", &i);
	switch (i)
	{
	case 1:swap1(x,y); printf("现在x=%d,y=%d\n", x, y); break;
	case 2:swap2(&x,y); printf("现在x=%d,y=%d\n", x, y); break;
	case 3:swap3(&x,&y); printf("现在x=%d,y=%d\n", x, y); break;
	case 4:swap4(&x,&y); printf("现在x=%d,y=%d\n", x, y); break;
	}
	return 0;
}

2.实现数组的逆置。如:int a[5] = { 1,3,4,5,6,7 };
逆置后int a[5] = { 7,6,4,5,3,1 }

#include<stdio.h>
#define N 100
void inverse(int a[],int n)
{
	int i,j;
	int temp;
	for (i = 0, j = n - 1; i < j; i++, j--)
	{
		temp = a[i];
		a[i] = a[j];
		a[j] = temp;
	}
}

int main()
{
	int a[N];
	int n;
	printf("请输入数组的个数n:");
	scanf("%d", &n);
	printf("\n");
	for (int i = 0; i < n; i++)
		scanf("%d", &a[i]);
	printf("数组如下:\n");
	for (int i = 0; i < n; i++)
		printf("%5d", a[i]);
	printf("\n");
	inverse(a, n);
	printf("逆置后的数组是:\n");
	for (int i = 0; i < n; i++)
		printf("%5d", a[i]);
	return 0;
}

3.从键盘读入一个字符串,去掉其中所有的空格得到一个新串后再输出
(只能定义一个字符数组,不可以定义两个字符数组,
可以根据编程需要定义字符指针以及其他变量)。

#include<stdio.h>
#include<string.h>
#define N 100
char *blank_str(char*str)
{
	int i = 0, j = 0;
	while(str[i])
	{
		if (str[i] != ' ')
			str[j++] = str[i++];
		else
			i++;
	}
	str[j] = '\0';
	return str;
}

int main()
{
	char str[N];
	printf("请输入一个字符串:\n");
	gets_s(str);
	blank_str(str);
	puts(str);
	return 0;
}

4.帮助小红从小明通过网络发送的两串字符串中,提取用户名和密码。
提取规则:将第一串字符串中所有的大小写字母按原序连起来,再按原序取奇数位就是用户名;
将第二串中所有数字按原序连起来,再按原序取偶数位就是密码。
例:小明发给小红的第一个字符串为“ag13re5D6s789h0R”,
则源串大小字母按序连起来为“agreDshR”,所以用户名为“arDh”;
第二个字符串为“UGa4fF6hHt97J89iK5i4L2P3”, 则源串数字按序连起来为“4697895423”,所以密码为“67943”。

#include<stdio.h>
#include<string.h>
#define N 100
char *allletter(char *str)
{
	int i = 0, j = 0;
	while (str[i])
	{
		if ((str[i] >= 'A' && str[i] <= 'Z') || (str[i] >= 'a' && str[i] <= 'z'))
			str[j++] = str[i++];
		else
			i++;
	}
	str[j] = '\0';
	return str;
}

void* username(char* str)
{
	printf("账号是:\n");
	int m = strlen(str);
	for (int i = 0; i < m; i+=2)
	{
		printf("%c", str[i]);
	}
	printf("\n");
	return 0;
}

char* allnumber(char* str)
{
	int i = 0, j = 0;
	while (str[i])
	{
		if (str[i] >= '0' && str[i] <= '9')
			str[j++] = str[i++];
		else
			i++;
	}
	str[j] = '\0';
	return str;
}

void* secret(char* str)
{
	printf("密码是:\n");
	int m = strlen(str);
	for (int i = 1; i < m; i += 2)
	{
		printf("%c", str[i]);
	}
	printf("\n");
	return 0;
}
void类型的函数可以没有返回值,但是void*类型的函数就是要返回一个任意值

int main()
{
	char str1[N],  str2[N];
	printf("请输入第一个字符串:\n");
	gets_s(str1);
	printf("请输入第二个字符串:\n");
	gets_s(str2);
	allletter(str1);
	username(str1);
	allnumber(str2);
	secret(str2);
	return 0;
}

实验报告六

1.验证用户输入的日期格式是否正确,如果不正确,
则提示重新输入,直到重新输入正确为止。
(提示:需要定义一个表示日期的结构体类型struct Date,
包括年、月、日信息,并用typedef重新定义新类型名Date;
检查日期是否有效,定义为函数int checkDate(Date date))。 

#include<stdio.h>
struct Date
{
	int Year;
	int Month;
	int Day;
}date;
typedef struct Date Date;

int checkDate(Date date)
{
	int y = 0;
	if (date.Month == 1 || date.Month == 3 || date.Month == 5 || date.Month == 7 || date.Month == 8
		|| date.Month == 10 || date.Month == 12)
		y = 1;
	if (date.Month = 4 || date.Month == 6 || date.Month == 9 || date.Month == 11)
		y = 4;
	if (date.Month == 2)
	{
		if ((date.Year % 4 == 0 && date.Year % 100 != 0) || date.Year % 400 == 0)
			y = 2;
		else
			y = 3;
	}
	if (date.Month < 1 || date.Month >12)
		return 0;
	if (y == 1 &&( date.Day < 1 || date.Day>31))
		return 0;
	if (y == 2 &&( date.Day < 1 || date.Day>29))
		return 0;
	if (y == 3 && (date.Day < 1 || date.Day>28))
		return 0;
	if (y == 4 && (date.Day > 30 || date.Day < 1))
		return 0;
	else return 1;
}

int main()
{
	int x;
	do
	{
		printf("请输入日期:\n");
		scanf("%d%d%d", &date.Year, &date.Month, &date.Day);
		x = checkDate(date);
	} while (x == 0);
	if (x)
		printf("正确.\n");
	return 0;
}

2.从键盘读入一系列字符并以“#”结束,
将读入的字符(不包括#号)存入文本文件D:\f1.txt中,
再从该文件读取内容,并在显示器上原样显示。

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

void writefile(char ch, FILE* fp)
{
	printf("Enter a text(end with #):\n");
	ch = getchar();
	while (ch != '#')
	{
		fputc(ch, fp);
		ch = getchar();
	}
}

void readfile(char ch, FILE* fp)
{
	while ((ch = fgetc(fp)) != EOF)
	{
		putchar(ch);
	}
	putchar('\n');
}

int main()
{
	FILE* fp;
	char ch = 0;
	fp = fopen("D:\\f1.txt", "w+");
	if (fp == 0)                      
	{
		printf("file error\n");
		exit(1);
	}
	writefile(ch, fp);
	rewind(fp);
	readfile(ch, fp);
	fclose(fp);
	return 0;
}

3.某班有学生若干名(不超过40名),其信息的组织采用如下的结构体定义。编写程序exp9_2.c,完成要求的功能。
struct Student
{
    char ID[20];
    char name[30];
    int age;
    double score;
};
① 从键盘读入该班级学生的信息。
② 将所有的学生信息存入D : \\Info.dat文件中、关闭该文件,建立文件定义函数CreateFile实现。
③ 另写一个函数ReadOut,将D : \\Info.dat文件中的信息读入到内存,并依次输出到显示器上,该函数由main函数调用。
④编写函数Sort,实现按成绩由高到低将学生记录进行排序并输出排序后的结果。
⑤文件读写采用二进制读写(fread、fwrite)方式。

#include<stdio.h>
#include<stdlib.h>
#define N 50

struct Student
{
	char ID[20];
	char name[30];
	int age;
	double score;
};
typedef struct Student Stu;

void CreateFile(Stu stu[],int n,FILE *fp)
{
	fp = fopen("D : \\Info.dat", "wb+");
	if (fp == 0)
	{
		printf("file error!\n");
		exit(1);
	}
	fwrite(stu, sizeof(Stu), n, fp);
	fclose(fp);
}

void ReadOut(Stu stu[], int n, FILE* fp)
{
	int i = 0;
	fp = fopen("D : \\Info.dat", "rb");
	if (fp == 0)
	{
		printf("file error!\n");
		exit(1);
	}
	fread(&stu[i], sizeof(Stu), n, fp);
	for (i = 0; i < n; i++)
		printf("%s %s %d %.2f\n", stu[i].ID, stu[i].name, stu[i].age, stu[i].score);
	fclose(fp);
}

void Sort(Stu stu[], int len)
{
	int i, k, index;
	Stu temp;
	for (k = 0; k < len - 1; k++)
	{
		index = k;
		for (i = k + 1; i < len; i++)
			if (stu[i].score > stu[index].score)
				index = i;
		if (index != k)
		{
			temp = stu[index];
			stu[index] = stu[k];
			stu[k] = temp;
		}
	}
	for (i = 0; i < len; i++)
		printf("%s %s %d %.2f\n", stu[i].ID, stu[i].name, stu[i].age, stu[i].score);
}

int main()
{
	int n, i, x;
	Stu stu[N];
	FILE* fp = NULL;                      
	do
	{
		printf("Please input the number of students:\n");
		scanf("%d", &n);
	} while (n < 1 || n>40);
	for (i = 0; i < n; i++)
	{
		x = i + 1;
		printf("%d(ID name age score):\n", x);
		scanf("%s%s%d%lf", stu[i].ID, stu[i].name, &stu[i].age, &stu[i].score);
	}
	CreateFile(stu, n, fp);
	printf("before being sorted:\n");
	ReadOut(stu, n, fp);
	printf("after being sorted:\n");
	Sort(stu, n);
	return 0;
}

说明:期末复习部分是按照学校发的大纲截取其中我认为比较重要的东西写上来的。

模块一:基础知识部分

1.C语言程序的组成:由一个或多个文件组成,每个文件由一个或多个函数组成,函数是C程序的基本单位

2.预处理命令都必须以“#”开始

3.带参数的宏可以完成一些简单的功能,例如:#define MUL(x,y) x*y

c= MUL(3+2,4+5),则变量c的值为16

计算的方法是直接将3+2带入x和4+5代入y得3+2*4+5=16。

4.结合方向:单目运算符、条件运算符、赋值运算符这3种为自右向左结合,其它均为自左向右结合。

5.唯一的三目运算符——条件运算符。格式(a<b)? a:b;

6.整型常量有三种合法进制表达:十进制数、八进制数(如012,以0为前缀)、十六进制数(如oxa3,以0x或0X为前缀)

7.实型常量只有十进制数,有两种表示形式:小数形式、指数形式,注意:小数形式要求一定要有小数点小数点前面或后面的数字可以缺省;指数形式一定要有E(或e),并且在其左边一定是合法的十进制整数或小数形式的实数右边必须是合法的十进制整数,E左右两边表达都不可以缺省

8.字符常量是以一对单引号括起的单个字符,如果以双引号作为定界符则一定不是正确的字符常量。需要特别注意的是以右\开头的转义字符的三种形式:‘\n’(右斜杠开头后跟一个特定字母)、‘\121’ (右斜杠开头后跟不超过3位八进制数所表示的ASCII码)、‘\xa5’ (右斜杠开头后跟x或X,再跟不超过2位十六进制数所表示的ASCII码),记住’A’、’a’、‘0’、‘\n’的ASCII码分别为:65、97、48、10,字符常量的大小就是其ASCII码值的大小。

9.字符串常量是以一对双“”括起的0个或多个字符,需要特别注意字符串的长度指双引号中实际字符的个数;而字符串所占的字节数为字符串长度+1,有一个’\0’作为字符串结尾的标志需要占用1字节空间

10.全局变量和static型的局部变量没做初始化,则默认初值为0

模块二:三种基本结构及流程控制

1.特殊的%s,无论scanf还是printf中,与之对应的都是地址,其他格式控制串,如:%d、%c、%lf、%f等,在scanf中用地址对应,但是在printf中用对应。(例如:char str[20]=”ABCDE”,则printf(“%s\n”,str);的输出结果是ABCDE,与%s对应的是表示字符串的首地址,输出遇到\0结尾标志就结束)

2.switch后面的表达式类型应当为整型、字符型、枚举型,而不可以是float或double型,因为表达式的取值必须是离散值;case后面必须是常量

3.如果表示条件的表达式值永远不可能为0, 则该循环为死循环。for语句的表达式2,如果表达式2缺省,则表示永真条件,就是死循环。

4.判断一个整数是否为质数(用一层循环可以解决)

函数原型:int prime(int n); 判断参数n是否为质数,如果是,返回1,如果不是,返回0。

int prime(int n)
{
	int i, j, k;
	k = (int)sqrt(n);
	for (i = 2; i <= k; i++)
		if (n % k == 0)
			return 0;
	return 1;
}

5.判断完数。(完数是指一个数恰好等于它的因子之和)

int judge(int n)
{
	int i,j=0,judge=0;
	for (i = 1; i < n; i++)
	{
		if (n % i == 0)
			j += i;
	}
	if (j == n)
		judge=1;
	return judge;
}

6.有很多函数求和的例子,但的写了。

模块三:函数

1.函数可以嵌套调用,但是不可以嵌套定义。

2.函数的返回值由首部的函数返回值类型决定,return后的表达式类型若与函数返回值类型不一致,则自动转换,将return后表达式的类型转成函数返回值类型。

3.函数通过return只能返回一个值,如果一个函数需要返回多个信息,则可以考虑借助于指针形式参数实现。

4.在主函数中定义了数组变量:int arr[20],并调用了函数f(arr),则下列关于函数f原型声明,哪几个是完全等效的______。

A、 void  f(int x[20]);

B、 void  f(int x[ ]);

Cvoid  f(int x[10 ]);  

Dvoid  f(int x);

Evoid  f(int *x);

答案:ABCE

首先要理解一维数组名作实参和形式参数传地址的实质;理解void f(int a[])中的形式参数a实质上是一个指针形式参数,也就是该函数首部可以写成:void f(int *a)或void f(int a[10] )  这里的10可以是任意整数都是完全等效的

模块四:数据类型

1.定义数组时元素个数不能用一个已有值的变量,例如:int n=10; int a[n];就是错误的定义。

#define N  3   int a[N*3];则是正确的定义。

2.字符串的输入gets,输出puts,连接strcat,复制strcpy,比较strcmp,长度strlen,转小写strlwr,转大写strupr。

3.数组定义int a[m][n],则在a[i][j]之前的元素的个数为______。

答案:i*n+j

4.可以对字符型数组进行整体输入、输出但是不可以对整型数组进行整体输入、输出。

5.已知: char *s = "student"; 则printf("%s\n", s+3)输出为____

答案:dent  

6.用字符指针操作字符串:比用字符数组操作字符串具有更大的灵活性,注意二者的区别

例:char *s=“ABC”;  char *s;  s=ABC;都是正确的

char p[4]=“ABC”;正确,但是char p[4]; p=ABC;却错误

s=p;是正确的赋值,但是s=*p,*s=AB都是错误的 

7.定义struct Point{ int x,y; }pos[ ]={{1,2},{3,4},{5,6}}, *pt=pos;则表达式(++pt)->y的值为______ ,  ++(pt->x) 的值为_________, ++pt->x 的值为______、(*pt).y的值为_____。

答案:4,2,2,2

第1,2,4空不用多说。就第三空->优先级高于++所以相当于第二空,所以它的值也是2.

8.以下对结构体变量stu中成员的非法引用是______。

struct Point

{

int x;

int y;

} pos, *p=&pos;

A、pos.x      B、(*p).y     C、p->x      D、Point.y

答案:D

模块五:文件

1.C中的文件由数据流形式组成,可按数据的存放形式分为二进制文件和文本文件。

2.C文件打开的方式:

基本方式: r(只读)、 w(只写)、a(追加) 

后面可以加上+表示可读可写(注意,如果打开一个新文件可读可写,则一定是w+;如果打开一个旧文件可读可写,则可能是r+或a+)、加上b表示打开二进制文件,否则默认是对文本文件操作。

3.fopen():打开文件                         fclose():关闭文件

fgetc():在文件里读取一个字符        fputc():写入一个字符到文件里

fgets():读取一个字符串                   fputs():写入一个字符串

fprintf():写入格式化数据                  fscanf():格式化读取数据

fread():读取数据                              fwrite():写入数据

rewind():把文件指针移到开始处      fseek():重定位文件指针

我自己的疑点:

1.选择排序:前小后大

void sort(int* a, int n)
{
	int i, k, index, temp;
	for (k = 0; k < n - 1; k++)//要排列n-1次
	{
		index = k;
		for (i = k + 1; i < n; i++)
			if (a[i] < a[index])
				index = i;//这里就对下标进行了交换
		if (index != k)
		{
			temp = a[index];
			a[index] = a[k];
			a[k] = temp;
		}//再对值进行交换
	}
}

2.链表

链表的基本构成单位是结点,结点由数据部分指针部分组成。数据部分用来存放待处理的数据,指针部分存放下一个数据的地址

单链表的建立,释放,打印(尾插法:新结点每次都插在链表的最后面):

#include<stdio.h>
#include<malloc.h>
struct Node//一个固定结构
{
	int date;//数据域
	struct Node* next;//指针域
};
typedef struct Node Node;

Node* Create()
{
	Node* head, * tail, * p;
	int num;
	head = tail = NULL;//初始化链表
	printf("请输入一组数据,以-9999结尾:\n");
	scanf("%d", &num);
	while (num != -9999)
	{
		p = (Node*)malloc(sizeof(Node));//申请动态空间
		p->date = num;//将数据存于数据域
		p->next = NULL;//将指针域赋值为空
		if (NULL == head)//如果原链表为空
		{
			head = p;
		}
		else
		{
			tail->next = p;//将新结点链入尾部,称为新结点
		}
		tail = p;//更新tail指针,指向新结点
		scanf("%d", &num);
	}
	return head;
}

void printf(Node* head)
{
	Node* p;
	p = head;//p从头指针开始
	if (head == NULL)
		printf("链表为空!\n");
	else
	{
		printf("链表如下:\n");
		while (p != NULL)//一个固定的输出结构
		{
			printf("%d", p->date);
			p = p->next;//p指向链表的下一个结点
		}
	}
	printf("\n");
}

void Release(Node* head)
{
	Node* p1, * p2;
	p1 = head;
	while (p1 != NULL)//用p1来控制循环,p2来进行结点的删除	
	{
		p2 = p1;
		p1 = p1->next;
		free(p2);
	}
	printf("链表释放内存成功!\n");
}

int main()
{
	Node* head;
	head = Create();
	printf(head);
	Release(head);
	return 0;
}

链表的删除:

Node* Delete(Node* head, int num)//num为待删除数据
{
	Node* p1, * p2;
	if (NULL == head)
	{
		printf("链表为空!\n");
		return head;
	}
	p1 = head;
	while (p1->next && p1->date != num)//在链表中找指定数据
	{
		p2 = p1;//用p2记下p1的位置
		p1 = p1->next;//p1指针向后移
	}
	if (p1->date == num)//找到了
	{
		if (head == p1)//如果删除的是第一个结点
		{
			head = p1->next;
		}
		else
		{
			p2->next = p1->next;//如果不是第一个结点执行此操作就可以将p1脱去
		}
		free(p1);//最后记得一定要释放掉删除数据的空间
		printf("删除成功!\n");
	}
	else
		printf("链表中无此数据!\n");
	return head;
}

链表的插入:(仍保持从小到大的排序)

Node* Insert(Node* head, int num)//num是要插入的数
{
	Node* p, * p1, * p2;
	p = (Node*)malloc(sizeof(Node));//为插入的数据申请空间
	p->date = num;
	p->next = NULL;
	p1 = head;//需要一个指针指向头指针
	while (p1 && p->date > p1->date)//确定插入位置
	{
		p2 = p1;
		p1 = p1->next;
	}//固定结构
	if (p1 = head)
	{
		head = p;
	}
	else
	{
		p2->next = p;//上面p2和p1一直是连在一起的,p2在p1前面。
现在while语句不成立后就在p2后面插入p
	}
	p -> next = p1;
	printf("数据插入成功!\n");
	return head;
}

3.编写一个函数lowprice统计所有商品中价格低于最高价50%的所有商品的个数。函数原型是int Lowprice(float *pa,int n);

int Lowprice(float* pa, int n)
{
	int i,sum=0;
	float max = pa[0];//这个获得最大值的函数也好久没见到了,理解起来不难
	for (i = 1; i < n; i++)
		if (max < pa[i])
			max = pa[i];
	for (i = 0; i < n; i++)
	{
		if (pa[i] < 0.5 * max)
			sum++;
	}
	return sum;
}

4.if(x=0),接下来的if后面的内容就不会执行了

5.switch语句中如果 case 语句不包含 break,控制流将会 继续 后续的 case,直到遇到 break 为止。

6.要对字符串进行遍历终止的条件是str[i]!='\0';如果新建了一个新的字符串需要在最后加上str[i]='\0';

7.sizeof一个指针的大小是4,sizeof一个数组的大小是数组的长度,与其中的元素无关。sizeof一个字符串的长度最后结果要加一。strlen一个数组得到的就是其中字符串的长度。一个数组占用的字节数是它的变量类型占的字节数*数组的长度。

8.在链表中删除了一个元素后一定要记得释放掉它的空间。(free(p1);)

9.打印九九加法表

int main()
{
	int i, j;
	for (i = 1; i <= 9; i++)
	{
		for (j = 1; j < i; j++)
		{
			printf("%d+%d=%d", i, j, i + j);
		}
		printf("\n");
	}
	return 0;
}

10.编写1个程序,将D:\abc.txt文件(事先通过记事本建立)中的数字字符复制到D:\def.txt文件中,英文字符输出到屏幕上。

int main()
{
	FILE* fin, * fout;
	char ch;
	fin = fopen("D:\\abc.txt", "r");
	fout = fopen("D:\\def.txt", "w");
	if (!fin||!fout)
	{
		printf("open file error!\n");
		exit(1);
	}
	ch = fgetc(fin);
	while (!feof(fin))
	{
		if (ch >= '0' && ch <= '9')
			fputc(ch, fout);
		else
		{
			if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
				putchar(ch);
		}
		ch = fgetc(fin);
	}
	fclose(fin);
	fclose(fout);
	return 0;
}

11.char a;int b;float c;double d;则a*b+d-c的结果类型是double型。

char<int<long<float<double所以向更高的方向转化。

12.fun((exp1,exp2),(exp3,exp4,exp5))含有2个实参,看的是括号的个数。

13.*p++与p++道理上一样,*p++虽然值上发生了变化,但是输出的还是原来的值。

14.C语言的预处理命令包括include.define,ifdef,但是不包括typedef.

15.

int main()
{
	char s1[20] = "abc\0def";
	char s2[30];
	strcpy(s2, s1);
	printf("%d %d %s", strlen(s1), sizeof(s1), s1);
	printf("%d %d %s\n", strlen(s2), sizeof(s2), s2);
	return 0;
}

代码的执行结果:3 20 abc 2 30 def;

strlen遇到'\0'就结束了所以长度为3.

  • 19
    点赞
  • 125
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值