好久没有更新了,一方面是因为国庆假期+最近各方面的事情确实有点忙,另一方面是day6的内容就要开始指针的学习,还不确定要怎么给大家通俗易懂地呈现出来,一些同学问我期中考试的事情,其实咱们学校的期中考试是考不到指针的,所以目前指针学不会问题也不是很大。
那么今天就以22年期中考试的前两道题目为例,讲解一下前几天知识的综合运用。
第一题:七进制转换
如果一个十进制正整数n是素数,那么对n的7进制表示的各位数字按十进制求和,其结果依然是素数(在此将1视作素数)。为了编程验证这一猜想,现需要完成以下函数:
1.Sum_Septenary函数,用于统计任意正整数对应7进制数的各位数之和,要求其原型为:
int Sum_Septenary(int n);
函数的返回值为正整数n对应的7进制表示的数的各位数字之和。
2.Is_Prime函数,判断一个十进制正整数n是否为素数,如果是素数则返回1,否则返回0,要求其原型为:
int Is_Prime(int n);
仅需提交题目所要求的两个函数原型对应的函数定义源代码,不可提交测试用的main函数及其它代码,否则会出现编译错误。
题目的要求很简单,就是1.转进制 2.各位数字求和 3.判断是不是素数
进制转换,在数学上通常采用的是采用除基取余法,将要转换的数字反复除以目标基,将每次的余数保留,最后逆序排列得到目标进制的表示。
我们使用C语言程序来把这个原理表示一下,以一个二进制数字为例:
#include <stdio.h>
// 该函数将十进制数转换为二进制数
void decimalToBinary(int decimalNumber) {
int binary[32]; // 用于存储二进制位的数组
int i = 0;
// 处理特殊情况
if (decimalNumber == 0) {
printf("二进制表示: 0\n");
return;
}
// 进行二进制转换的过程
while (decimalNumber > 0) {
binary[i] = decimalNumber % 2; // 取余数
decimalNumber = decimalNumber / 2; // 更新商
i++;
}
// 输出二进制表示
printf("二进制表示: ");
for (int j = i - 1; j >= 0; j--) {
printf("%d", binary[j]);
}
printf("\n");
}
// 主函数
int main() {
int decimalNumber;
// 获取用户输入的十进制数
printf("请输入一个十进制数: ");
scanf("%d", &decimalNumber);
// 调用函数进行转换
decimalToBinary(decimalNumber);
return 0;
}
接下来,我们来写一个可以将十进制数字转换为任意进制的程序:
#include <stdio.h>
// 该函数将十进制数转换为指定进制数
void convertToBase(int decimalNumber, int base) {
int remainder;
int quotient = decimalNumber;
int i = 0;
char baseDigits[] = "0123456789ABCDEF"; // 用于表示大于十的数字
char result[100]; // 存储结果的数组
// 处理特殊情况
if (decimalNumber == 0) {
printf("0");
return;
}
// 进制转换的过程
while (quotient != 0) {
remainder = quotient % base; // 取余数
result[i++] = baseDigits[remainder]; // 保存余数
quotient = quotient / base; // 更新商
}
// 逆序输出结果
printf("转换结果为: ");
for (int j = i - 1; j >= 0; j--) {
printf("%c", result[j]);
}
}
// 主函数
int main() {
int decimalNumber, base;
// 获取用户输入的十进制数和目标进制
printf("请输入十进制数: ");
scanf("%d", &decimalNumber);
printf("请输入目标进制: ");
scanf("%d", &base);
// 调用函数进行进制转换
convertToBase(decimalNumber, base);
return 0;
}
在上一段程序之中,我们发现和二进制那一段不同的是,我们使用的字符串来存储进制转换的结果,如果想用这个来进行运算的时候要遍历的时候对每一个元素减去它的ASCII码。
求各位数字之和:
我们可以利用C语言之中int类型的特性,即%10获取个位数字,%10将其整体右移之后并舍去小数部分。
以1234为例,我们可以先声明一个名为sum的整型变量,让它等于0作为记录各位之和的计数器,接下来使用1234%10获取其个位数4,
加到sum上,接下来1234/10得到123,再加3,以此类推。以下是c语言表示:
#include<stdio.h>
int main()
{
int num;
scanf("%d",&num);
int sum = 0;
while(num){
sum += num%10;
num /= 10;
}
printf("%d",sum);
return 0;
}
判断素数:
素数指的是除了1和它本身,没有别的自然数因子的自然数。判断方法很简单:从2到sqrt(number)(整数平方根)逐个测试能否整除,如果找到一个能整除的数,则该数不是素数,否则就是素数。
#include<stdio.h>
int isPrime(int number) {
if (number <= 1) {
return 0; // 1和负数不是素数
}
for (int i = 2; i * i <= number; i++) {
if (number % i == 0) {
return 0; // 如果能被整除,不是素数
}
}
return 1; // 如果没有能整除的数,是素数
}
int main()
{
int num;
scanf("%d",&num);
if(isPrime(num)) printf("Yes");
else printf("No");
return 0;
}
结合以上,我们可以对本题做出解答
#include <stdio.h>
#include <math.h>
// 函数用于统计正整数n对应的7进制表示的各位数字之和
int Sum_Septenary(int n) {
int sum = 0;
int base = 1; // 初始化7进制的位权基数为1
while (n > 0) {
int digit = n % 7; // 取余得到最低位的数字
sum += digit * base; // 将该位数字加入总和
base *= 10; // 更新位权基数
n /= 7; // 去掉已经处理的最低位
}
return sum;
}
// 函数用于判断一个正整数n是否为素数
int Is_Prime(int n) {
if (n <= 1) return 0; // 1和负数不是素数
if (n == 2) return 1; // 2是素数
if (n % 2 == 0) return 0; // 偶数不是素数
// 对于奇数n,检查是否有小于等于sqrt(n)的因子
int limit = (int)sqrt(n) + 1;
for (int i = 3; i <= limit; i += 2) {
if (n % i == 0) return 0; // 有因子,不是素数
}
return 1; // 没有小于sqrt(n)的因子,是素数
}
int main() {
int n;
printf("输入一个正整数n: ");
scanf("%d", &n);
if (Is_Prime(n)) {
int septenarySum = Sum_Septenary(n);
printf("7进制各位数字之和:%d\n", septenarySum);
if (Is_Prime(septenarySum) || septenarySum == 1) {
printf("结论:符合猜想\n");
} else {
printf("结论:不符合猜想\n");
}
} else {
printf("结论:不是素数\n");
}
return 0;
}
第二题:编写函数Encryption,实现对字母ch循环加密,要求其原型为:
char Encryption(char ch, int k);
其中:形参ch为待加密字母。形参k为字母加密偏移量。返回加密后的字母。
加密算法为:如果ch为字母,则在由A-Z或a-z顺序构成的环形结构中,将字母ch循环右移k个字母,得到加密后的字母并将加密结果返回。若ch为其它字符,则不做任何变换,直接返回字母ch。对待加密字母需要区分大小写。
提示:例如,‘a’右移3个字母则加密结果为’d’,‘x’右移3个字母则加密结果为’a’。可以通过将字母的ASCII值加偏移量后与26求余运算实现该操作。
根据题目所给的提示,很轻易的就可以写出来
#include <stdio.h>
char Encryption(char ch, int k) {
if (ch >= 'A' && ch <= 'Z') {
// 大写字母加密
ch = ((ch - 'A' + k) % 26) + 'A';
} else if (ch >= 'a' && ch <= 'z') {
// 小写字母加密
ch = ((ch - 'a' + k) % 26) + 'a';
}
// 其他字符不变
return ch;
}
int main() {
char ch;
int k;
printf("请输入要加密的字母: ");
scanf(" %c", &ch); // 注意加一个空格以消耗换行符
printf("请输入加密偏移量 k: ");
scanf("%d", &k);
char encrypted = Encryption(ch, k);
printf("加密后的结果: %c\n", encrypted);
return 0;
}
我们来分析一下原理:
- 字母的ASCII值表示了字母在计算机字符集中的位置。例如,大写字母 ‘A’ 的ASCII值是 65,‘B’ 的ASCII值是 66,依此类推,小写字母 ‘a’ 的ASCII值是 97,‘b’ 的ASCII值是 98,以此类推。
- 偏移量
k
表示你想要将字母右移的位置数。如果k
是正数,表示右移;如果k
是负数,表示左移。 - 加上偏移量
k
后,你会得到一个新的整数值,代表字母在字符集中的新位置。 - 由于字母是环形结构,你希望字母右移
k
个位置后,如果超出了字母表的末尾,应该回到字母表的开头。这就是使用取模运算的原因。在这里,我们使用 26(字母表中字母的总数)来取模。 - 通过将ASCII值加上偏移量
k
,然后取模 26,你可以确保结果始终在字母表范围内,从而实现了字母的循环右移或左移。
例如,假设你有一个字母 ‘A’ (ASCII值为 65) 并且想将它右移3个位置。你将65加3得到68,然后对26取模(68 % 26),结果为16。然后,你可以将16转换回字母 ‘A’ 的ASCII值(65),再加上16,最终得到字母 ‘Q’。这就是循环加密的基本原理。
这个方法适用于大写字母、小写字母以及其他字母表中的字符,只需相应地调整ASCII值范围和模数。这种方法简单而有效,可用于实现各种循环加密算法。