经典例题(一)——经典例题的归纳总结。
题目
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
望诸君努力,共同进步!
相关文章
- Amazon EKS 现在支持 EC2 Inf1 实例
- 使用 ezsmdeploy Python 程序包和几行代码将机器学习模型部署到 Amazon SageMaker
- 瞬息万变时代中的扩展挑战
- 使用 AWS CodeArtifact 的软件程序包管理
- 使用 AWS CDK 加速 EKS 集群部署
- VPC 安全的十个最佳实践
- 基于 MediaConvert 实现加载 WebVTT 字幕的 HLS 流媒体的封装
- 新增功能 – 由第二代 AMD EPYC™ 处理器提供支持的 Amazon EC2 C5a 实例
- php_python远程调试
- 机器学习为数字化转型插上翅膀
- java-synchronized原理
- 机器学习基础
- Amazon FSx for Windows File Server – 存储大小和吞吐容量扩展
- 如何优雅的删除一个 VPC
- 欢迎进入 IPv6 的云计算世界!
- Okta 通用目录与 AWS 之间的单点登录
- 新增功能 – AWS Marketplace 的 SaaS 合同升级和续订
- 介绍最新的 AWS 精英,2020 年 5 月
- 什么是 Deno?
- 欢迎参加无服务器优先功能线上活动