C语言编程题练习

1、三年换一行输出闰年

#include
//输出1900~2000年中的闰年,每输出3年换一行
int main() {
	int num = 0;
	for (int year = 1900; year <= 2000; year++) {
		//闰年判断
		if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) {
			printf("%d ", year);
			num++;
			//每三年换行
			if (num == 3) {
				printf("\n");
				num = 0;
			}
		}
	}
}

注意 闰年判断方式及每循环三次换行的代码



2、输出最高平均成绩的学生

#include
#include//使用atoi函数的库
#define N 2
struct student {
	long stu_num;
	char sex;
	char name[15];
	int score[4];
	float average;
};

/*
*	另一种接受输入方式
	printf("请输入第%d个学生信息\n", i + 1);
	printf("请输入学号:");
	gets_s(str); stuarr[i].stu_num = atoi(str);//类型转换
	printf("请输入性别:");
	gets_s(str); stuarr[i].sex = str[0];
	printf("请输入姓名:");
	gets_s(stuarr[i].name); //注意name是字符串,直接接受
*/
int main(){
	int i, j, index;
	float sum, max;
	struct student stuarr[N];//存储多位学生信息
	//注意性别名字只能填写英文
	for (i = 0; i < N; i++) {
		printf("请输入%d个学生学号,性别,名字\n", i + 1);
		scanf("%1d,%c,%s", &stuarr[i].stu_num, &stuarr[i].sex, &stuarr[i].name);
		printf("请输入各科成绩:\n");
		for (j = 0; j < 4; j++) {//外层控制学生,内层控制各个科目
			scanf("%d", &stuarr[i].score[j]);
		}
	}
	//求平均成绩
	for (i = 0; i < N; i++) {
		sum = 0.0;
		for (j = 0; j < 4; j++) {
			sum += stuarr[i].score[j];
			stuarr[i].average = sum / 4.0;
		}
	}
	max = stuarr[0].average;
	index = 0;
	//找出最高的平均成绩的同学所对应的下标
	for (i = 1; i < N; i++) {
		if (stuarr[i].average > max) {
			max = stuarr[i].average;
			index = i;
		}
	}
	printf("总平均成绩最高的学生信息:学号:%d, 性别:%c,姓名:%s,平均成绩:%1f\n",stuarr[index].stu_num, stuarr[index].sex, stuarr[index].name, stuarr[index].average);
}

测试需要输入全英文,如:1,f,Marry
代码重点在创建结构体简化代码
scanf方式输入更加便捷



3、键盘输入找出被7整除的数

int main() {
	int a,i;
	for (i = 0; i < 5; i++) {
		printf("请输入第%d个数字:",i+1);
		scanf("%d", &a);
		if (a % 7 == 0) {
			printf("找到此数:%d", a);
			break;
		}
	}
	//结束循环还没找到
	if (i == 6) {
		printf("未找到次数!");
	}
}


4、计算sum=a+aa+aaa…

#include
int main() {
	int a, n,sum1,sum2=0,i;//sum1算出每一个数  i控制位数
	printf("请输入a,n: ");
	scanf("%d%d", &a, &n);
	for (sum1 = 0, i = 0; i < n; i++) {
		sum1 = sum1 * 10 + a;//算出每一位数字
		sum2 += sum1;//累加
	}
	printf("sum= %d", sum2);
}


5、去掉最低最高分,计算余下平均分

#include
//键盘输入5个评委的分数 去掉一个最高分 去掉一个最低分 求其余8人的平均分
//输出平均分  最高分  最低分
int main() {
	int arr[5],i,score=0,max,min,aver,sum=0;
	//输入成绩
	for (i = 0; i < 5; i++) {
		printf("请输入第%d个评委的分数:",i+1);
		scanf("%d",&score);
		arr[i] = score;
	}
	//求出最大最小值
	for (i = 0; i < 5; i++) {
		max = min = arr[0];
		if (arr[i] > max) {
			max = arr[i];
		}
		if (arr[i] < min) {
			min = arr[i];
		}
		sum += arr[i];
		//注意是余下的平均分
		aver = (sum-max-min) / (5-2);
	}
	printf("最高分:%d、最低分:%d、平均分:%d", max, min, aver);
}


6、文件操作

6.1 内容输出到控制台

#include
#include//exit(0)所要用的库
//将文件file1.txt文件中的内容读出并显示到屏幕上
int main() {
	FILE* fp;
	char ch;
	//打开文件,使得指针指向具体文件
	if((fp=fopen("E://file1.txt", "r")) == NULL) {
		printf("文件打开失败!");
		exit(0);
	}
	//每次读取一个字符
	ch=fgetc(fp);

	while (ch!=EOF) {
		//输出一个字符
		fputchar(ch);
		//再次读取下一个字符
		ch = fgetc(fp);
	}
	fclose(fp);
}

6.2 将文件复制,并将小写改写成大写

#include
#include//exit(0)所要用的库
//将文件file1.txt文件中的内容读出并显示到屏幕上
int main() {
	FILE* fp1, *fp2;
	char ch;
	//打开源文件,使得指针指向源文件
	if((fp1=fopen("E://file1.txt", "r")) == NULL) {
		printf("文件打开失败!");
		exit(0);
	}
	//打开目标文件,使得指针指向目标文件
	if ((fp2 = fopen("D://file1.txt", "w")) == NULL) {
		printf("文件打开失败!");
		exit(0);
	}
	//先读取首字符进行判断
	ch = fgetc(fp1);

	while (ch!=EOF) {
		//小写转大写  A:65  a:97
		if (ch > 'a' && ch < 'z') {
			ch = ch - 32;
		}
		fputc(ch, fp2);//将字符输出到fp2指向的文件
		//再次读取下一个字符
		ch = fgetc(fp1);
	}

	printf("文件复制成功!");
	fclose(fp1);
	fclose(fp2);
}

用fgetc一个个字符读取的方式比较方便



7、正逆序操作

7.1 逆序输出一个数输入的数

#include
//逆序输出一个数输入的数
int main() {
	int num = 374528, digtal=0,rev=0;

	//取出各个位数进行比较
	while (num > 0) {
		//读取个位数
		digtal = num % 10;
		//倒序生成数 原来数字*10 + 个位数
		rev = rev * 10 + digtal;
		//删去个位数
		num = num / 10;

	}
	printf("%d", rev);
}

倒序生产数的代码在经典例题中计算一串字符串中有几个数字也用到过


7.2 正序输出一个数的各位数字

#include
//正序输出一个数输入的数
int main() {
	int num = 374528,count=1,t=num;//t用于计算位数
	while (t > 9) {
		t /= 10;
		count *= 10;//计算num是几位数  3位数100  4位数1000
	}
	while (count > 0) {
		int d = num / count;//取出最高位数的数字
		printf("%d ", d);
		num %= count;//去掉最高位
		count /= 10;
	}
}

通过中间变量计算数是几位数,再通过位数去分别依次取出最高位的数字


7.3 将输入的字符串反序输出

方法一:指针法

#include
//正将输入的字符串反序输出
int main() {
int main() {
	char str[81],*p = str;
	printf("请输入一串字符串:");
	gets_s(str);
	
	//将指针移动到字符串的最后一个非'\0'元素
	while (*(p+1)) {
		p++;
	}
	//倒序输出
	printf("反序输出结果:");
	while (p >= str) {
		printf("%c", *p);
		p--;
	}
}

方法二:数组下标法

#include
#include
//正将输入的字符串反序输出
int main() {
	char str[81],temp;
	int i, j, len;
	printf("请输入一串字符串:");
	gets_s(str);
	len = strlen(str);
	//i表示头下标 j表示尾下标  只需比较k/2次即可
	for (i = 0, j = len - 1; i < len / 2; i++, j--) {
		temp = str[j];
		str[j] = str[i];
		str[i] = temp;
	}
	puts(str);
	return 0;
}

指针发较为便捷,先将指针移动到末尾再从末尾依次输出。下标法思想简单,同时便利头尾下标进行交换



8、输出200~300的素数

#include
//输出200~300的素数
//素数:除1与自身外,不能余其它整数
int main() {
	int i,j;
	for (i = 200; i <= 300; i++) {
		for(j = 2; j < i; j++) {
			if (i % j == 0) {
				break;
			}			
		}
		//是素数则j会一直自增变成i
		if (j == i) {
			printf("素数:%d\n", i);
		}
		
	}
	return 0;
}

注意输出素数时候的判断条件是一直找不到可以和他相除的数,j最总变成i



9、字符比较

#include
//输输入两个字符。若这两个字符之差为偶数,则输出它们的后继字符,否则输出它们的前驱字符
//后继字符:较大字符后的字符  前驱字符 较小字符前的字符
int main() {
	char a, b,t;
	printf("请输入两个字符:");
	scanf("%d,%d", &a, &b);
	if ((a-b) % 2 == 0) {
		t = (a > b) ? a : b;
		t++;
		printf("后继:%c", t);
	}
	else {
		t = (a < b) ? a : b;
		t--;
		printf("前驱:%c", t);
	}

	return 0;
}

读懂题目,三目运算符的使用



10、输入年月,输出该月天数

#include
//输入年份和月份,输出该月的天数
int main() {
	//七八月都是31  其余均是一大一小  一月大二月小..
	int year, month, arr[13] = { 0,31,28,31,30,31,30,31,31,30,31,30,31 };

	printf("请输入年份:");
	scanf("%d", &year);

	printf("请输入月份:");
	scanf("%d", &month);

	if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) {
		arr[2]++;
	}

	printf("%d年%d月的天数为:%d",year, month, arr[month]);

	return 0;
}

月份的天数与平闰年



11、升序输出(奇数在前偶数在后)

#include
//输入10个数将十个数升序输出,并且奇数在前,偶数在后
//10,9,8,7,6,5,4,3,2,1  输出为1,3,5,7,9,2,4,6,8,10
int main() {
	int arr[10],odd[10],even[10], i, j, k, temp;
	for (i = 0; i < 10; i++) {
		printf("请输入第%d个数:", i + 1);
		scanf("%d", &arr[i]);
	}
	
	//冒泡排序
		//外层决定每趟要比较的次数 9是因为不用和自己比较
	for (i=0; i < 10-1; i++) {
		//内层是获取每个要比较的下标  
		for (j=0,j<10-1-i;j++){//每比较一趟就少一个数(最后一个数),故10-i  -1是应为下标
		//每完成一次内循环便把此次内循环比较的最大的一个数放置最尾部			 
		//交换相邻两个数,将大的往后移
			if (arr[j] > arr[j+1]) {
				temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
	printf("\n排序后的数组:");
	for (i = 0; i < 10; i++) {
		printf("%d ", arr[i]);
	}
	printf("\n");
	
	j = 0, k = 0;//分别作奇偶数组的下标
	//生成奇函数数组
	for (i = 0; i < 10; i++) {
		if (arr[i] % 2 != 0) {
			odd[j++] = arr[i];
		}
		else {
			even[k++] = arr[i];
		}
	}

	//打印奇函数数组
	for (i = 0; i < j; i++) {
		printf("%d ", odd[i]);
	}
	//打印偶奇数数组
	for (i = 0; i < k; i++) {
		printf("%d ", even[i]);
	}
}

冒泡排序:有五个数,第一个数要和后面四个依次比较,第二个要和后面三个依次比较… 故内循环是到10-i为止,



12、录入文章并求单词个数、按大小输出

#include
#include
#include
//录入一段英文文章,统计其中单词个数,并按照单词长度从小到大输出各个单词
//假定这段文章不超过1000个字符,单词不超过240个
struct voca {
	int lent;//单词长度
	char word[20];//单词内容
};
int main() {
	int i = 0, word = 0, len;
	struct voca* danci;//定义结构体指针
	//为结构体指针开辟240个struce长度的内存空间,该指针名可以当数组用
	danci = (struct voca*)malloc(240 * sizeof(struct voca));

	char a[1000];
	int j = 0;
	printf("请输入:\n");
	gets_s(a);
	while (a[i] != '\0') {
		if (a[i] == ' ') {
			//跳过连续空格
			for (i++; a[i] == ' '; i++);
		}
		else {
			word++;//计算单词数
			len = 1;//每次重新计算需要将上一次的长度清除
			//跳过连续字符
			for (i++; a[i] != ' ' && a[i] != '\0'; i++) {
				len++;//统计每个单词的长度
			}
			danci[j].lent = len;//该单词长度
			strncpy(danci[j].word, a + i - len, len);
			j++;
		}
	}
	int m, n;
	struct  voca t;
	for (m = 0; m < word; m++) {
		for (n = 0; n < word - m; n++) {
			if (danci[n].lent > danci[n + 1].lent) {
				t = danci[n];
				danci[n] = danci[n + 1];
				danci[n + 1] = t;
			}
		}
	}
	int f;
	printf("从小到大顺序:\n");
	for (f = 0; f < word + 1; f++) {
		printf("%s", danci[f], word);
	}
	printf("\n");
	printf("单词个数:%d\n", j);

	return 0;
}


13、统计字符中的单词数

#include
//输入一行字符,统计其中共有多少个单词,单词直接用空格符分隔开
int main(){
	char str[100];
	int i = 0, word = 0;
	printf("请输入一行字符:");
	gets_s(str);
	while (str[i] != '\0') {
		if (str[i] == ' ') {
			for (i++; str[i] == ' '; i++);//跳过连续空格
		}
		else {
			word++;//记录单词个数
			//跳过连续单词数
			for (i++; str[i] != ' ' && str[i] != '\0'; i++);//跳过所有非空格
		}
	}
	printf("该字符串单词个数:%d", word);
	return 0;
}

跳过所有连续空格和非空格的代码需要重点掌握



14、排列组合

//有0、1、2、3、4共五个数,能组成多少个重复数字的3位数并输出
#include
int main() {
    int i,j,k,num=0;
    for (i = 1; i < 5; i++) {
        for (j = 0; j < 5; j++) {
            for (k = 0; k < 5; k++) {//穷举法
                if (i != k && j != k && i != j) {
                    num++;
                    printf("%d ", i * 100 + j * 10 + k);
                    if (num % 5 ==0) {
                        printf("\n");
                    }
                }
            }
        }
    }
    
}

穷举列举出所有可能的情况,再进行筛选



15、求所有水仙花数

15.1 方法一:枚举法

#include
#include//使用三次方函数pow
int main() {
	int i, j, k,count=0,number;
	for (i = 1; i < 9; i++) {
		for (j = 0; j < 9; j++) {
			for (k = 0; k < 9; k++) {
				number = i * 100 + j * 10 + k;
				//153 = 1的三次方 +5的三次方 +3的三次方
				if ( number==(pow(i,3) +  pow(j,3) + pow(k,3)) ){
					printf("%d ",number);
					count++;
				}
			}
		}
	}
	printf("\n水仙花数个数=%d\n",count);
}

15.2 方法二:取出各个位数

#include
#include//使用三次方函数pow
int main() {
	int ge, shi, bai,count=0;
	for (int i = 100; i < 1000; i++) {
		ge = i % 10;
		shi = i / 10 % 10;;
		bai = i / 100;
		if (i == pow(bai, 3) + pow(shi, 3) + pow(ge, 3)) {
			printf(" %d", i);
			count++;
		}
	}
	printf("\n水仙花数个数: %d", count);
}

1、方法二的使用更加广泛,在应对求更大范围的水仙花数时更加实用





16、寻找完数

方法一:枚举法

#include
//找出一万以内的完数 完数:6=1+2+3, 28=1+2+4+7+14  本身等于其因子之和
int main() {
	int i, j, sum,count=0;
	//列出所有数
	for (i = 1; i < 10000; i++) {
		sum = 0;//注意每次要先清空上一次的因子之和
		for (j = 1; j < i; j++) {
			//选出其中所有的的因子
			if (i % j == 0) {
				sum += j;
			}
		}
		//本身等于因子之和
		if (sum == i) {
			printf("%d ", sum);
			count++;
		}
	}
	printf("\n一万以内完数的个数:%d", count);
}

方法二:算法

书本P156 有提升性能的算法 以根号i作为一个分水岭,因子关于其对称,当出现两边因子相同则要减去一个



17、分解质因数

#include
//将一个不小于2的整数进行分解质因数 
int main() {
	int n = 33;
	printf("%d=",n);
	for (int i = 2; i <= n; i++) {
		//第一个是质因数后面很可能还是,如40=2*2*2*5
		while (n!=i){//一直分解到不是质因数为止	
			//找到第一个质因数
			if (n % i == 0) {
				printf("%d* ", i);
				//准备寻找下一个质因数
				n = n / i;
			}
			else {
				break;
			}
		}		
	}
	printf("%d ", n);
}


18、判断重复数字

#include
// 输入一个不超过9位数的无符号整数,判断该整数中是否存在重复数字
int main() {
	int num = 12345677,i,j;
	int count[10] = { 0 };//用一个数组记录各位数字出现的次数
	while (num != 0) {
		count[num % 10]++;//出现一次,对于数组元素+1  1%10还是等于1
		num /= 10;//移动到前一位数位
	}
	
	for (i = 0; i < 10; i++) {
		if (count[i] > 1) {
			break;
		}
	}

	//小于10,说明循环提前结束了
	if (i < 10) {
		printf("有重复数字");
	}
	else
	{
		printf("不存在重复数字");
	}
}

运用数组记录出现次数 、%10依次取出各个位数



19、升序数组插入数字后仍是升序

方法一:用指针

#include
#define N 10
//插入数字到升序数组中,使插入后还是升序
int main() {
	int arr[N] = { 10,20,30,40,50,60,70,80,90 };
	int insert = 5, * p = arr + N - 2;//指向数组最后一个非0元素的指针 注意是-2
	while (p >= arr) {
		//将大的数字往后移动一位
		if (*p > insert) {
			*(p + 1) = *p;
			p--;
		}
		else
		{
			//当插入的数是最小元素时,指针会移动到首元素,while里条件满足于 循环会先结束
			//故不会执行下面语句,出现bug,故放在循环外部
			//*(p + 1) = insert;//放在此处会有小bug,当插入数字最小时插入不进
			break;
		}
	}
	//只能在循环结束后指针移动到首位,进行替换
	*(p + 1) = insert;
	printf("插入后的数组:");
	for (int i = 0; i < 10; i++) {
		printf("%d ", arr[i]);
	}
}

方法二:用数组

#include
int main() {
	int arr[10]={1,2,3,4,5,6,7,8,9};
	int num,i;
	printf("输入一个数:");
	scanf("%d", &num);
	//sizeof(arr) / sizeof(arr[0])代表数组长度,
	//-1表示下标 再-1表示多创建了一个用于存放插入的数据
	//反向扫描
	for (i = sizeof(arr) / sizeof(arr[0]) - 1 - 1; i > 0; i--) {
		//如果插入数字小,则将数字和下标都往后移动一位,循环直到找出插入数字大的位置
		while (num <= arr[i]) {
			arr[i + 1] = arr[i];
			i--;

		}
		//如果插入数字大
		//当插入的num最小也会执行这个条件
		if (num > arr[i]) {
			arr[i + 1] = num;
			break;
		}
	}
	for (i = 0; i < 10; i++) {
		printf("%d ", arr[i]);
	}
}

注意插入数字替换原有元素的时机 *(p + 1) = insert;书写的位置



20、字符串中提取整数

#include
//字符串中提取整数
int main() {
	char str[81] = "1a123  xxy u23&8889";
	char* p = str;
	int num,count=0;
	while (*p) {
		//遇到第一个数字字符
		if (*p >= '0' && *p <= '9') {
			//遇到连续数字字符
			for (num = 0; *p >= '0' && *p <= '9'; p++) {
				num = num * 10 + (*p - '0');//注意此处是 -'0',将字符串转换成数字
				
			}
			count++;
			printf("%d ", num);
		}
		else {
			//跳过所有非数字字符 这里可有可无
			if(*p != '\0' && ( * p > '0' || *p < '9')) {
				p++;
			}
		}
	}
	printf("数字个数:%d",count);

}

字符串转换成数字:减去字符串0,注意处理连续字符串,跳过连续非字符串代码



21、两个升序数组并归

#include

int merge_sort(int *a,int lena,int *b,int lenb,int *c) {
	int i=0, j=0, k=0;
	//两个数组内的元素依次比较
	while (i < lena && j < lenb) {
		if (a[i] < b[j]) {
			c[k++] = a[i++];
		}
		else {
			c[k++] = b[j++];
		}
	}
	//比完其中一个数组后,另一个数组还有剩余,直接依次存入
	while (i < lena) {
		c[k++] = a[i++];
	}
	while (j < lenb) {
		c[k++] = b[j++];
	}
	return 0;
}

//两个升序数组并归
int main() {
	int a[10] = { 0,3,6,9,10,18,23,25,30,35 };
	int b[8] = { -5,-1,1,2,5,11,28,40 };
	int i, c[18];
	printf("原始数组a:");
	for (i = 0; i < 10; i++) {
		printf("%d ", a[i]);
	}
	printf("\n原始数组b:");
	for (i = 0; i < 8; i++) {
		printf("%d ", b[i]);
	}
	merge_sort(a,10,b,8,c);	
	printf("\n合并后的新数组c:");
	for (i = 0; i < 18; i++) {
		printf("%d ", c[i]);
	}
}

思路:先比较两个数组,比完其中一个数组后,将另一个数组直接存放在新数组中



22、子串是否与主字符串匹配

方法一:课本while方法

#include
#include
int index(char *s,char*t,int start) {
	int m = strlen(s), n = strlen(t);
	int i=0, j=0;
	if (start < 0 || m<0 ||start + n > m ) {
		return -1;
	}
	while (i < m && j < n) {
		if (s[i] == t[j]) {
			i++;
			j++;
		}
		else {
			i = i - j + 1;//减去if里面匹配了的部分长度,并+1表示从下一个位置开始匹配
			j = 0;
		}
	}
	if (j == n) {
		return i - j;//子串在母串中的起始位置  子串-母串 = 前面一段
	}
	else
	{
		return -1;
	}
}

// 设主串数组名为S,子串数组名为T,找出子串T在主串S中第一次出现的位置
int main() {
	char S[] = "abcdegdefg", T[] = "def";
	//成功返回子串在主串的起始位置,失败返回-1
	int num = index(S, T, 1);
	printf("子串在主串的起始位置:%d", num);//返回的是下标,下标从0开始,返回的位置是6
}

运用下标依次比较,当比较不相同则将子串清空从头开始,母串从下一位开始比较

方法二:for循环

#include
#include
int main() {
	char str1[81], str2[81];
	printf("输入母串:");
	gets_s(str1);
	printf("输入字串:");
	gets_s(str2);
	
	int len1, len2, i, j,k, flag = 0, local = 0;
	len1 = strlen(str1);
	len2 = strlen(str2);
	/*
		漏了比较每个元素时母串的移动,因为要变化逐个比较,变要将其交给k做下标。
	*/
	for (i = 0; i < len1; i++) {
		//外层循环控制母串比较的起点
		//交给k是因为要进行比较下一位的变化
		k = i;
		//内层表示子串的每个元素
		for (j = 0; j < len2; j++) {
			//不相等则退出当前循环,让母串移动到下一位开始比较
			if (str1[k] != str2[j]) {
				flag = 0;
				break;
			}
			if (str1[k] == str2[j]) {
				flag = 1; 
				//如果相同则比较下一位,k++表示移动母串下标
				k++;
			}
		}
		if (flag){
			//记录完第一次出现的位置之后就退出
			local = i + 1;
			break;
		}	
	}
	if (flag) {
		printf("存在,子串位置位于%d", local);
	}
	else {
		printf("不存在!");
	}
}


23、在一个字符串找出某一字符

#include
//方式一
char* strch01(char*p ,char ch) {
	while (*p) {
		if (ch == *p) {
			return p;
		}
		else
		{
			return NULL;
		}
		p++;
	}

}

//方式二
char* strch02 (char* s, char ch) {
	//跳过不匹配的字符
	while (*s && *s != ch) {
		s++;
	}
	//如果不是读到了末尾,则返回当前匹配的字符指针
	if (*s) {
		return s;
	}
	return NULL;
}
// 在一个字符串找出某一字符
int main() {
	char str[81] = "abcdefg", ch = 'a', * p = str, * s;
	s = strch02(p, ch);

	if (s == NULL) {
		printf("字符串中不存在该字符!");
	}
	printf("从字符串中找出的字符:%c", *s);
}


24、二分查找

#include

int search(int* arr, int len, int target) {
	int low=0, high = len-1;
	int mid;
	while (high > low) {
		mid = (low + high) / 2;
		if (arr[mid] == target) {
			return mid;
		}
		//如果目标值在中间值的右边,增大最小值
		else if (arr[mid] < target) {
			low = mid;
		}
		else if (arr[mid] > target) {
			high = mid;
		}
	}
	return -1;
	
}


//用折半查找法找某数是否在给定的升序数组中
int main() {
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int result = search(arr, 10, 2);
	printf("查找结果位于的下标:%d", result);
}

通过不断改变两个端点,实现中间值的动态改变



25、打印杨辉三角

#include


//打印杨辉三角 二维数组的方式
int main() {
	int a[5][5], i, j, k;
	//将每行的第一个元素和最后一个元素固定成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++) {//注意此处的终止条件,第三行除了两端的1只生成一个新的元素
								//第四行生成两个..  故第一次内循环只运行一次,第二次两次
			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("%6d", a[i][j]);
		}
		printf("\n");
	}
}

注意内外循环的条件,先固定首位元素的1,再求其余中间元素,注意是从第三行开始,中间元素的个数从1开始依次递增



26、删去指定字符

#include
#include

//电脑终端输入一行字符串  要求从该串中删去指定字符
int main() {
	char str[81], ch, fast = 0, slow = 0;
	printf("请输入一行字符串str:");
	gets_s(str);
	printf("请输入要删除的字符ch:");
	scanf("%c", &ch);
	int len = strlen(str);
	
	//最后一个字符没有被替换,仍会随着打印打印出来  
	//如ABCD  删除B   输出会输出ACDD 需要额外在处理最后一个元素
	while (str[fast] != '\0') {
		//快慢指针法 
		if (str[fast] != ch) {
			str[slow++] = str[fast];
		}
		fast++;
	}
	//将最后一位换成结束符
	str[len - 1] = '\0';
	//put方法读取到结束符就会结束输出字符串
	puts(str);
}

双指针法,注意最后一位元素并没有被替换,需要额外处理



27、判断是否为回文串

#include
#include
//“回文串”是一个正读和反读都一样的字符串 如:“level”或者“noon”
int main() {
	printf("输入字符串:");
	char str[10];
	gets_s(str);
	
	//strlen为字符串长度,使用为下标需-1
	int start=0, last=strlen(str)-1,flag=1;
	//左右下标相等说明比较完毕
	while (start <= last) {
		//依次比较首尾元素
		if (str[start++] != str[last--]) {
			flag = 0;
			break;
		}
	}
	if (flag == 1) {
		printf("是回文!");
	}
	else {
		printf("不是回文!");
	}
}


28、计算1K + 2k + 3k + Nk

#include
#include
//计算1K + 2k + 3k + Nk
int main() {
	int N, K, sum = 0;
	printf("请输入个数N:");
	scanf("%d", &N);
	printf("请输入次方K:");
	scanf("%d", &K);
	for (int i = 1; i <= N; i++) {
		sum += pow(i, K);
	}
	printf("和为:%d", sum);

	//方式二:
	int power;
	for (int i = 1; i <= N; i++) {
		power = 1;
		//计算第i个数的k次方  等价于pow方法
		for (int j = 1; j <= K; j++) {
			power = power * i;
		}
		sum += power;
	}
}

k次方等价于for循环累乘



29、求学生最差最好成绩

#include
//某班有三个学生 输入每个学生成绩,求出该学生的平均成绩
//找出最差和最好成绩,以输入负数表示结束该学生成绩输入
int main() {
	float score = 0, score2 = 0, max = 0, min = 0, num = 0;
	int time = 1;
	for (int i = 0; i < 3; i++) {
		printf("请输入第%d个学生的成绩\n",i+1);
		printf("请输入第1个门的成绩:" );
		scanf("%f", &score);
		//先输入一次,作为比较的起点
		num = max = min = score;
		int time2 = 2;
		while (score > 0) {
			printf("请输入第%d个门的成绩:",time2++);
			//在输入第二次,每次和第一次进行比较
			scanf("%f", &score2);
			if (score2 < 0) {
				break;
			}
			//最高、最低、平均值的计算
			if (score2 > score) {
				max = score2;
			}
			else {
				min = score2;
			}
			num += score2;
			time++;
		}
		float aver = num / time;
		printf("\n");
		printf("第%d个同学输入结束!\n",i+1);
		printf("其平均成绩:%f,最高分:%f,最低分%f\n", num, max,min);
		printf("\n");
	}

先输入第一次作为比较的开头,后续输入的依次与其进行比较



30、计算递推式的某一项

#include
//n为奇数时:An=2*A(n-1)+1; n为偶数时:An=2*A(n-1)-1; 
//已知A0=0  编写一个函数int fun(int n) 计算第n项的值An
int fun(int n) {
	int an;
	if (n == 0) {
		an = 0;
	}
	else
	{
		if (n % 2 == 1) {
			an = 2 * fun(n - 1) + 1;
		}
		else
		{
			an = 2 * fun(n - 1) - 1;
		}
	}return an;
}

int main() {
	int n = 4;
	fun(n);
	printf("a(%d)=%d\n", n, fun(n));
}

递推式用递归实现



31、文件内容排序

#include
#include
#define N 5
//有一个文本文件numbers.txt 其中有10个整数,每个整数独占一行。
//编写程序将整数从小到大顺序拍好后,重新写入到该文件中。
//要求在排序前和排序后分别输出该文件内容

void fun(int s[]) {
	for (int i = 0; i <= N - 1; i++) {
		printf("%d ",s[i]);
		printf("\n");
	}
}
int main() {
	int s[N], i, j, temp;
	FILE* fp;
	fp = fopen("E:\\numbers.txt", "r");
	for (i = 0; i <= N - 1; i++) {
		//从文件中读取数据给数组
		fscanf(fp, "%d\n", &s[i]);
	}
	printf("排序前的顺序:\n");
	fun(s);

	//对数组进行冒泡排序 从小到大 大的往后放
	for (i = 0; i < N; i++) {
		for (j = 0; j < N - i; j++) {
			if (s[j] > s[j + 1]) {
				temp = s[j];
				s[j] = s[j + 1];
				s[j + 1] = temp;
			}
		}
	}

	fp = fopen("E:\\numbers.txt", "w");
	for (i = 0; i <= N - 1; i++) {
		//将数组输出到文件中  printf是输出到控制台
		fprintf(fp, "%d\n", s[i]);
	}

	printf("排序后的顺序为:\n");
	fun(s);
	
	fclose(fp);
	return 0;
}

先读取文件存入数组,使用fscanf方法 指定读取一个数字一个换行符的组合,用于读取每行相同形状的数据会方便 后对数组进行冒泡排序,再输出回文件中



1、买苹果问题

#include

int main() {
	float money=0,aver;
	int num = 2,day=1,sum=0;
	
	while (num < 100) {
		money += 0.8 * num;
		num = num * 2;
		day++;
		
	}
	aver = money / day;
	printf("平均每天花钱:%.2f", aver);
}


2、猴子吃桃问题

//第一天摘下桃子,吃了一半多一个,以后每天如此,直到第十天早上发现只剩下一个,问一开始摘了多少桃子
int main() {
	int sum = 0; 
	//不包括第十天,从第一天开始
	for (int i = 1; i < 10; i++) {
		sum = (sum + 1) * 2 ;
	}
	printf("第一天摘了%d个桃子", sum);
}


3、婚礼问题

  • 3个新郎A、B、C 3个新娘X、Y、Z 他们分别说出以下结果:
    A说他将和X结婚;X说他的未婚妻是C;C说他将和Z结婚
    这人事后知道他们是再开玩笑,问谁和谁结婚
#include

//3个新郎A、B、C   3个新娘X、Y、Z  他们分别说出以下结果:
//A说他将和X结婚;X说他的未婚妻是C;C说他将和Z结婚  
//这人事后知道他们是再开玩笑,问谁和谁结婚
int main() {
	//数字1,2,3分别代表X、Y、Z 
	int a, b, c;
	for (a = 1; a <= 3; a++) {
		for (b = 1; b <= 3; b++) {
			for (c = 1; c <= 3; c++) {
				//A不会和X(1)结婚;X(1)的未婚妻不会是C;C也不会和Z(3)结婚  
				//A、B、C一一配对,不能共用老婆
				if (a != 1 && c != 1 && c != 3 && a != b && b != c && a != c) {
					printf("%c将嫁给A\n", 'x'+  a - 1);
					printf("%c将嫁给B\n", 'x' + b - 1);
					printf("%c将嫁给C\n", 'x' + c - 1);
				}
			}
		}
	}
}

枚举列举出所有可能的情况,再根据题目条件和现实情况进行筛选



4、分糖果问题

c


5、找出符合条件的数

  • 在3位整数100~999中查找符合如下条件的整数并输出在屏幕上,这个数既是完全平方数,又有两位数字相同,如121(11的平方),144(12的平方)
#include
//在3位整数100~999中查找符合如下条件的整数并输出在屏幕上,
//这个数既是完全平方数,又有两位数字相同,如121(11的平方),144(12的平方)
int main() {
	int ge, shi, bai,i,j;
	for (i = 100; i < 999; i++) {

		//寻找完全平方,10的平方为100、32的平方为1024
		for (j = 10; j < 32; j++) {
			if (j * j == i) {
				ge = i % 10;
				shi = i / 10 % 10;
				bai = i / 100;
				if (ge == shi || ge == bai || shi == bai) {
					printf("%d ", i);
				}
			}
		}	

		//写法二: 未知循环用while
		j = 10;//保证是三位数
		while (j * j <= i) {
			if (i == j * j) {
				ge = i % 10;
				shi = i / 10 % 10;
				bai = i / 100;
				if (ge == shi || ge == bai || shi == bai) {
					printf("%d ", i);
				}
			}
			j++;
		}
	}
}


6、寻找符合条件的六位数

  • 有一个六位数,它本身是一个整数的平方,其高三位和第三位也分别是一个整数的平方 如:225625=475*475 ,求满足上述要求的六位数
#include
#include
//有一个六位数,它本身是一个整数的平方,其高三位和第三位也分别是一个整数的平方
//如:225625=475*475 ,求满足上述要求的六位数
//隐含的条件,整数开根号 = 其前三位开根号 + 后三位开根号

//知识点:sqrt开根号,如果结果是小数则平方不会变回原来的数
int main() {
	int i, j, last, end, last2, end2, count = 0;
	//所有的六位数
	for (i = 100000; i < 999999; i++) {
		j = sqrt(i);//整数开根号
		if (j * j == i) {//如果j是小数则会四舍五入,则无法恢复成i的平方
			last = i / 1000;
			end = i % 1000;
			last2 = sqrt(last);
			end2 = sqrt(end);
			if (last == last2 * last2 && end == end2 * end2) {
				count++;
			}

		}

	}
	printf(" %d", count);
}

判断是否是一个整数的平方的两种方式:
1、内外循环if条件判断
2、sqrt开根号,如果结果是小数则平方不会变回原来的数



7、数字转换成字符串

#include
//(834 16)用递归方法将一个整数n(n>=1)转换成字符串。例如:输入483,应输出字符串“438”

void convert(int n) {
	int i;
	if ((i = n / 10) != 0) {
		convert(i);
	}
	//单个数字/字符:
	//字符 -‘0’转换成数字
	//数字 +‘0’转换成字符

	//字符串 ,atoi("1234")
	//一串数字, itoa(20,arr,进制)
	putchar(n % 10 + '0');
	
}

int main() {
	convert(438);
}

数字、字符串的互相转化



8、输入并筛选展示学生信息

#include
#include
//编写一个30名学生信息状况的示意性检索程序
/*
每名学生的信息包括:xh(学号)、xb(性别)、cj(成绩)、xm(姓名)
要求:1、输入3名学生信息
	  2、输出男同学中成绩大于90的学生的xm、xb、cj
*/
//创建结构体数组
struct student {
	int xh;
	char xb;
	float cj;
	char xm[20];
}stu[3];


int main() {
	int i;
	char str[20];
	//为每位同学赋值,固定代码
	for (i = 0; i < 3; i++) {
		printf("请输入第%d个同学的成绩\n", i+1);
		printf("请输入学号:");
		gets_s(str);
		stu[i].xh = atoi(str);
		printf("请输入性别:");
		gets_s(str);
		stu[i].xb = str[0];
		printf("请输入成绩:");
		gets_s(str);
		stu[i].cj = atof(str);
		printf("请输入姓名:");
		gets_s(stu[i].xm);
	}

	for (i = 0; i < 3; i++) {
		if (stu[i].xb == 'm' && stu[i].cj >= 90) {
			printf("学号:%d 性别:%c 成绩:%.2f 姓名:%s", stu[i].xh, stu[i].xb, stu[i].cj, stu[i].xm);
			printf("\n");
		}
	}
}

结构体数组可以简化代码



9、数组的一行输入及删除

#include
#include
//编程实现数组元素的移动:设数组有1-个元素,输入一个数x,把数组的第x个位置的元素删除,
//后面的元素依次前进一个位置。重复若干次这样的删除,得到最后结果
/*
	输入10个元素数组(空格隔开):1 2 3 4 5 6 7 8 9 10
	要删除K次  : K
	接下来输入K行,每行一个数,表示指定删除第X个元素

*/

int main() {
	int i=0, j=0, k,num;
	int arr[10] = { 0 };
	char str[100],*p=str;
	//第一行:输入数组
	//方式一:用字符串接收转换成数字(复杂用方法二)
	gets_s(str);
	while (*(p + 1) != '\0') {
		//固定代码,将字符串转换成数字串 
		//遇到第一个数字
		if (*p >= '0' && *p <= '9') {
			//单个数字
			num = *p - '0';
			//处理连续数字
			for (num = 0; *p >= '0' && *p <= '9'; p++) {
				num = num * 10 + (*p - '0');
			}
			//存储进数组
			arr[j++] = num;
		}
		p++;
	}
	/* 
	方式二:用scanf("%d")进行输入  空格不会读入
		for(i=0;i<10;j++){
			scanf("%d",&a[i]);
		}
	}

	*/
	printf("删除之前的数组:\n");
	for (i = 0; i < 10; i++) {
		printf("%d ", arr[i]);
	}

	//第二行:K次删除
	printf("\n请输入要删除的次数K:");
	scanf("%d", &k);
	//数组删除:双指针
	int fast = 0,slow = 0;
	for (i = 0; i < k; i++) {
		num = 0;
		printf("要删除的第%d个数字:",i+1);
		scanf("%d", &num);
		for (fast = 0,slow=0; fast < 10; fast++) {
			if (arr[fast] != num) {
				arr[slow++] = arr[fast];
			}
		}
	}
	//删除之后只输出删除后的元素 如 删除345 三次后:1 2 6 7 8 9 10 10 10 10
	printf("删除之后的数组:\n");
	for (i = 0; i < 10-k; i++) {
		printf("%d ", arr[i]);
	}
}


10、字符串循环左移

#include
//编写函数void shift(char *s,int n)
//要求将字符串s循环左移n次。例如,"hello",左移3次得到"lohel"  hello ohell
/*
	elloh
	llohe
	lohel
*/

void shift(char* s, int n) {
	char* p1 = s, * p2 = s, t;
	int i = 0;
	//p2指向字符串最后一个元素
	while (*(p2+1)!='\0') {
		p2++;
	}
	while (i < n) {
		p1 = s;
		//存储首元素
		t = *(p1);
		//将元素后移动一位
		while (p1 != p2) {
			*(p1) = *(p1 + 1);
			p1++;
		}
		//将首元素的值放入最后一位
		*p2 = t;
		i++;
	}
	printf("%s", s);
}

int main() {
	char s[] = "hello";
	shift(s, 3);
}

每次移动首位元素到末尾,循环三次
没有读懂题目,指针要来的便捷



11、婚约数问题

#include
/*
	婚约数指两个正整数中,彼此除了1和本身的其余所有约数的和与另一方相等
	例如:最小的一对婚约数是(48,75)因为
	48的约数相加和:2+3+4+6+8+12+16+24=75
	75的约数相加和:3+5+15+25=48
	编写程序,输入一个正整数,判定它是否能和另一个正整数构成一堆婚约数
*/
void marry(int n) {
	int i,sum=0,sum2=0;
	//找出n的约数和
	for (i = 2; i < n; i++) {
		if (n % i == 0) {
			sum += i;
		}
	}
	printf("输入数字的约数和:%d\n", sum);
	//找第二个数的约数和
	int n2 = sum;
	for (i = 2; i < n2; i++) {
		if (n2 % i == 0) {
			sum2 += i;
		}
	}
	//各自的约数和与另一方整数相等
	if (sum2 == n && sum == n2) {
		printf("(%d,%d)是一对婚约数", n, n2);
	}
	else {
		printf("(%d,%d)不是一对婚约数", n, n2);
	}

}

int main() {
	//测试婚约数:(140、195)和(1050、1925)
	marry(1000);
}


12、字符串替换

c#include<stdio.h>
/*
	831 19年真题 
	编写函数int strrepl(char *s, char*r,char c),把字符串s中出现的r中的每个字符
	都用字符c代替,函数返回替换的字符数量
	例如:如果s为字符串“code(1,2)”,r为“().”,c为字符'_' 
	那么执行strrepl后,s变成"code_1_2_".

	注意:
	1、函数strrepl中要改变参数s所指向字符串的内容(使参数s所指向的字符串是替换之后的新字符串)
	2、还需要编写主函数,并在主函数中初始化字符串s和字符串r的内容,输入e值,并调用strrepl函数
	实现替换字符功能,最后输出替换字符串之后的新字符串
*/

int strrepl(char* s, char* r, char c) {
	int count = 0;
	char *p1=s,*p2=r,*p3=r;//p3用于存储r的初始位置

	//字符串s以'\0'为结束符
	while (*p1) {//等价于*p1 != '\0'
		//s的每一个字符要和r全部字符都比较一边
		while (*p2) {
			if (*p1 == *p2) {	
				*p1 = c;
				count++;
			}
			p2++;
		}
		p2 = p3;//将r重置,下一次比较其要从头开始
		p1++;//开始遍历s的下一个元素
	}
	return count;
}
int main() {
	char s[20] = "code(1.2)", r[20] = "().";
	char c = '_';
	int num = strrepl(s, r, c);
	printf("被替换字符数量:%d\n", num);
	printf("替换后的字符串:%s", s);
}

类似子串与母串的比较



你可能感兴趣的:(学习笔记,c语言)