题目
1、素数打印
2、二分查找
3、数组交换
4、月份打印
5、字母大小写转换
6、字符串逆序并打印
1、素数打印
题目:实现一个函数,判断一个数是不是素数。利用上面实现的函数打印100到200之间的素数。
这里,我们要先了解素数的定义,素数也叫质数 ,即在正整数中,除了1与本身之外没有其他约数的数(1除外)。
方法一:
也就是说,这个数只能被1和它本身整除。了解这一点后我们开始入手写代码,在这里我们最容易想到的方法就是试除法,即从2开始,不断地对那个数进行试除,假设这个数是n,直到试除到n(不包含n)为止,如果没有出现可以被整除的数,则n就是素数。
这里我们先来看一下如何实现对一个数是否为素数的判定:
#include<stdio.h> void is_prime(int i) { //用[2,i)之间的数进行试除 int j = 0; //这里我们定义一个变量,假如这个变量最后是1,说明它是素数 // 假如是0,说明不是素数。 int flag = 1; for (j = 2; j < i; j++) { //==0,说明这个数能被j整除 if (i % j == 0) { //能被整除,说明i不是素数,给flag赋值为0 flag = 0; printf("%d 不是素数", i); break;//没有继续试除的必要了,因为已经出现别的约数了,可以直接停止循环 } } //经历以上循环后,如果flag还是1,说明没有别的约数了。即,i是素数 if (flag == 1) { printf("%d 是素数", i); } } int main() { //如果一个正整数除了1和自己之外,再没有其他的约数,则该数据为素数,具体方式如下 int i = 0; scanf("%d", &i); //注意一点,1不是素数 if (i == 1) { printf("%d 不是素数", i); } else { //进行素数判定 is_prime(i); } return 0; }
这里我们需要注意的是,=与==的区别,前者为赋值,后者是用来判断相等,千万不要用混了。
但是,上述方法有一个缺陷:就是超过i一半的数据,肯定不是i的倍数,上述进行了许多没有意义的运算,因此可以换一种方法,大家看举个例子,假如我们要判断100是不是素数,我们有必要从2试除到99吗?答案是否定的,我们只需要试除到它的开平方,也就是10,就可以判定是否为素数。以此类推来判断别的数
这里就需要用到库函数,sqrt(),专门用来求开平方的,使用必须包含头文件<math.h>
方法二:优化后:
#include<stdio.h> #include<math.h> void is_prime(int i) { //用[2,sqrt(i)]之间的数进行试除,避免大量重复运算 int j = 0; int flag = 1; for (j = 2; j <=sqrt(i); j++) { if (i % j == 0) { flag = 0; printf("%d 不是素数", i); } } if (flag == 1) { printf("%d 是素数", i); } } int main() { int i = 0; scanf("%d", &i); //注意一点,1不是素数 if (i == 1) { printf("%d 不是素数", i); } else { //进行素数判定 is_prime(i); } return 0; }
这么做就避免了大量重复计算。
接下来,了解这个后,进行打印1-100之间的素数就容易多了
题解:
#include<stdio.h> #include<math.h> //打印1-100之间的素数 void print_prime() { int j = 0; int v = 0; for (v = 100; v <= 200; v++) { int prime = 1;//假设1为素数,0不是素数 for (j = 2; j <= sqrt(v); j++) { if (v % j == 0) { prime = 0; break; } } if (prime == 1) { printf("%d ", v); } } } void is_prime(int i) { //用[2,sqrt(i)]之间的数进行试除,避免大量重复运算 int j = 0; int flag = 1; for (j = 2; j <=sqrt(i); j++) { if (i % j == 0) { flag = 0; printf("%d 不是素数\n", i); } } if (flag == 1) { printf("%d 是素数\n", i); } } int main() { int i = 0; scanf("%d", &i); //注意一点,1不是素数 if (i == 1) { printf("%d 不是素数\n", i); } else { //进行素数判定 is_prime(i); //打印素数 print_prime(); } return 0; }
2、二分查找
编写代码在一个整形有序数组中查找具体的某个数
要求:找到了就打印数字所在的下标,找不到则输出:找不到。
我们先了解以下什么是二分查找:如图所示
了解后我们开始入手答题:
#include<stdio.h> int main() { //定义查找的数 int k = 0; //定义整型数组 int arr[] = { 1, 3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25 }; int left = 0;//左下标 //右下标为总元素个数-1,因为下标从0开始 int right = sizeof(arr) / sizeof(arr[0]) - 1; printf("请输入要查找的数:->"); scanf("%d", &k); //左下标始终小于右下标,当相等时就说明找到那个数了 while (left <= right) { //中间坐标 int mid = (right + left) / 2; //中间坐标对应元素<要求的,那么新的查找区域左边坐标就变成了mid+1,右边不变 if (arr[mid] < k) { left = mid + 1; } //中间坐标对应元素>要求的,那么新的查找区域右边坐标就变成了mid-1,左边不变 if (arr[mid] > k) { right = mid - 1; } //左右坐标相等,说明确定这个值了 if (arr[mid] == k) { printf("找到了,下标为%d", mid); break;//找到结果,中止循环 } } //左下标大于右下标说名这个数是不存在的 if (left > right) { printf("找不到"); } return 0; }
注意一点,一定要是有序的数组!!!!从小到大或者从大到小
3、数组交换
将数组A中的内容和数组B中的内容进行交换。(数组一样大)
方法1:
这里我们主要需要知道一点,就是如何完成两个数据的交换,举个例子,一瓶水,一瓶尿,如何让它们进行交换,肯定是需要借助第三个空瓶子,把水倒进空瓶子,再把尿倒进原来盛水的瓶子,在把空瓶子里的水倒进原来盛尿的瓶子,就完成了交换(话粗理不粗)
在C语言里也是一样
千万不可以直接a=b,b=a,如果一旦这样的话,直接第一步b就把a覆盖了。
理清后入手:
#include <stdio.h> int main() { int arr1[10] = { 0 }; int arr2[10] = { 0 }; int i = 0; printf("请输入10个数字:>"); for (i = 0; i < 10; i++) { scanf("%d", &arr1[i]); } printf("请输入10个数字:>"); for (i = 0; i < 10; i++) { scanf("%d", &arr2[i]); } //交换 for (i = 0; i < 10; i++) { int tmp = arr1[i]; arr1[i] = arr2[i]; arr2[i] = tmp; } return 0; }
这里就完成数组交换了:打印看一下
方法2:
当然,我们也可以用指针来解题,指针表示的是地址,我们把两个数组的地址都进行交换,也可以实现数组交换,如下:
#include<stdio.h> //数组名表示首元素地址 void swap(int* arr, int* brr, int sz) { int n = 0; for (n = 0; n < sz; n++) { //首元素地址也就是arr[0],brr[0]的地址,加1就表示arr[1]与brr[1]的地址 //解引用后进行交换,也可以实现数组交换 int tmp = *(arr + n); *(arr + n) = *(brr + n); *(brr + n) = tmp; } } int main() { int arr[] = { 1,2,3,4,5,6,7,8 }; int brr[] = { 9,10,11,12,13,14,15,16 }; //数组一样大 int sz = sizeof(arr) / sizeof(arr[0]); //进行交换 swap(arr, brr, sz); int i = 0; //打印arr,brr printf("arr="); for (i = 0; i < sz; i++) { printf("%d ", arr[i]); } printf("\n"); printf("brr="); for (i = 0; i < sz; i++) { printf("%d ", brr[i]); } return 0; }
4、月份打印
KiKi想获得某年某月有多少天,请帮他编程实现。输入年份和月份,计算这一年这个月有多少天。
输入描述:
多组输入,一行有两个整数,分别表示年份和月份,用空格分隔。
输出描述:
针对每组输入,输出为一行,一个整数,表示这一年这个月有多少天。
方法一:
这里我们要知道,闰年2月有29天,平年28天,所以我们要进行闰年的判断,这里我们有两种方法,
第一种就是直接列举,把每个月份都列举出来,平年与闰年只有2月不同,如下;
#include <stdio.h> int main() { int year = 0; int month = 0; //多组输入 while (scanf("%d %d", &year, &month) != EOF) { //判断是否闰年 if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) { //2月 if (month == 2) { printf("29\n"); } //不是二月份的时候 else goto end; } //不是闰年 else { //2月 if (month == 2) { printf("28\n"); } //不是二月 else goto end; } //列举 end: if ((month == 4) || (month == 6) || (month == 9) || (month == 11)) { printf("30\n"); } else if ((month == 1) || (month == 3) || (month == 5) || (month == 7) || (month == 8) || (month == 10) || (month == 12)) { printf("31\n"); } } return 0; }
这样做是可以,不过看起来可能有点繁琐,大家看另一个方法:
方法二:
#include<stdio.h> int main() { int y, m; //我们把一年的12个月的天数都放在数组里 int days[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; //多组输入 while (scanf("%d %d", &y, &m) != EOF) { //天数对应数组的下标,数组的下标就是月份-1,比如,一月对应的就是days[0] int day = days[m - 1]; //判断闰年 if ((y % 4 == 0 && y % 100 != 0) || (y % 400 == 0)) { //如果是闰年,二月就+1天 if (m == 2) { day += 1; } } printf("%d\n", day); } return 0; }
是不是更简洁巧妙了一点,利用数组,列举所有月份天数,数组下标就是月份-1,如果是闰年,就二月对应(days[1]=28)+1即29天
5、字母大小写转换
完成字母大小写转换,有一个字符,判断它是否为大写字母,如果是,将它转换成小写字母;反之则转换为大写字母。
输入描述:
多组输入,每一行输入一个字母。
输出描述:
针对每组输入,输出单独占一行,输出字母的对应形式
这题很简单,主要就是知道大写字母与小写字母的ASCLL码值相差32,下图为ASCLL表
题解:
#include<stdio.h> int main() { char letter = '0'; //多组输入 while (scanf("%c", &letter) != EOF) { if ((letter >= 'a') && (letter <= 'z')) { letter -= 32; printf("%c\n", letter); } else if ((letter >= 'A') && (letter <= 'Z')) { letter += 32; printf("%c\n", letter); } } return 0;
6、字符串逆序并打印
将一个字符串str的内容颠倒过来,并输出。
数据范围:1≤len(str)≤10000
输入描述:
输入一个字符串,可以有空格
输出描述:
输出逆序的字符串
这里首先就是注意,输入可以有空格,那我们就不能用scanf了,因为scanf只能读取到空格,改用gets。
这里我是利用指针求解的,当然也可以用递归(不容易理解),或者一些别的方法,在这里就先介绍本人的解题:
#include<stdio.h> #include<string.h> void reversed(char* str) { //strlen专门求字符串长度,头文件<string.h> int len = strlen(str); //将str首元素地址放在left里 char* left = str; //末元素地址=首元素地址+元素个数-1,存放在right里 char* right = str + len - 1; //当left=right时,就说明没有可以调换的了 while (left < right) { //地址解引用后就会找到所指向的元素,进行交换即可实现字符串逆序 char tmp = *left; *left = *right; *right = tmp; left++; right--; } printf("%s", str); } int main() { char str[10000] = { 0 }; //输入字符串,在这里用gets是考虑到题目要求,输入可以存在空格,而scanf只能读取到空格,空格后面的读取不了 gets(str); //数组名表示数组首元素地址 reversed(str); return 0; }
end
望诸君努力,共同进步!