create the expansion numkey count a space

51 Views Asked by At

this is my code, i want to input string "adiva fiqri" with key "div" but i want the key is "divdi vdivd" (with space seems like string input) but my new key is following the string (including space) "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");
}

this is my code, i want to input string "adiva fiqri" with key "div" but i want the key is "divdi vdivd" (with space seems like string input) but my new key is following the string (including space) "divdivdivdi"

1

There are 1 best solutions below

0
On

The key is to understand you only encode and decode Letters. All other characters remain unchanged. The case of the key does not matter since the key simply represents an offset from the beginning of the alphabet. The only requirement is that you be consistent with case when measuring offset from the beginning.

You should only call strlen() once on any given string. If you need to save the length, then create a variable, e.g.

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

There is no need to use strlen() in a loop limit (e.g. for(i=0;i<strlen(str);i++)) to iterate over a string. In C a string is terminated with the nul-character '\0' (e.g. plain old ASCII 0). All you need to do it iterate using the character as the test. When your reach the nul-terminating character and the loop will exit on its own, e.g.

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

With that in mind, you can follow the description at Vigenère cipher to write your encryption and decryption implementations. You can write the encrypt function as:

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;
}

And your decrypt function would be:

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;
}

If you like, you can replace the use of pointers with array indexes (e.g. using a for loop with index i and k[i] instead of using a pointer to the current character -- up to you. I find it easier just to iterate with a pointer until *ptr == 0; when the nul-character is reached at the end of the string. (just the same as using ptr[i])

A complete example where you pass the key as the first argument to the program ("LEMON" by default if no argument is given -- to match the examples in the link above). The user is prompted to enter the string to encrypt/decrypt:

#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));
}

Example Use/Output*

Using the Wikipedia Example:

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

Using your example:

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

Look things over and let me know if you have further questions.