【问题标题】:create the expansion numkey count a space创建扩展 numkey 计算一个空格
【发布时间】:2021-03-25 16:18:44
【问题描述】:

这是我的代码,我想用键“div”输入字符串“adiva fiqri” 但我希望键是“divdi vdivd”(空格看起来像字符串输入)但我的新键跟随字符串(包括空格)“divdivdivdi”

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

void capital(int i, int j, char str[100]){
  //converting entered string to Capital letters
 for(i=0,j=0;i<strlen(str);i++)
 {
 
   str[j]=toupper(str[i]);   
   j++;
  
 }
 str[j]='\0';
 return str[j];
}

int main()
{
 int i,j,k,numstr[100],numkey[100],numcipher[100];
 char str[100],key[100], newKey[100];
 printf("Enter a string : ");
 gets(str);
 
 
 //converting entered string to Capital letters
 /*
 for(i=0,j=0;i<strlen(str);i++)
 {
  if(str[i]!=' ')
  {
   str[j]=toupper(str[i]);   
   j++;
  }
 }
 
 str[j]='\0';
 printf("Entered string is : %s \n",str);
 */
 
 capital(i, j, str);
 printf("Entered string is : %s \n",str);
 
 
 //Storing string in terms of ascii
 for(i=0;i<strlen(str);i++)
 {
  numstr[i]=str[i]-'A';
 }
 
 //masukan kunci
 printf("Enter a key : ");
 gets(key);
 
 
    //converting entered key to Capital letters
 for(i=0,j=0;i<strlen(key);i++)
 {
 
   key[j]=toupper(key[i]);   
   j++;
  
 }
 key[j]='\0';
 
 
     //Assigning key to the string
    for(i=0;i<strlen(str);)
    {
     for(j=0;(j<strlen(key))&&(i<strlen(str));j++)
     {
      numkey[i]=key[j]-'A';
      i++;
      
     }
     
    }
   
   //enkripsi
    for(i=0;i<strlen(str);i++)
    {
     numcipher[i]=numstr[i]+numkey[i];
    if(numcipher[i]>25)
     {
      numcipher[i]=numcipher[i]-26;
    }
    
    }
     
      //generating new key
    for(i = 0, j = 0; i < strlen(str); ++i, ++j){
        if(j == strlen(key))
            j = 0;
 
        newKey[i] = key[j];
    }
    
    
    //hasil
    printf("New Key : %s \n", newKey); 
    printf("Vigenere Cipher text is : ");   
    
    for(i=0;i<strlen(str);i++)
    {
      printf("%c",(numcipher[i]+'A')); 
    }
    
 printf("\n");
}

这是我的代码,我想用键“div”输入字符串“adiva fiqri” 但我希望键是“divdi vdivd”(空格看起来像字符串输入)但我的新键跟随字符串(包括空格)“divdivdivdi”

【问题讨论】:

  • 您刚刚在同一文本中发送了两次垃圾邮件。请添加 more 详细信息,而不仅仅是相同的垃圾。更详细地解释正在发生的事情以及我们应该看的地方。删除与当前问题无关的已注释掉的代码。
  • "adiva fiqri" with key: "div" 将加密为"dldyi alyml" 请参阅Vigenère cipher
  • @davidC.Rankin 怎么样?你能纠正我的代码吗?

标签: c vigenere


【解决方案1】:

关键是要理解你只对字母进行编码和解码。所有其他字符保持不变。键的大小写无关紧要,因为键只是表示从字母表开头的偏移量。唯一的要求是从头开始测量偏移量时要与大小写保持一致。

你应该只对任何给定的字符串调用strlen()一次。如果需要保存长度,则创建一个变量,例如

    size_t  slen = strlen (str),
            klen = strlen (key);

没有必要在循环限制中使用strlen()(例如for(i=0;i&lt;strlen(str);i++))来迭代字符串。在 C 中,字符串以空字符 '\0' 结尾(例如,普通的旧 ASCII 0)。您只需使用字符作为测试进行迭代即可。当您到达 nul 终止字符时,循环将自行退出,例如

    for (i = 0; str[i]; i++)

考虑到这一点,您可以按照Vigenère cipher 的描述来编写您的加密和解密实现。您可以将加密函数编写为:

char *vigenere_encipher (char *cipher, const char *s, const char *key)
{
    char *ci = cipher;
    const char *k = key;
    
    while (*s && *s != '\n') {
        /* works encoding from upper or lower regardless of key case
         * due to key char representing offset from beginning of alphabet
         * in either case.
         */
        if (isalpha (*s)) {         /* only encodes and decodes Letters */
            if (islower (*s))
                *ci++ = (tolower (*k) - 'a' + *s - 'a') % 26 + 'a';
            else if (isupper (*s))
                *ci++ = (toupper (*k) - 'A' + *s - 'A') % 26 + 'A';
            k++;
            if (!*k)
                k = key;
        }
        else                        /* non-Letters remain unchanged */
            *ci++ = *s;
        s++;
    }
    *ci = 0;
    
    return cipher;
}

你的解密函数是:

char *vigenere_decipher (char *s, const char *cipher, const char *key)
{
    char *de = s;
    const char *k = key;
    
     while (*cipher) {
        if (isalpha(*cipher)) {     /* only encodes and decodes Letters */
            if (islower (*cipher)) {
                int off = *cipher - tolower (*k);
                if (off >= 0)
                    *de = off % 26 + 'a';
                else
                    *de = off + 26 + 'a';
            }
            else if (isupper (*cipher)) {
                int off = *cipher - toupper (*k);
                if (off >= 0)
                    *de = off % 26 + 'A';
                else
                    *de = off + 26 + 'A';
            }
            k++;
            if (!*k)
                k = key;
        }
        else                        /* non-Letters remain unchanged */
            *de = *cipher;
        de++, cipher++;
    }
    *de = 0;
    
    return s;
}

如果您愿意,您可以使用数组索引替换指针的使用(例如,使用索引为ik[i]for 循环,而不是使用指向当前字符的指针——由您决定。我发现在字符串末尾到达 nul-character 时,使用指针迭代直到 *ptr == 0; 更容易。(与使用 ptr[i] 相同)

一个完整的示例,您将key 作为第一个参数传递给程序(如果没有给出参数,则默认为"LEMON" - 以匹配上面链接中的示例)。提示用户输入要加密/解密的字符串:

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

#define MAXC 1024

char *vigenere_encipher (char *cipher, const char *s, const char *key)
{
    char *ci = cipher;
    const char *k = key;
    
    while (*s && *s != '\n') {
        /* works encoding from upper or lower regardless of key case
         * due to key char representing offset from beginning of alphabet
         * in either case.
         */
        if (isalpha (*s)) {         /* only encodes and decodes Letters */
            if (islower (*s))
                *ci++ = (tolower (*k) - 'a' + *s - 'a') % 26 + 'a';
            else if (isupper (*s))
                *ci++ = (toupper (*k) - 'A' + *s - 'A') % 26 + 'A';
            k++;
            if (!*k)
                k = key;
        }
        else                        /* non-Letters remain unchanged */
            *ci++ = *s;
        s++;
    }
    *ci = 0;
    
    return cipher;
}

char *vigenere_decipher (char *s, const char *cipher, const char *key)
{
    char *de = s;
    const char *k = key;
    
     while (*cipher) {
        if (isalpha(*cipher)) {     /* only encodes and decodes Letters */
            if (islower (*cipher)) {
                int off = *cipher - tolower (*k);
                if (off >= 0)
                    *de = off % 26 + 'a';
                else
                    *de = off + 26 + 'a';
            }
            else if (isupper (*cipher)) {
                int off = *cipher - toupper (*k);
                if (off >= 0)
                    *de = off % 26 + 'A';
                else
                    *de = off + 26 + 'A';
            }
            k++;
            if (!*k)
                k = key;
        }
        else                        /* non-Letters remain unchanged */
            *de = *cipher;
        de++, cipher++;
    }
    *de = 0;
    
    return s;
}

int main (int argc, char **argv) {

    char buf[MAXC] = "",
        cipher[MAXC] = "",
        *key = argc > 1 ? argv[1] : "LEMON",
        decode[MAXC] = "";

    fputs ("input : ", stdout);
    if (!fgets (buf, MAXC, stdin)) {
        fputs ("(user canceled input)\n", stderr);
        return 1;
    }
    printf ("key   : %s\n"
            "cipher: %s\n", key, vigenere_encipher (cipher, buf, key));

    printf ("decode: %s\n", vigenere_decipher (decode, cipher, key));
}

示例使用/输出*

使用*示例:

$ ./bin/vcipher_fn
input : ATTACKATDAWN
key   : LEMON
cipher: LXFOPVEFRNHR
decode: ATTACKATDAWN

用你的例子:

$ ./bin/vcipher_fn div
input : adiva fiqri
key   : div
cipher: dldyi alyml
decode: adiva fiqri

检查一下,如果您还有其他问题,请告诉我。

【讨论】: