【问题标题】:Comparing letters with enum将字母与枚举进行比较
【发布时间】:2020-05-20 21:20:46
【问题描述】:

尝试使用凯撒密码。

enum alfabeto{
    A=0,B,C,D,E,F,G,H,I,L,M,N,O,P,Q,R,S,T,U,V,Z         // 21
};

void cifra(char *string, int k){
    enum alfabeto letter;    // initialize the enum letter
    size_t i = 0;    // initialize counter
    while (*(string+i)!='\0'){    // while string is not ended
        letter = *(string+i);     // attempt to "link" the enum letter to the equivalent (already uppercased) char
        printf("%d", letter);
        letter = (letter+k) % 21;    // then it increases of a factor k and if it goes out of 21, it should take the right value
        printf(" %d\n", letter);
        ++i;
    }
}

输出:

$ ./"cesare" 

write the text:
>TEST

choose the factor k:
>2

84 8
69 14
83 7
84 8

值错误...可能是因为我无法将枚举值“链接”到字符...我该怎么做?c

【问题讨论】:

  • 1) 为什么不是完整的字母表? 2) 为什么是*(string+i) 而不是string[i]
  • 每个输入字母都被编码为ASCII值(例如T -> 84),但是你的输出值限制在[0, 21)范围内,不对应与 ASCII 字母表。您需要将它们移回正确的范围;这通常通过添加 'a''A' 的“基础”值来完成,具体取决于输入的情况。
  • 您需要一个字符查找字符数组来匹配您的枚举。 C 中的枚举名称没有反射。因为范围有中断,您还需要扫描该查找数组 O(n) 以查找该值,或者为缺少的字母添加填充以允许 O(1) 查找。
  • @MichaelDorgan 如何制作查找表?从来没有这样做过。

标签: c arrays string enums char


【解决方案1】:
    letter = *(string+i);     // attempt to "link" the enum letter to the equivalent (already uppercased) char

应该是:

    letter = *(string+i) - 'A';     // attempt to "link" the enum letter to the equivalent (already uppercased) char

这样,“A”将根据需要映射为零。

【讨论】:

  • 他的范围不是连续的。他还需要使用查找表来解决丢失的字母。
  • 如果只是在缺失的字母中加上“I'm a bad value”,仍然可以查找偏移量,否则是通过字母和值的Pair结构进行搜索。不错,但很烦人。
  • @DavidSchwartz 如何制作查找表?从来没有这样做过。
【解决方案2】:
//                         A B C D E F G H I  J  K L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z
const int offsetTable[] = {0,1,2,3,4,5,6,7,8,-1,-1,9,10,11,12,13,14,15,16,17,18,19,-1,-1,-1,20};
const char charLookupTable[] = "ABCDEFGHILMNOPQRSTUVZ";

// Should probably use a struct for the above to prevent size mis-matches
const int offsetTableSize = 21;

void cifra(char *str, int k){
  char letter;
  int newLetterOffset;

  printf("%s\n", str);  // Show initial string.

  while (letter = *str++){    // while string is not ended
    const int oldLetterOffset = offsetTable[letter - 'A']; // Get the old letter's offset.
    if(letter <= 'A'  || letter >= 'Z' || oldLetterOffset == -1)
    {
        printf("\nBad character %c found - ending string processing\n", letter);
        return;
    }
    newLetterOffset = (oldLetterOffset + k) % offsetTableSize; // Get the letter's position, add the global offset, and wrap to table size.
    printf("%c", charLookupTable[newLetterOffset]);  // Use that offset to read the character's value from the shortened alphabet.
  }
  printf("\n\n");
}

int main()
{
  cifra("HELLO", 0);
  cifra("HELLO", 1);
  cifra("HELLo", 1);
  cifra("YELLO", 1);

  return 0;

}

请注意,我需要 2 个表格来完成这项工作,因为我们必须进出您的缩短字符集。通常,我们会使用一个结构来保存这两个数组,但我在这个例子中保持简单。此外,数组不需要是全局的,但我将它们放在那里也是为了让事情更简单。

请注意,我还更改了您的 printf() 值以使用字符和字符串以使其更易于阅读。

最后,我添加了一些错误检查,因为你不能相信用户会给你一个好的字符串。许多安全漏洞或随机崩溃都是由此导致的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-08-28
    • 1970-01-01
    • 2022-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多