crispTT 发表于 2021-11-25 21:31:33

关于C语言课后作业S1E15,求教!!!

1. 求 10000 以内的素数个数#include <stdio.h>

int main()
{
      int count = 2; // 已知2和3是素数
      int i, j;
      _Bool flag = 1;

      for (i = 5; i < 10000; i++)
      {
                for (j = 2; j < i / 2; j++)
                {
                        if (i % j == 0)
                        {
                              flag = 0;
                              break;
                        }
                }

                if (flag)
                {
                        count++;
                }
                else
                {
                        flag = 1;
                }
      }

      printf("10000以内共有%d个素数!\n", count);

      return 0;
}
i为啥要从5开始,2和3也是素数啊,从5开始最后的结果不就不准了吗?还有为啥if后面还有个else {flag = 1}; 只要是素数,从头到尾flag不都是1吗?有什么作用呢?

3. 写一个凯撒加密程序。
#include <stdio.h>

int main()
{
      int ch;

      printf("请输入明文:");

      while ((ch = getchar()) != '\n')
      {
                if (ch >= 'a' && ch <= 'z')
                {
                        putchar('a' + (ch - 'a' + 3) % 26);
                        continue;
                }

                if (ch >= 'A' && ch <= 'Z')
                {
                        putchar('A' + (ch - 'A' + 3) % 26);
                        continue;
                }

                putchar(ch);
      }

      putchar('\n');

      return 0;
}
putchar('a' + (ch - 'a'+3)%26);是什么意思啊,换算成整型来计算的话,(ch-'a'+3)怎么都不可能打过26把,求余以后不是0就是1再加上'a'怎么可能做到向后偏移两位的,这是为什么啊?求大佬指点!!!

番杰 发表于 2021-11-25 21:31:34

第一个问题:
就像你说的2和3也是素数,因为这两个很简单嘛,人用脑一算就知道了,所以就不需要用程序去算,
直接从5开始,这样就省去2.3.4(3次循环),省去了一点点点点点的程序运行时间。

另外,结果并不会不准,因为在程序的第5行:int count = 2; /就已经将(2和3)算进去了。
再另外,else {flag = 1}这个语句,相当于使每一次进入第一个for循环(第9行的)确保flag = 1;
然后进入第二个for循环(第11行的),若该数不是素数,那么它就能满足第13行的if语句,使flag = 0;并退出这个for循环,
此时flag = 0 不满足 第20行的if语句;所以执行else;
把flag 重新赋值为 1;使其进入下次循环,flag的值还是为1;

第二个问题:
1.首先,(ch - 'a'+3)%26)这个表达式的结果不只是0和1;
对26取余,结果为0-25之间的任何一个数;

2.至于('a' + (ch - 'a'+3)%26)这个怎么计算,那么咱们简单的举个例子:
就已简单的字符ch = ‘ a ’为例;
带入('a' + (ch - 'a'+3)%26) = ‘a’ +(‘a’ - ‘a’ + 3)%26 = ‘a’ +3%26 = ‘a’ + 3
结果是 "a"+ 3 ,在编译器中这个计算就是用‘a’的ASCII码值+3;得到的数值在对照ASCII表转换为字符型的值;
当然咱们不用这么费事:这次从a向后数3个字符就行:
b、c、b,所以结果就是‘d’

综上:经过程序,把输入的‘a’变成了‘d’;
同理:输入其他的也一样:就是往后面数偏移多少位就行;

旧情难再续 发表于 2021-11-25 22:54:25

..

crispTT 发表于 2021-11-25 23:27:01

番杰 发表于 2021-11-25 21:31
第一个问题:
就像你说的2和3也是素数,因为这两个很简单嘛,人用脑一算就知道了,所以就不需要用程序去算 ...

卧槽,豁然开朗,感谢大佬!

jackz007 发表于 2021-11-26 00:01:35

       【问题 1】:代码使用了穷举因子的方式在判定素数。在开始判断前前,先假定目标数就是一个素数(flag = 1),然后,按照从小到大的顺序,从所有比目标数小的数中,循环枚举目标数可能的因子,如果真的找到了任何一个因子(可以整除目标数),那么,就对前面的假设加以否定(flag = 0),并立即结束循环(break);反之,如果一直到循环结束也没有能够找到目标数的任何一个因子,那就说明前面的假设成立,目标数真的就是一个素数。循环结束后,根据 flag 的数值,就可以断定目标数是否属于素数。
       【问题 2】:凯撒密码是采用字母错位的方法进行加密的,明文和密文都是字母,在本例中加密采用
密文 = 明文 + 3
      的规律进行加密,例如,字母 'a' -> 'd','b' -> 'e','c' -> 'f' . . .,'A' -> 'D','B' -> 'E' ,'C' -> 'F',... 显然,对于字母表比较位置靠前字母的加密比较好办,对于位置靠后的字母,加密过后,可能就会超过所属字母的范围,例如,'w' -> 'z' 那么,后续字母 'x'、'y' 、'z' 加密过后肯定会超出所属的字母表,那么,应该怎么办?按照规则,如果密文字符 ASCII 编码超出,应该自动回卷,就是说,'x' -> 'a'、'y' -> 'b'、'z' -> 'c'。取余操作正好可以满足自动回卷的要求。
      我们知道,字母表中每个字母的 ASCII 编码是按照其字母表位置顺序连续变化的。
小写字母 - 'a'
大写字母 - 'A'
      一个字母被像上面这样减过以后,会得到一个 0~25 变化的数值,这个数值加过 3 以后
小写字母 - 'a' + 3
大写字母 - 'A' + 3
       这个数值范围变为 3 ~ 28,我们需要把这个范围再次调整到 0 ~ 25 的范围,怎么办?让这个值对 26 取余就可以了
(小写字母 - 'a' + 3) % 26
(大写字母 - 'A' + 3) % 26
       这样,把这个数值再加上相应的字母表开头字母的 ASCII 编码,得到的就是密文字符了。
'a' + (小写字母 - 'a' + 3) % 26
'A' + (大写字母 - 'A' + 3) % 26
      
      

新生路飞 发表于 2021-11-26 12:03:41

凯撒加密是什么意思
页: [1]
查看完整版本: 关于C语言课后作业S1E15,求教!!!