【问题标题】:Struggling with wraparound counting in C在 C 中挣扎于环绕计数
【发布时间】:2020-11-18 21:46:01
【问题描述】:

我是新手,如果我不能很好地解释自己,请见谅。如果它有帮助,我正在为作为哈佛 CS50x 开放课程的一部分的凯撒问题集做这个。 我正在尝试使用简单的密钥将用户生成的纯文本转换为密文。为了做到这一点,我试图在我的最后一个函数中使用一个环绕计数公式。但是,有时我会打印出空白而不是新字符...帮助!

编辑:我使用的是 5 键和明文“Helloz!”去测试。期待看到Mjqqte! 而是看到空格。

#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <stdlib.h>

int convert(string n);
string k, text;
char text;
int r, c, t,x;
bool validate(string n);
//int encrypted(string n);

int main(int argc, string argv[])
{
    //accept single command-line argument, non negative integer, k with appropriate error
    k = argv[1];
    
    if (argc > 1 && argc <= 2)
    {
        //printf("Success\n%s\n", argv[1]);
        // print individual characters of argv[i]
        validate(k);
    }
    
    else //if wrong input then print error message and main should return 1
    {
        printf("Usage: ./caesar key\n");
        return 1;
    }
    
    text = get_string("plaintext:");
    t = atoi(k);
    printf("%i\n", t);
    
    convert (text);
    printf("\n");
}
    //output "ciphertext:" without a newline, with the characters roated by k positions
    //after output, print a newline and exit by returning 0 from main


bool validate(string n)
{
   for (int i = 0; k[i] != '\0'; i++)
   {
        if (48 <= k[i] && k[i] <= 57)
        {
            //printf("%c\n", k[i]);
        }
        else
        {
            printf("./caesar key\n");
            return 1;
        // save for later: printf("%s \n", k);
        }
    }
    return r;
}

int convert(string n) 
{
    //if fits within a range, Reads individual characters
    for (int i = 0; i < text[i]; i++)
    {
        if (isalpha(text[i]))
        {
            x = text[i];
            //printf("%i\n", x);
      
            c = (x+t) % 26;
            // printf("%i\n",c);
      
            printf("%c", c);
        }
        else
        {
            printf("%i", text[i]);
        }
    }
    
    return 0;
}

【问题讨论】:

  • 你在用那个 for 循环条件 i &lt; text[i] 做什么?我猜这恰好适用于短字符串(长度小于大约 65 个字符,具体取决于内容),但不是循环文本字符串的正确方法。
  • 你的c = (x+t) % 26;不正确,你丢失了字母的前缀ascii值,应该是c = 'a' + ((x - 'a' + t) % 26);。试试看。
  • 请尝试显示一个最小的独立程序来重现问题。目前我不知道你给出了什么输入,你得到了什么输出,或者你期望什么。
  • 请注意,@UriyaHarpeness 的公式仅适用于小写字母 - 您可能需要进一步处理以处理小写和大写字母
  • 当然可以,解码后的文本约定为小写,密文为大写,可以使用tolowertoupper来实现。

标签: c cs50 caesar-cipher


【解决方案1】:

这是一个适合你的实现:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

void convert(char *text, unsigned char k) {
    for (unsigned int i = 0; i < strlen(text); i++) {
        if (isalpha(text[i])) {
            // Contains the 3 leftmost bits, containing the uppercase/lowercase part.
            char c = (text[i] / 32) * 32;
            // Perform the shifting with modulo on the alphabetic index of the letter.
            text[i] = c + ((text[i] % 32) + k) % 26;
        }
    }
}

int main(int argc, char *argv[]) {
    unsigned char k = strtol(argv[1], NULL, 10);
    char text[64];

    printf("Using key %d.\n", (int) k);
    printf("Plaintext: ");
    fgets(text, 64, stdin);
    // Remove newline.
    text[strlen(text) - 1] = 0;

    convert(text, k);
    printf("Ciphertext: %s.\n", text);

    return 0;
}

试运行:

>>> cipher 4
Using key 4.
Plaintext: Test mE Right Away!!1
Ciphertext: Xiwx qI Vmklx Eaec!!1.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-06
    • 2014-08-30
    • 1970-01-01
    • 2021-08-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-30
    相关资源
    最近更新 更多