倘若能够偷懒,想必,就没有这篇文章了。

说是一次C语言实验作业,但是题目都没有什么难度。抱着 “敷衍的做完作业,不如不做” 的态度,在和不想做却不能不做的情形斗争了几十天,挣扎到了截止日附近才开始做,

”既然题目已经如此无聊了,索性在实现中找点乐子“ 如此想到,便有了本篇中的许多花活。

Tips : 做第一题的时候没有想起来整活,就没有记录,所有只有图片

Part 1 凯撒密码

Ex1-5:(综合及设计类)将“China”译成密码,译码规律是:用原来字母后面的第 4 个字母代替原来的字母。例如,字母“A”后面第 4 个字母是“E”,用“E”代替“A”。因此,“China” 应译为“Glmre”。

题目还很贴心的配了图

image-20240115013016777


例题 [1]

(1)请编一程序,用赋初值的方法使 c1、c2、c3、c4、c5 五个变量的值分别为’C’、’h’、’i’、’n’、’a’,经过运算,使 c1、c2、c3、c4、c5 分别变为’G’、’l’、’m’、’r’、’e’,并输出。

我的实现:

image-20240115013439045

分析题意,只是向ASCII码更高的值位移4位不需要很复杂的做法,仅仅是 Cn += 4; 就可以解决。

很明显,我不想写一堆 Cn += 4; 的语句,但是题目又规定了必须用 c1、c2、c3、c4、c5 五个变量 ,所以用[宏进行批量模式替换](##C/C++ 的宏)是再好不过的选择。

运行结果:

image-20240115015325182

例题 [2]

(2)将译码规律修改为:将字母用它前面的第 4 个字母代替,例如:’E’用’A’代替,’Z’用’V’代替,’D’用’Z’代替,’C’用’Y’代替,’B’用’X’代替,’A’用’W’代替。修改程序并运行。

我的实现:

#include <stdio.h>
#define Rp(x) ((c##x>='A'&&c##x<='Z')?'A':'a')
#define Mod(x,y) ((x<0)?(y-((-x)%y)):(x%y))
#define Plus(x) c##x=Mod((c##x-Rp(x)+4),('Z'-'A' + 1))+Rp(x);
#define G(x) c##x,
int main(){ 
	char c1='T',c2='o',c3='d',c4='a',c5='y';
	Plus(1)Plus(2)Plus(3)Plus(4)Plus(5)
	printf("%c%c%c%c%c",G(1)G(2)G(3)G(4)c5);
	return 0;
}

这道题就开始上强度了,因为它的规则是向低位偏移4位,所以势必会使得 "a" 这样的字符在经过减法的时候会变成负数。

在 C 语言中,负数取模仍是负数,所以按照 [例题 [1]](##例题 [1]) 的处理方式——直接给每个字符的ASCII码值减4,最后得到的数字会无法落在有效的英文字符的ASCII码值区间。所以,这里就要对取模操作做一点改进。

另外,我使用了条件表达式。条件表达式在很多编程语言中都有,合理的使用,可以避免繁琐的 if ... else ... 语法,不仅更容易写出紧凑的程序,而且会在一些特定场合提升程序的可维护性。

唯一缺点是:可读性依赖编程者的水平。(看不懂就是另一个故事了 :))

参考:[% 的循环控制](##% 的循环控制)

运行效果:

Xshec
--------------------------------
Process exited after 0.006181 seconds with return value 0 (0 ms cpu time, 3120 KB mem used).

Press ANY key to exit...

知识库

% 的循环控制

计算机的空间不是无限的,而形如网络数据包的处理、音视频播放的内存载入等情景,短期数据量较小,但是总数据量较大,计算机不可能有无限的内存来存储这些数据。好在,在一般情况下,这些随时间推移不断增多的数据多数是即时性的——仅仅在被传输过来的一段时间需要,使用后就会被丢弃。这种情况下,存储这些数据的缓冲区通常选用 循环队列 (经常被称作 循环缓冲区

如果要实现一个固定容量的循环队列,一般的做法是使用一个定长数组来存储数据。

int cache[10]; 创建了一个长度为10的数组。想象一个f(x) , x \in \mathbb{Z}

宏定义的写法:

#define Mod(x,y) ((x<0)?(y-((-x)%y)):(x%y))
#define Mod(x,y) ((x<0)?(y+(x/y)*x):(x%y))

上面两个写法是等价的。

如果写成函数就是:

int Mod(int x,int y){
	return (x<0)?(y-((-x)%y)):(x%y);
}
int Mod(int x,int y){
	return (x<0)?(y+(x/y)*x):(x%y);
}

C/C++ 的宏

C/C++ 的宏通常被初学者看成很没有用的东西,因为大部分老师仅仅演示了宏定义常量的用法,而忽视了宏的模式替换的能力。

宏能够定义各种常量,其实也是一种模式替换。不妨想一想,如果宏的能力仅仅是替换,为什么定义了#define N 100 的时候,不会把形如int Not = 3; Num 之类的自定义标识符中的 "N" 替换掉?不难理解,仅仅把宏看成一种文本替换的工具,这是不完整的理解。