课本笔记记录

  • 注意printf的输出格式:%d %o %x
  • 不要轻易在scanf中加换行符 scanf(“%d\n”) 按回车输入不了
  • f六位小数 不足补零
  • m指定输出宽度 小数点也战一位
  • .n输出n位小数
  • 0~127的范围内,整数和char可以通用
  • “A”:65 “Z”:90
    -“a”:97 “z”:122
  • getchar() 读入一个字符 反之是putchar(ch)
    getchar()会接收回车符,ASCll为10 需要多用一个getchar将其吸收
  • 数字字符转换数字 c-‘0’
    数字转换成数字字符 c+‘0’

    大转小 ch+32 或 ch-‘A’+a
  • 循环读入多行字符:(c=getchar() != EOF)
  • 数组只能在声明的同时初始化 分开写不对
  • 字符串的最后一个字符:空字符(“\0”)ASSll: 0
    空白符(空格符):32、水平制表符:9、回车符:13
  • 字符串输出:printf(“%s”,str)、puts(str)
  • 字符串输入:scanf(遇到空格符结束,可以输入多个参数)、gets(可以读取空格,遇到换行符结束,只能输入一个参数)、fgets(str, strlen, 文件指针) != NULL,文件指针处改为stdin从键盘输入
  • fscanf:从文件输入而不是键盘 fprintf:输出到文件而不是屏幕(txt文件操作)
    相比起scanf和printf只多了第一个参数,传入文件指针表示对什么文件进行操作
#include<stdio.h>
#include<stdlib.h>
//键盘输入存储学生信息到txt文件
int main() {
	char stuid[10], name[20];
	float score;
	FILE* fp;
	if ((fp = fopen("E:\\score.txt", "w")) == NULL) {
		exit(0);
		printf("文件打开失败!");
	}
	fprintf(fp, "学号\t姓名\t入学成绩\n");
	for (int i = 0; i < 2; i++) {
		printf("请输入学生学号姓名和入学成绩(空格隔开):");
		scanf("%s%s%f", &stuid, &name, &score);//键盘到文件
		//注意此处输出格式要用\t \n来调整格式
		fprintf(fp, "%s\t%s\t%f\n", stuid, name, score);//输出到文件
	}
	fclose(fp);
}

在这里插入图片描述

删掉第一行的中文后读取

while (fscanf(output, "%s%s%f", &stuid, &name, &score) != EOF) {
		printf("%s\t%s\t%\n", stuid, name, score);
	}

四、运算符和表达式

1、优先级:

  • 常用优先级(大到小):自增++ 、大于 、 !=、&& 、|| 、条件三目 、+= 、逗号。同等地位则左结合(除了自增三元赋值)
  • 1 || 0 && 0 --> &&的优先级比||高 等价于 1 || ( 0 && 0 ) 1已经为真 ||短路右边不执行 答:1
  • 0 && 0 || 1 等价于 ( 0 && 0 ) || 1, ||前部分为0 但不出现短路,最后值为1.而不是&&短路。 总结:当&&和||同时出现需要先考虑优先级用括号括起,再去考虑短路
  • 注意赋值符号导致的变量的值中途改变 如:x=1时、 x += x += x+1的值为6 、和a=b, b=c,c=d和表达式的结合,还有和类型转换截断 (int)3.14 的组合
  • a*b\2 从左到右 、a+(b++) 的括号可有可无,都是先进行加法后再自增
  • char必须转换成int,‘a’+‘b’=195,同时注意float的六位小数位
  • (double)a/2 先执行类型转换
	int x,y;
	printf("%d", 0 || 8!=5 && 8  );
	//优先级:!= > && > ||     
	0 || ((8!=5) && 8) --> 0 || (1 && 8) -->  1
	
	int x,y;
	printf("%d", (x = 1, y = 2, x++, y++, x + y));//5 逗号表达式优先级最低
	//故要等所有都执行完才执行逗号表达式,相当于从头到尾都执行了一遍
	
	int x=0,y=0;
	printf("%d", x += 1 != x > y); 
	//x = x + (1 != (x > y))
	// x = x+ (1 != 0) 
	// x = x+1 
	// x=1
	//优先级:大于小于 > !=  > 赋值+=   

2、逗号表达式:

在这里插入图片描述

	int x = 0, y = 0,z=0;
	(x, y, z) = (1, 2, 3);//相当于两个逗号表达式,等价z=3
	printf("%d、%d、%d", x, y, z);//0  0  3只有z赋到了值
	x=(x, y, z) = (1, 2, 3);//把z的值3赋给了x
	printf("%d、%d、%d", x,y,z);//3  0  3
 	
 	int x = 0, y = 0,z=0;
	(x, y, z = 1, 2, 3);//把z的值3赋给了x
	//先执行z=1,由于没有赋值,逗号表达式的结果3没有保存
	printf("%d、%d、%d\n", x, y, z);//0 0 1
	x = (x, y, z = 1, 2, 3);
	printf("%d、%d、%d\n", x, y, z);//3 0 1
	x = 0, y = 0, z = 0;
	//逗号表达式的值为3-0 然后才赋值给3,而不是逗号表达式里为x赋值3
	x = (x, y, z= 1, 2,3) -x;
	printf("%d、%d、%d\n", x, y, z);//3 0 1
	



五. 分支结构

  • 海伦公式:由三角形边长a、b、c, 半周长h 得面积S=sqrt( h*(h-a)*(h-b)*(h-c) )
  • 椭圆公式、平闰年(%100!=0)、构成三角形的条件
  • else一定要和最近的if配对 (找错)



六、循环结构程序基本算法

1、课本例题

1-1、判断一个数是否为素数

//此方法判断输入的数是否是素数
int flag(int n) {
	int i, k;
	k = sqrt(n);//对输入的数开根号
	for (i = 2; i <= k; i++) {
		if (n % i == 0) {
			break;
		}
	}
	if (i>k){//排除i=k的的情况
		return 1;
	}else{
		return 0;
	}
}

1- 2、数列求和

//计算1/2 + 3/2 + 5/3 + 8/5 +...
int main(){
	int sum,t,x=1,y=2;
	for (int i = 1; i < 10; i++) {
		sum += i;
		t = x; x = x + y; y = x;//前一个的分母是下一个的分子,前一个的分子+分母是下一个的分母
	}
}

1-3、三角形打印

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1-4、一维数组杨辉三角(不会)

#include<stdio.h>
#define N 6
/*
1、一维数组打印杨辉三角
*/
void one() {
	int a[N + 1], i, j;
	a[1] = 1;
	printf("%d\n", a[1]);
	for (i = 2; i <= N; i++) {
		a[i] = 1;
		//计算第二行开始的除了两端的数字
		for (j = i - 1; j >= 2; j--) {//第三行才进入
			//1 1   
			//1 2 1   2来自其上一次执行的同样位置的元素和其之前元素之和
			a[j] = a[j] + a[j - 1];
		}
		
		//每计算一行数据打印一行  <i:需要多少打印多少
		for (j = 1; j < i; j++) {
			printf("%d ", a[j]);
		}
		printf("\n");
	}
}
int main(){
	one();
}

1-5、牛顿迭代法(不会)

牛顿迭代法计算x平方=a的解,即计算根号a的值
x = 1 +( a - 1 ) / ( x + 1 )

1-6、文本文件字符统计(重点

  • 一个个字符读取的方式,统计出现次数用数组
int main(){
	FILE* fp;
	char ch, count[128];
	while (ch = (fgetc(fp)) != EOF) {
		count[ch]++; //对应位置自增
	}
}

2、课后习题

2-1、程序阅读题

#include <stdio.h>
int main()(
	char str[20]="azdwgtjqmn";
	int i,count=0;
	for (i=0; str[i]!='\0'; i++){
		str[i]+=4;
		if (str[i]>'z') str[i]-=26;
		count++;
	}
	printf("str[%d]=%s\n", count, str);
	return 0;
}

注意阿斯克码对应得字母全写成小写,Q写q 全部列出来

2-2、程序填空题

(1) 打印上下三角形

在这里插入图片描述

(2) 冒泡变形
while (i <= N)
		printf("%d, ",/*第4个空*/ a[i++]);

使用i++避免死循环,用for则不需要,但while打印图形的代码更加简洁

2-4(6)同构数

#include<stdio.h>

//找出同构数  6->36   25->625
//同时取两者的个位,依次比较,当两者比较完后,如果较小的数能除尽说明是同构
int main() {
	int i, j, t, k;
	for (int i = 1; i <= 1000; i++) {
		t = i;
		k = i * i;
		while (t) {
			if (k % 10 != t % 10) break;
			else {
				k = k / 10;
				t = t / 10;
			}
		}
		if (t == 0) {
			printf("%d %d\n", i, i * i);
		}
	}
}


七、函数与结构化程序设计

1、课本例题

1-1、求组合数(公式重要

在这里插入图片描述

//计算n的阶乘
long factorial(int n) {
	int i;
	long s = 1;
	for (i = 1; i <= n; i++) {
		s = s * i;
	}
	return s;
}

本质是三个阶乘的乘除 ,将共性抽取,大的n在上面 下的k在下面做分母,位置互换

1-2、判断素数方法

#include <math.h>
int prime(int n) {
	int num,flag=1;
	if (n == 1) {
		return 0;
	}
	num = sqrt(n);
	for (int i = 2; i < num; i++) {
		if (num % i == 0) {//不是素数
			flag=0;
			break;//找到了就退出
		}
	}
	return flag;
}

程序最好只有一个出口,不要设置多个return

int fun(float x,float,y){
	return (x*y);
}

注意此时返回的值要转换成int

值传递:实参赋值给形参 ,但不会影响各自的值,互相独立,形参值改变,主函数实参不变

1-3、两个正整数的最大公约数(方法重要

#include <stdio.h>
int div(int a,int b ) {
	int r, t;
	if (a < b) t = a, a = b, b = t;
	if (b > 0) {//保证被除数大于零
		while ((r = a % b) != 0) {
			a = b, b = r;//上一次的结果成为被除数
		}
	}
}

1-4、随机数(方法重要

#include <stdio.h>
#include<random>
//产生[low,high]之间的随机数 
int random(int low,int high ) {
	int k = rand() % (high - low + 1);//[0,high-low]
	return low + k;//[low,high]
}

1-5、递归调用过程(思想重要

#include <stdio.h>
void fun1(int n) {
	if (n >= 10) {
		fun1(n / 10);//先逐级调用,再回代过程中才顺序执行打印语句
	}
	printf("%d, ", n%10);
}

void fun2(int n) {
	printf("%d, ", n % 10);//调用之前就打印了,和回代无关
	if (n >= 10) {
		fun2(n / 10);
	}
}
int main() {
	fun1(567);
	printf("\n");
	fun2(567);
}

函数调用结束返回的时候,要注意返回哪一层
如果函数递归了,相当于阻塞了其之后下面的代码。要等其调用完之后,才从当前结果逐层返回回去

1-6、递归 实现斐波那契数列(重要

#include <stdio.h>
//1 1 2 3 5 8..  第三项开始是前两项之和
long Fibo(int n) {
	long value;
	if (n == 1 || n == 2) //1、2项都等于1
		value = 1;
	else
		value = Fibo(n - 1) + Fibo(n - 2);//第三项为  f(1) + f(2) = 2
	//注意是n-2和n-1
	return value;
}

1-7、递归 求一维数组最大值==(重要)==

#include <stdio.h>
//a={1,2,3,4} 3     a数组中前n项的最大值
int max(int a[],int n) {
	int value;
	//递归到最后把数组初值给了value
	if (n == 0) value = a[0];
	else {
		value = max(a, n - 1);//卡住,当n=1时才进行会回代执行下面代码
		//n依次为1 2 3
		if (a[n] > value) {
			value = a[n];
		}
	}	
}

1-8、宏定义的形式参数运算

#define L(a,b,c) a+b+c
x=6*L(3,4,5) // 成了6*3+4+5  要在宏定义处加括号此处才会有括号

2、课后习题

2-1、最大公约数和最小公倍数 (记住)

  • 最大公约数:辗转相除法,余数做下一次的除数(根号后面的数)
  • 最小公倍数 = 两数乘积 / 最大公约数
#include <stdio.h>
int max(int a,int b) {
	//保证传入的a是两数大的一方
	int r,t;
	if (a < b) {
		t = a; a = b; b = t;
	}
	//除数大于0才除
	if (b > 0) {
		while ((r = a % b) != 0) {
			//除数变成被除数,余数变成下一次的除数
			a = b; b = r;
		}
	}
}

//最小公倍数 = 两数乘积 / 最大公约数
int min(int a, int b) {
	int x;
	x = a * b / max(a, b);
}

2-2、最大素数因子

  • 质数(素数):只能被1和其本身相除的数 但1何其本身不是素数
#include <stdio.h>
#include<math.h>
//判断质数(素数):只能被1和其本身相除的数 但1何其本身不是素数
int isNum(int n) {
	int m = sqrt(n);
	for (int j = 2; j <= m; j++)
	{
		if (n % j == 0)
		{
			return 0;
		}
	}
	return 1;
}
int main() {
	int num, max=0, count = 0;
	printf("请输入一个正整数:");
	scanf("%d", &num);
	for (int i = 1; i <= num; i++)
	{
		if (num % i == 0)//最大质数能整除
		{
			if (isNum(i))
			{
				if (i>max) {
					max = i;
				}
			}
		}
	}
	printf("最大的素数因子是:%d", max);
	return 0;
}

2-3、递归-求整数幂 (不会)

#include <stdio.h>
int power(int n, int d) {
	if (d == 0) {
		return 1;
	}
		return n*power(n, d - 1);
}
// n*
// n*n*
// n*n*n*
// n*n*n*1
// 把大问题拆分成小问题,把小问题拼接成大问题,确定终止条件
int main() {
	int num =power(3, 3);
	printf("%d", num);
}

2-4、递归-求两数最大公约数 (不会)

  • 公约数就是公因数 辗转相除法
#include <stdio.h>
int max(int m, int n) {
	if (n == 0) return m;
	//不断处理除数和被除数,直到被除数为0,返回上一次的除数
	//如48 ÷ 36 = 1...12
	//36 ÷ 12 = 0  12是最大除数
	return max(n, m % n);
}

2-5、递归-返回指定数字 (不会)

  • 编写递归函数 digt(n,j),它返回整数n从右边开始的第j位数字。例如:
    digit(25364,4)=5
    digit(25634,3)=6
#include <stdio.h>
int digit(int n, int j) {
	if (j == 1) {
		return n % 10;
	}
	return digit(n / 10, j-1);
	
}

int main() {
	int num = digit(25634,4);
	printf("%d", num);
}

递归方法总结

1、将问题拆解,如求幂拆解成n*n, 斐波那契是(n-1,n-2),公约数是将除数变成余数,被除数变成除数
2、拆解的小问题是递归传值的参数,如公约数是每次都要传入,而幂是进行×n运算
3、确认最后的终止条件,幂函数是次方为0了就停了,公约数是余数为0就停



八、指针与数组

1、课本例题

1-1、固定格式文本文件读取(以fgetc(fp)的形式)(重要)

  • 172200100;Lin Daihua;128;116;82;275;172200101;Lai Baichi;100;126;92;285;172200102;Wu Jiaxu;168;126;92;255;
#include <stdio.h>
#include<stdlib.h>
FILE* fp;
//此方法用于一个个字符串读取,当符合条件存入字符数组中,以;作为单位读取
//比起scanf更容易操作但代码量稍多
int read_flag(char* p) {
	//从文件中读取一个字符
	char ch = fgetc(fp);
	while (ch == ' ' || ch == '\t' || ch == '\n') {
		ch = fgetc(fp);//自动读取下一位 实现跳过空白符的作用
	}
	while (ch != EOF && ch != ';') {
		*p++ = ch;//存储进空字符串中
		ch = fgetc(fp);
	}
	*p = '\0';//形成字符串
	if (ch == EOF) return 0;//代表文件已经读到尾部了
	else return 1;//还有下个学生可以读
}
int main() {
	char str[30];
	float sum, score, maxsum;
	int order=0; //记录当前读取的是第几个属性值
	if ((fp = fopen("D:\\score.txt", "r")) == NULL) {
		printf("打开文件失败!");
		exit(0);
	}
	sum = 0.0, maxsum = 0.0;
	while (read_flag(str) ){
		if (order % 6 <= 1) {//姓名学号
			printf("%s ", str);
		}
		else if (order % 6 <= 5) {//四门成绩
			score = atof(str);//将字符串转换成浮点数
			sum += score;
			printf("%.2f ", sum);
			if (order % 6 == 5) {
				printf("%.f\n", sum);
				if (sum > maxsum)maxsum = sum;
				sum = 0.0;
			}
		}
		order++;
	}
}

补充:fscanf通配符方式读取 (重要!!)

  • % [^; ] 读取到;为止,不包括;
  • %[^1-9A-Z] 读取到1-9和A-Z后才终止存储到对应变量中,可以用来屏蔽中间的空格
int main(int argc,char *argv[]) {
	char buf[100],name[20];
	int id,age,s1,s2,s3,s4;
	FILE* fp;
	fp = fopen("D:\\score.txt", "r");

	//172200100; Lin Daihua; 128; 116; 82; 275;
	while (fscanf(fp, "%d;%[^;];%d;%d;%d;%d;",&id,&name,&s1,&s2,&s3,&s4) != EOF) {
		printf("%d、%s、%d、%d、%d、%d\n", id, name, s1, s2, s3, s4);
	}
	/*
	读取格式:172200100;Lin Daihua;128;
	通配符:     %d    ;  %[^;]   ; %d;
	*/
	
	//% [^; ] 读取到;为止,不包括;
	//%[^1-9A-Z] 读取到1~9和A~Z后终止
}

1-2、二维数组打印杨辉三角

#include <stdio.h>
int main() {
	int a[5][5],i,j;

	//先打印每行的开头和结尾的1
	for (i = 0; i < 5; i++){
		a[i][0] = a[i][i] = 1;
	}
	//从第三行开始打印内部元素  注意起点
	for (i = 2; i < 5; i++) {
		for (j = 1; j < i; j++) {
			a[i][j] = a[i-1][j]+a[i-1][j-1];
		}
	}

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

1-3、行指针,元素指针,元素间的关系 (重要)

在这里插入图片描述

  • 二维数组名a 默认是行指针(一维数组数组名是元素指针)
  • 做加减法时,当a是行指针时,a+1时候默认跳过一行,而不是一个元素。
  • 第k个元素的元素指针都是和列进行除法和取余运算
  • a【0】是一维数组数组名,即首元素地址,元素指针,&a【i】才是行指针
  • *a是行指针解引用,取出的是元素指针
  • 加法和【】的替换 如:((a+i)+j)~a[i][j]
    (a[0]+iN+j)的N是列

1-4、字符串处理函数 (特别重要!)

  • 求字符串长度strlen(str):遇到‘\0’就终止,其不包括在长度内
#include <stdio.h>
#include<string.h>
int main() {
	char str[20] = "\t\v\\\0will\n"; //3  t v \
	char str2[30] = "\x68\082\n"; //1  x68 十六位进制数		\1\2\3长度为3
	printf("%d、%d", strlen(str), strlen(str2));
}
  • 字符串拼接 strcat(str1,str2):将2拼接到1的末尾.
    必须保证str1的容量足够大,拼接前都有\0,拼接后只有一个\0
  • ==字符串赋值 strcpy(str1,str2),将2中的复制到1中去,调用成功返回str1的起始地址 ==
    strncpy: 在原有基础上多加了个n,可指定赋值前几位字符,但需要手动添加’\0’
#include <stdio.h>
#include<string.h>
int main() {
	char str1[20] = "星期一";
	char str2[30] = "星期六"; 
	strcpy(str1, str2); //成功返回str1的起始地址
	puts(str1);//星期六
	//字符串的赋值不能用 str1 = str2,因为常量不可修改
	//只能通过strcpy进行覆盖

	strncpy(str1, "Sunday", 3);//将Sun赋给str1
	str1[3] = '\0';//手动添加结束符
	puts(str1);
}
  • 字符串比较 strcmp(str1,str2)
    将两个字符串自左至右逐个字符比较(根据ASCII码大小)直到出现不同字符或遇到‘\0’
    str1=str2 0
    srr1>str2 正数 反之负数,换句话说就是strcmp(str1,str2)>0 说明前面的数字大
    字符串的比较不能用”==“ 比的是地址
    字符串的赋值和比较要用方法

1-5、指针找错

  • 注意在循环中对指针进行操作,要将移动到末尾的指针要重新移动回首地址
  • 实参和形参是指针时,形参会间接影响实际的变量值,但还是值传递。同时注意其他形参都不能改变实际的值,只有传的是指针才可以。
  • 指针作为函数的实参,要传的是地址,注意加取地址符

1-6、将两个升序数组合并成一个

#include <stdio.h>

//传入两个升序数组合并成一个新数组z
void merge_sort(int* x, int lenx, int*y,int leny,int *z) {
	int i, j, k;
	//将xy两个数组逐个元素进行比较
	while (i < lenx && j<leny) {
		if (x[i] < y[j]) {
			z[k++] = x[i++];
		}
		else {
			z[k++] = x[j++];
		}
	}
	//把剩余元素全部存入余下的数组z中
	while (i < lenx) {
		z[k++] = x[i++];
	}
	while (j < leny) {
		z[k++] = x[j++];
	}
}

1-7、实现strcmp的功能

int strcmp02(char* ch1, char* ch2) {
	while (ch1 && ch2 ) {
		if (*ch1 == *ch2) {
			ch1++;
			ch2++;
		}
		else {
			break;
		}
	}
	return (*ch1 - *ch2);
}

1-8、字符串匹配

  • 核心:用下标,母串每次比较完成一次后移动一位,子串置空
  • 补充1:strstr(str, substr):返回第一次出现子串的地址
  • 补充2:strchr(str,ch) 返回字符ch第一次出现的地址
#include <stdio.h>
#include<string.h>
//找出子串在母串第一次出现的位置
int index(char*s, char*t,int start) {
	int m, n,i,j;
	m = strlen(s);
	n = strlen(t);
	if (start < 0 ||  n==0) {
		return -1;
	}
	while (i<m && j<n) {
		if (s[i] == t[j]) { i++; j++; }
		//核心代码,母串移动一位,子串置空
		else { i = i - j + 1; j = 0; }
	}
	//如果比较的长度等于子串长度
	if (j == n) return i - n;//返回位置
	else return -1;	
}

1-7、二维数组做参数

//此时的实参为两个一维数组数组名
int fun1(int x[],int y[]) {} //等价于int *x,int *y

//此时实参为二维数组名+0(行指针),一维数组数组名(元素指针) 
int fun2(int (*x)[3], int *y) {} //等价于int x[][3],int y[]
//注意使用的时候需要将x解引用得到元素指针,
//在做加法得到每个元素指针再解引用得到每个元素

1-8、返回指针的函数

  • 如果返回的指针是指向那个函数中的变量,则可能会出错,如下:
//此时的实参为两个一维数组数组名
int* max(int *p) {
	int m = *p; return &m; //指向max函数中声明的变量,可能出错
	int* q = p; return q; //要用指针存储形参指针而不是变量
}

1-9、字符串数组的排序

  • 运用指针数组 char *arr[] = {“str1”, “str2”, “str3”…};实现对字符串数组的排序 ,其还有另一种写法**p。存储指针的数据,每个指针指向一个字符串,然后用选择排序(第0个字符和第1,2,3个比较,以此类推选出最小),注意比较要用strcmp逐个字符比较

1-10、main函数的形参及文件复制(逐个复制方法重要!

#include <stdio.h>
/*
	输入格式:命令名 参数1 参数2...
	例如:输入COPY C:\old.txt D:\new.txt
	argc获得整数值3  代表有三个数
	argv[0]=COPY、argv[1]=C:\old.txt、argv[2]=C:\new.txt
*/
int main(int argc,char *argv[]) {
	FILE* fp1, * fp2;
	char ch;
	if (argc != 3) {//说明格式不对
		printf("格式:cp 源文件名 目标文件名");
	}
	fp1 = fopen(argv[1], "r");//源文件读
	fp2 = fopen(argv[2], "w");//目标文件写出

	while ((ch = fgetc(fp1)) != NULL) {//逐个读取源文件字符
		putc(ch,fp2);//每读取一个写出一个
	}
}

2、课后习题

2-1、行指针的写法 (错了

#include<string.h>
int main() {
	char str[20], s[3][20];
	for (int i = 0; i < 3; i++) {
		gets(s+i);
		gets(&s[i]);
		//要填行指针,而不是s[i][20]
	}
}

2-2、子母串比较的另一种形式(错了

#include <stdio.h>
int at(char* substr, char* str) {
	int i, j, post;
	//通过引入新的变量post实现母串的自增
	//post没使用过要想到怎么使用
	for (post = 0; str[post] != '\0'; post++)
	{
		//母串每次自增到下一位
		i = 0; j = /*第2空*/post;
		while (substr[i] != '\0' && substr[i] == str[j])
		{
			i++;
			j++;
		}
		if (substr[i] == '\0')
		{
			return /*第3空*/post + 1;//下标从0开始,正常序号要+1
		}
	}
	return 0;
}

2-3、结构体实现学生排序

  • 先按照第一门成绩排,再按照第二门排,最后按照学号排
#include<stdio.h>
#define N 6
struct stu {
    int id;
    int scores[4];
}s[6];

int main() {
    FILE* fp;
    fp = fopen("D://score.txt", "r");
    stu t;
    int i, j, k;
    //读取文件数据进结构体数组中
    for (i = 0; i < N; i++) {
        fscanf(fp, "%d %d %d %d %d", &s[i].id, &s[i].scores[0], &s[i].scores[1], &s[i].scores[2], &s[i].scores[3]);
    }

    printf("排序前:\n");
    for (i = 0; i < N; i++) {
        printf("%d %d %d %d %d\n", s[i].id, s[i].scores[0], s[i].scores[1], s[i].scores[2], s[i].scores[3]);
    }


    for (i = 0; i < N; i++) {
        k = i;
        for (j = i+1; j < N; j++) {
            if (s[j].scores[0] > s[k].scores[0]) {
               k = j;//记录第一门课成绩最大的学生
            }
            else if (s[j].scores[0] == s[k].scores[0]) {//第一门课相等
                if (s[j].scores[1] > s[k].scores[1]) {
                    k = j;//更改k值记录第二门课最大的学生
                }
                else if (s[j].scores[1] == s[k].scores[1]) {//第二门课相等
                    if (s[j].id < s[i].id) {//学号小的在前面
                        k = j;//更改k值记录学号最大的学生
                    }
                }
            }
        }
        //交换两个学生
        if (k!= i) {
            t = s[i]; s[i] = s[k]; s[k] = t;
        }

    }

    printf("排序后:\n");
    for (int i = 0; i < N; i++) {
        printf("%d %d %d %d %d\n", s[i].id, s[i].scores[0], s[i].scores[1], s[i].scores[2], s[i].scores[3]);
    }
}

掌握选择排序 循环i之后的元素,每次找出最大就交换

2-4、二维数组的鞍点

  • 重点再倒数第二个if,代表第二个for顺利比较完成,没有发生值的交换
#include<stdio.h>

int main()
{
	int i, j;
	int arr[3][3] = { 0 };
	int max = 0;
	int flag = 0;//如果找到了鞍点给它赋值 1 
	
	int arr[3][3] = { 1,2,3,4,5,6,7,8,9 };

	//找鞍点
	for (i = 0; i < 3; i++)
	{
		//让max等于二维数组第 i 行的第一个元素
		max = arr[i][0];

		//记录最大值所在的列
		int t = 0;

		//找出一行中的最大值并把值赋给 max
		for (j = 1; j < 3; j++)
		{
			if (arr[i][j] > max)
			{
				max = arr[i][j];
				t = j;
			}
		}

		//判断 max 是否为该列上最小的元素
		for (j = 0; j < 3; j++)
		{
			//上边的 t 记录了 max 所在的列
			//所以用 max 与该列的元素比较,看 max 是否为该列上最小的元素
			if (max > arr[j][t])
			{
				//如果大于就跳出
				break;

			}
		}
		//如果全部比较完(也就是j==3的时候)说明 max 为当列最小,max为鞍点

		if (j == 3)
		{
			printf("找到了鞍点在:%d行%d列,为%d\n", i, j, arr[i][t]);
			flag = 1;
			break;//因为只有一个鞍点,所以找到了就退出循环
		}
	}

	if (flag != 1)
	{
		printf("没有找到鞍点 \n");
	}
	return 0;
}

十进制转十六进制

#include <stdio.h>

void func(int n, char buf[])
{
	if (n < 16)//n==0
		printf("0x");
	else
		func(n / 16, buf); //递归运算
	printf("%c", buf[n % 16]); //查字库输出对应的字符
}

int main()
{
	int n;
	char buf[17] = "0123456789ABCDEF"; //创建十六进制字库
	printf("输入一个十进制正整数:");
	scanf("%d", &n);
	printf("转换成十六进制:");
	func(n, buf); //调用递归函数来转换成十六进制输出
	return 0;
}

模考卷

第一套

1、int i=1, j=8;求表达式:i+(j%4!=0)的值。 ==#注意%是取余数,/不看余数==

在这里插入图片描述

在这里插入图片描述在这里插入图片描述

编程题

一、删除后按原次序组成最小

  • 请在整数 n=742683613984 中删除 8 个数字, 使得余下的数字按原次序组成 的新数最小。
#include<stdio.h>
#include<string.h>
int main(){
	int i, j, t, flag;
	char a[30] = "43612", c;
	t = strlen(a);
	while (strlen(a) > 4)
	{
		flag = 0;
		//获得每个下标
		for (i = 0; i < strlen(a) - 1; i++)//7
		{
			//后面的比前面的数大,不大则继续找下一对
			if (a[i] > a[i + 1])//7>4
			{

				flag = 1;
				//从较大数的下标开始,将其之后的元素重新存入数组中
				//相当于整个数组左移了一位
				for (j = i; j < strlen(a) - 1; j++)
					a[j] = a[j + 1];//4268... 替换掉了一开始的最大数7
				a[--t] = '\0';//字符数组结束符
			}
			//标志发生了一次替换
			if (flag == 1)
				break;
		}
		//替换完成
		if (flag == 0)
			break;
	}
	for (int j = 0; j < 4; j++)
		printf("%c", a[j]);
	printf("\n");
	return 0;
}
/*
	转换成字符数组进行操作
	找四位数
	先从头到尾开始找最小的数 A
	两两进行比较,如果后一个数比前一个数还要小,就把整个数组往前移动一位
	找四位数,for循环用于每次剔除元素,直到无法提出
	注意flag的变化
*/


二、自恋数

  • 设计一个程序, 输出 1~99999 的所有自恋数。自恋数:当一个 n 位数的所有数位上数字的 n 次方和等于这个数本身。如 1, 2, 3, …, 9 是自恋数。
#include<stdio.h>
#include<math.h>
/*
设计一个程序, 输出 1~99999 的所有自恋数。
自恋数:当一个 n 位数的所有数位上数字的 n 次方和等于这个数本身。如 1, 2, 3, ..., 9 是自恋数。
*/
//获取位数 
int digtal(int n) {
	int d = 0;
	while (n > 0) {
		d++;
		n = n / 10;
	}
	return d;
}
int main(){
	int d,i,j,sum=0;
	for (i = 1; i < 99999; i++) {
		d = digtal(i);
		j=i;
		while (j > 0) {
			//获取所有数位上数字的 n 次方和
			sum += pow(j % 10,d);
			j = j / 10;
		}
		if (sum == i) {
			printf("%d是自恋数\n", i);
		}
		d = 0;
		sum = 0;
	}
}
拓展一:同构数
  • 输出 2~1000之间的所有同构数,所谓同构数是指它出现在它的平方数的右端。
    例如,5、6、25 的平方分别等于 25、36、625,所以5,6和 25 都是同构数。
#include<stdio.h>
int static sum2 = 0;//注意要是全局变量
int total(int target,int count) {
	if (count > 0)
	{
		递归实现逆序输出  不使用则是顺序输出得52
		total(target / 10, count - 1);
		sum2 = sum2*10 + target % 10;
	}
	return sum2;
}
int main() {
	int i, j, k, count=0, sum;
	for (i = 2; i < 1000; i++)
	{
		k = i;     
		while (k > 0) //判断所找的数是一个几位数
		{
			count++;
			k = k / 10;
		}
		j = i * i;
		sum = 0;
		//计算同构数
		sum = total(j,count);
		if (sum == i)
		{
			printf("%d的平方是%d,%d是同构数!\n", i,j,i);
		}
		count = 0;
		sum2 = 0;
	}
	return 0;
}

2、等比数
#include<stdio.h>
#include<math.h>
void repeat(int *p,int n) {
	for (int a = 0; a < 3; a++)
	{
		p[n % 10]=1;
		n /= 10;
	}
}
int allUse(int *q) {
	for (int f = 1; f < 10; f++)
	{
		if (q[f] != 1)
			return 0;
	}
	return 1;
}
int main() {
	for (int i = 123; i <= 987; i++)
	{
		for (int j = 123; j <= 987; j++)
		{
			for (int k = 123; k < 987; k++)
			{
				if (i*2 == j && i*3 == k) {
					int num[10] = { 0 };
					repeat(num, i);
					repeat(num, j);
					repeat(num, k);
					if (allUse(num) == 1)
						printf("%d %d %d\n", i, j, k);
				}
					
			}
		}
	}
	return 0;
}



三、合并文件信息将其排序

  • 有两个磁盘⽂件 A.txt 和 B.txt, 各存放⼀⾏字母, 今要求把这两个⽂件中
    的信息合并(按字母顺序排列), 输出到新⽂件 C.txt 中。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
/*
3、有两个磁盘⽂件 A.txt 和 B.txt, 各存放⼀⾏字母, 今要求把这两个⽂件中
的信息合并(按字母顺序排列), 输出到新⽂件 C.txt 中。
*/

//将如字串含有大小写的字符数组区分大小写进行排序
void sort(char a[], int n) {
	int i, j;
	char temp;
	for (i = 0; i < n - 1; i++) {
		for (j = i + 1; j < n; j++) {//确定要比较的数
			if (a[i] >= 'A' && a[i] <= 'Z' && a[i] >= 'a' && a[i] <= 'z') {
				if (a[i] + 32 > a[j]) {//比较大写字母
					temp = a[i];
					a[i] = a[j];
					a[j] = temp;
				}
				else if (a[i] - 32 > a[j]) {//比较小写字母
					temp = a[i];
					a[i] = a[j];
					a[j] = temp;
				}
				else {
					if (a[i] > a[j]) {
						temp = a[i];
						a[i] = a[j];
						a[j] = temp;

					}
				}
			}
		}
	}
}


int main(){

	FILE* fp_A, * fp_B, * fp_C;
	char str[81];
	int i=0;
	if ((fp_A = fopen("D:\\A.txt", "r"))==NULL) {
		exit(0);
		printf("打开文件失败!");
	}
	if ((fp_B = fopen("D:\\B.txt", "r")) == NULL) {
		exit(0);
		printf("打开文件失败!");
	}
	if ((fp_C = fopen("D:\\C.txt", "w")) == NULL) {
		exit(0);
		printf("打开文件失败!");
	}
	//一个个字符读入  重要!!!
	//fscanf是按格式一行读入,此处要存入字符串,故用一个个存储的方式
	while (!feof(fp_A)) {
		str[i++] = fgetc(fp_A);
	}
	while (!feof(fp_B)) {
		str[i++] = fgetc(fp_B);
	}

	int len = strlen(str);
	//对数组进行排序
	sort(str, len);
	
	for (i = 0; i < len; i++) {
		putchar(str[i]);
		fputc(str[i],fp_C);
	}
	fclose(fp_A);
	fclose(fp_B);
	fclose(fp_C);
	
}

/*
	法一:追加,读取A的内容到数组,再把数组添加到B 再读取B (麻烦)
	法二:因为将内容进行排序,分别将A、B都读取到数组中进行排序

	数组进行操作时注意大小写的转换

	重点关注两个文件的内容读取到一个数组的操作,fgetc(*fp) 和!feof判断
*/
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值