【问题标题】:How should I solve this cipher with pointer arithmetic?我应该如何用指针算术解决这个密码?
【发布时间】:2013-11-19 06:47:35
【问题描述】:

问题如下:

使用指针算法求解以下密码。给定的字符串是 GKQTEHIN。定义一个指针并将其设置为该字符串中的字母“T”。前后遍历字符串。为每个字母添加/减去 1 到 5 之间的单个值(键)以解决此密码并形成一个有意义的单词。提示:你将在解决它时使用它。

希望这已正确完成...

char given[]="GKQTEHIN";
char *pointer; 
pointer=&given[3];

pointer-=3;
printf("%c", *pointer-4);

pointer+=1;
printf("%c", *pointer+4);

pointer+=1;
printf("%c", *pointer-4);

pointer+=1;
printf("%c", *pointer-4);

pointer+=1;
printf("%c", *pointer+4);

pointer+=1;
printf("%c", *pointer+4);

pointer+=1;
printf("%c", *pointer-4);

pointer+=1;
printf("%c\n\n", *pointer+4);

“编译器”这个词被打印出来了。

【问题讨论】:

  • 我如何“在每个字母表中添加/减去单个值...”? -- 你不认为你会得到这个问题的更好答案吗?来自你的教授或助教?
  • 请您的老师仔细检查字符串“GKQTEHIN”——我认为应该是“GSQTYXIV”
  • 这个问题是废话,你已经完成了所有明确的部分,并且给定的字符串产生零个“有意义”的单词,无论如何解释模糊的部分。我和亚当一样,给定的字符串不是以这种方式编码的,或者只是完全错误的。
  • 感谢大家的意见,并将继续努力。我昨晚给他发了电子邮件,没有收到个人回复,但他向我们全班同学发了一条消息,说“字母 I 和 E 将在最后一个解密的单词中互换位置。”
  • 哦,所以我只是用笔和纸弄乱了字母表,答案是“编译器”。对于字符串中的每个元素(从左到右),减去 4、加 4、减 4、减 4、加 4、加 4、减 4 和加 4。哇。乐趣。不过,我不确定如何使用循环来减少乏味。再说一次,说明并没有要求这样做……至少我有一些东西要上交,我想。谢谢你的所有话,伙计们。

标签: c pointers encryption pointer-arithmetic


【解决方案1】:

如何“在每个字母表中添加/减去单个值...”?

计算机只能理解和处理数字,因为计算机中的一切都是数字(或可以被视为数字)。这意味着字母实际上是内部的数字。 C 中的char 使用ASCII encoding,这使得每个字母对应一个数字。因此,您只需将密钥添加到代表 char 的代码中。您可以毫无问题地使用char 作为数字。

char a = 'a';
a++;
printf("%c\n", a); // prints 'b'

【讨论】:

    【解决方案2】:

    要为 char 添加一些值,请使用以下内容。您可以通过循环遍历整个字符串来执行此操作。

    int main()
    {
        char ch = 'a';  // or some other character
        int x = 2;  // or some other value
        ch = (ch - 'a' + x) % 26 + 'a';  // make sure you have a value between 'a' and 'z'
    
        printf("%c\n", ch); // prints 'c'
    }
    

    【讨论】:

    • 谢谢,这很有用。但这真的算指针算术吗……?
    • 好吧,我对你的锻炼并不完全理解。它说:“向前和向后遍历字符串。”然后“在每个字母中添加/减去 1 到 5 之间的单个值(键)”。所以我不太确定你应该做什么。
    • 是的......我也无法连接这些点。尽管如此,还是感谢您的意见。
    • 指针算法用于指向字母(遍历)。所以 pointer+=1 向右移动一位,pointer-=1 向左移动一位......只需通过比较 &given 和 &given +strlen(given) 来确保你留在字符串内
    • 所以你只需要使用指针算法来遍历字符串吗?然后你可以从角色中添加或减去东西?
    【解决方案3】:

    你需要在这里应用两个概念:

    首先,pointer 是一个变量,其中包含given[] 中某个字符的地址

    如果给它加 1,它将指向下一个字符。如果从中减去 1,它将指向前一个字符。

    但您需要将其保持在数组的边界内。所以pointer永远不能小于&given[0](或者只是given,它也计算第一个元素的地址),当它指向空字符(\0)时,你应该停止递增字符串的结尾。您可以通过创建一个循环来执行此操作,该循环在每次迭代时递增pointer,通过在指向空字符时将pointer 重置为given 来处理边界,并在再次遇到T 时停止。

    第二,*pointerpointer指向的字符。

    您可以通过添加或减去(*pointer) 来更改字符。例如,您已将pointer 初始化为&given[3](与given + 3 相同),因此它指向字母T。所以(*pointer) + 1 就是U(*pointer) - 2 就是R。如果要保存新角色,可以写

    *pointer = (*pointer) - 2;
    

    或者只是

    (*pointer) -= 2;
    

    您还需要担心字母表“掉到最后”。例如,(*pointer) + 7 将是Z 之后的字符,但您可能希望它“环绕”回A。最简单的方法是如果*pointer > 'Z' 减去26(因为字母表中有26 个字母),或者如果*pointer < 'A' 加上26。您也可以使用取模运算符 (%),但这更复杂。


    综合起来:

    • 我们知道我们将始终添加一个介于 -5 和 5 之间的常数值。
    • 我们将通过将每个值添加到字符串中的每个字符并打印结果来测试每个值。

    这是一个可以做到这一点的算法:

    1. 使用变量创建一个循环,例如 key,该变量从 -5 运行到 5。
    2. 在循环内部,将given 重置为其初始字符串。
    3. 同样在循环内部,创建一个 second 循环
      1. pointer初始化为given + 3
      2. key 的值添加到*pointer 处的字符,
      3. 在每次迭代期间增加 pointer
      4. pointer 遇到空字符时返回到字符串的开头,并且
      5. pointer 再次回到given + 3 时停止。

    我会留给您编写代码。如果遇到困难,请随时更新您的问题,并记得添加您编写的代码!

    祝你好运!

    【讨论】:

    • 但是有超出AZ范围的字符,下端可以有空格、制表符、换行符、数字...,上端可以有标点符号、小写... .
    • 鉴于作业的级别,以及原始单词仅包含大写字母的事实,我敢打赌答案也是全大写单词。
    【解决方案4】:

    你基本上是在遍历这个,寻找一个模式:

    -5 BFLO CDI
    -4 CGMPADEJ
    -3 DHNQBEFK
    -2 EIORCFGL
    -1 FJPSDGHM
    +0 GKQTEHIN
    +1 HLRUFIJO
    +2 IMSVGJKP
    +3 JNTWHKLQ
    +4 KOUXILMR
    +5 LPVYJMNS
    

    但是遍历和添加键的说明一目了然,因此您需要尝试各种方式(基本上就像一个单词搜索跨越拼图的未知单词)。

    向前和向后可能意味着一直向前,然后一直向后或同时向前和向后。

    添加一个常量键(2、3 或 4)会给你一行,但是从一行中的任何点向前和向后遍历行似乎会产生垃圾,因此索引(可能带有常量)作为关键变量,因此您需要查看 '//'、'\'、'/\'、'/' 前后以及从中间到末端和末端到中间的模式,其中对角线表示方向。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-09
      相关资源
      最近更新 更多