<mosaic.cnfolio.com>
PROGRAM
  1. /*--------------------------------------------------------------------------
  2. ------------------------------ PSEUDO CODE ---------------------------------
  3. ----------------------------------------------------------------------------
  4. START
  5.    Read and store length of cipher key
  6.    IF length is less than 2 or greater than 16
  7.       THEN
  8.          Display error message "Length of cipher key must be a numerical value between 2 and 16"
  9.       Add one to error count
  10.    END IF
  11.    
  12.    Read and store cipher key
  13.    IF length of cipher key is less than 2 or greater than 16
  14.       THEN
  15.          Display error message "Cipher key text must be between a length of 2 and 16"
  16.          Add one to error count
  17.    END IF
  18.    
  19.    IF cipher key is not equal to cipher key length
  20.       THEN
  21.          Display error message "The stated length of your cipher key is incorrect. The correct value is -actual length of cipher-."
  22.          Add one to error count
  23.    END IF
  24.    
  25.    WHILE we still have characters in our cipher key
  26.       IF current letter in cipher key is the same as any remaining letters in the cipher key
  27.          THEN
  28.             Display error message "Cipher key text must not contain any duplicate letters. -current letter- is a duplicate"
  29.             Add one to error count
  30.       END IF
  31.    END WHILE
  32.  
  33.    WHILE we still have characters in cipher key
  34.       IF current letter in the cipher key is not a-z lower case
  35.          THEN
  36.             Display error message "Cipher key text must only contain lowercase letters a-z, no punctuation, numbers, or special characters. Remove the following: -currentent letter-"
  37.             Add one to error count 
  38.       END IF
  39.    END WHILE
  40.    
  41.    Read and store length of plain text
  42.    IF length is less than 4 or greater than 256
  43.       THEN
  44.          Display error message "Length of plain text must be a numerical value between 4 and 256"
  45.          Add one to error count
  46.    END IF
  47.    
  48.    Read and store plain text
  49.    IF length of plain text is less than 4 or greater than 256
  50.       THEN
  51.          Display error message "Plain text must be between 4 and 256 characters long"
  52.          Add one to error count
  53.    END IF
  54.    
  55.    WHILE we still have plain text characters
  56.       IF current letter in the plain text is invalid
  57.          THEN
  58.             Display error message "Plain text must only contain lowercase letters a-z, no punctuation, numbers, or special characters. Try removing the following: -current letter-"
  59.             Add one to error count
  60.       END IF
  61.    END WHILE
  62.       
  63.    IF plain text is not equal to plain text length
  64.       THEN
  65.          Display error message "The stated length of your plain text is incorrect. The correct value is -actual text length-"
  66.          Add one to error count
  67.    END IF
  68.    
  69.    IF we have no errors (error count should be 0)
  70.       THEN
  71.          Make a copy of the plain text, which we will alter as appropriate, leaving the original untouched
  72.          Use N to indicate position in cipher key, starting from zero (the first letter of the cipher)
  73.          WHILE we have cipher key letters remaining
  74.             IF N is not the last character of the cipher key
  75.                THEN
  76.                   The character to replace it with will be N+1 which is the next character in the cipher
  77.                ELSE
  78.                   When we have no next characters, we use the first value of the cipher key as N+1
  79.             END IF
  80.             
  81.             Display "Step N+1: Replace cipher N with cipher N+1" N and N+1 being the 2 letters we are substituting
  82.             
  83.             WHILE we have plain text letters remaining, compare cipher key letter N with current plain text letter (starting at the first letter)
  84.                IF current plain text letter is the same as cipher key letter N
  85.                   THEN
  86.                      Replace current corresponding letter in plain text copy with cipher key letter N+1
  87.                END IF
  88.                Move to the next letter in plain text
  89.             END WHILE
  90.             Display altered plain text copy as ouput
  91.             Move on to the next letter in the cipher
  92.          END WHILE
  93.    END IF
  94. END
  95. ---------------------------------------------------------------------------------*/
  96.  
  97.  
  98. #include <stdio.h>
  99. #include <string.h>    //used for strlen which returns the exact length of a string, and strcopy which copies a string
  100. #include <ctype.h>      //used for ToLower function
  101.  
  102. int main( void )
  103. {
  104.    int cipherLength;
  105.    char cipher[15] = {'\0'}; //total length, minus one to account for array
  106.    int plainTextLength;
  107.    char plainText[255] = {'\0'}; //total length, minus one to account for array
  108.    int error = 0; //to keep track of errors - more than one will stop the substitution from being performed
  109.    
  110. //---------------------------------------------------------------------------------
  111. //------------------------------- READING THE INPUT -------------------------------
  112. //---------------------------------------------------------------------------------
  113.  
  114. //FIRST LINE OF INPUT - LENGTH OF CIPHER KEY
  115.    scanf("%d", &cipherLength);
  116.  
  117. //SECOND LINE OF INPUT - CIPHER KEY
  118.    scanf("%s", &cipher); //cipher key will just be a single word with no spaces, so we can scan for a string
  119.  
  120. //THIRD LINE OF INPUT - LENGTH OF PLAIN TEXT
  121.    scanf("%d", &plainTextLength);
  122.    
  123. //FOURTH LINE OF INPUT - PLAIN TEXT
  124.    scanf("%c"); //picks up and ignores linebreak just before the text input
  125.    gets(plainText); //picks up all remaining input
  126.    
  127.    
  128. //---------------------------------------------------------------------------------
  129. //-------------------------------- ERROR CHECKING  --------------------------------
  130. //---------------------------------------------------------------------------------
  131.  
  132.    if((cipherLength < 2) || (cipherLength > 16)) //If the value is out of the range
  133.    {
  134.       if(cipherLength>99) //if its a ridiculous amount outside of the range, it is probably a typo of a non-numerical value
  135.       {
  136.          printf("Stated length of cipher key may be a letter or special character, this must be an NUMBER between 2 and 16.\n");
  137.       }
  138.       else
  139.       {
  140.          printf("Stated length of cipher key is %d, this must be an integer between 2 and 16.\n", cipherLength); //otherwise we can assume it was human error and tell them exactly where they went wrong
  141.       }
  142.       error++; //add one to the error count
  143.    }
  144.    
  145.    if((strlen(cipher) < 2) || (strlen(cipher) > 16)) //If the actual string length is out of range
  146.    {
  147.       printf("Cipher key text is %d characters long, it must be between 2 and 16.\n", strlen(cipher));
  148.       error++;
  149.    }
  150.    
  151.    if(strlen(cipher) != cipherLength) //If the actual length is different to the stated length
  152.    {
  153.       printf("Your stated cipher length is %d but its actual length is %d; make sure these match.\n", cipherLength, strlen(cipher));
  154.       error++;
  155.    }
  156.    
  157.    for(int i = 0; i <= strlen(cipher); i++) //Loop through each letter of the cipher to check they're all valid
  158.    {
  159.       if(((cipher[i]<'a') || (cipher[i]>'z')) && ((cipher[i] != ' ') && (cipher[i] != '\n') && (cipher[i] != '\0')))
  160.       {     
  161.          if((cipher[i] >= 'A') && (cipher[i] <= 'Z')) //Special statement for uppercase letters, since they will likely be the most common human error.
  162.          {
  163.             cipher[i] = tolower(cipher[i]); //instead of putting an error for upper case letters, we can fix it for the user
  164.          }
  165.          else //Everything else can just be printed out to show the user what to look for
  166.          {
  167.             printf("%c is an invalid character; in the cipher, input lower case letters a-z only!\n", cipher[i]);
  168.             error++;
  169.          }
  170.       }
  171.      
  172.       for(int j=(0+i); j<(strlen(cipher)-1); j++) //Nested loop to check for duplicates. Use the outer loop variable i to keep track of where we are in the string. i.e. we don't need to compare letters that have already been compared.
  173.       {
  174.          if( cipher[i]==cipher[j+1] ) //Compare current letter to the next one, to avoid comparing it against itself
  175.          {
  176.             printf("%c is a duplicate letter; make sure no characters are repeated in the cipher.\n", cipher[i]);
  177.             error++;
  178.          }
  179.       }
  180.    }
  181.    
  182.    if((plainTextLength < 4) || (plainTextLength > 256)) //If the value is out of range
  183.    {
  184.       printf("Stated length of the plain text is %d, this must be an integer between 4 and 256.\n", plainTextLength);
  185.       error++;
  186.    }
  187.    
  188.    if((strlen(plainText) < 4) || (strlen(plainText) > 256)) //If the actual string length is out of range
  189.    {
  190.       printf("The length of the plain text is %d; it must be between 4 and 256 characters. This includes spaces!\n", strlen(plainText));
  191.       error++;
  192.    }
  193.    
  194.    if(plainTextLength != strlen(plainText)) //If the actual length is different to the stated length
  195.    {
  196.       printf("Your stated plain text length is %d but its actual length is %d; make sure these match.\n", plainTextLength, strlen(plainText));
  197.       error++;
  198.    }
  199.    
  200.    for(int i = 0; i <= plainTextLength; i++)
  201.    {     
  202.       if(((plainText[i]<'a') || (plainText[i]>'z')) && ((plainText[i] != ' ') && (plainText[i] != '\n') && (plainText[i] != '\0'))) //ignoring all expected characters
  203.       {
  204.          if((plainText[i] >= 'A') && (plainText[i] <= 'Z')) //Special statement for uppercase letters, since they will likely be the most common human error
  205.          {
  206.             plainText[i] = tolower(plainText[i]); //instead of showing an error for uppercase letters, we can fix it for the user
  207.          }
  208.          else //For all other invalid characters, print them out so they can see what to remove
  209.          {
  210.             printf("%c is an invalid character; in the plain text, input lower case letters a-z only!\n", plainText[i]);
  211.             error++;
  212.          }
  213.       }
  214.    }
  215.    
  216.  
  217. //---------------------------------------------------------------------------------
  218. //------------------------------------ OUTPUT -------------------------------------
  219. //---------------------------------------------------------------------------------
  220.    
  221.    if(!error) //If there are no errors logged
  222.    {
  223.       char copy[strlen(plainText)]; //Initialising a new string, the same size as the original plain text
  224.       strcpy(copy, plainText); //make a copy of the original plain text string and put it into the copy array
  225.       for(int n=0; n<cipherLength; n++) //keep looping until we've run out of letters in the cipher
  226.       {
  227.          if(n!=cipherLength-1) //If its NOT the last letter in the cipher
  228.          {
  229.             printf("Step %d: Substitute %c with %c\n", (n+1), cipher[n], cipher[n+1]); //Display the current step number and what letters are being swapped
  230.  
  231.             for(int i=0; i<strlen(plainText); i++) //Keep looping until we've run out of letters to swap in the plain text
  232.             {
  233.                if(plainText[i]==cipher[n]) //Use original plain text as a reference
  234.                {
  235.                   copy[i]=cipher[n+1]; //Change the copy, original text remains unchanged
  236.                }
  237.             }
  238.             printf("%s\n", copy); //Once we've changed it, display it and move on to the next step
  239.          } 
  240.          else //If its the final character in the cipher key
  241.          {
  242.             printf("Step %d: Substitute %c with %c\n", (n+1), cipher[n], cipher[0]);
  243.            
  244.             for(int i=0; i<strlen(plainText); i++) //keep looping until we've run out of letters
  245.             {
  246.                if(plainText[i]==cipher[n]) //Use original plain text as a reference
  247.                   copy[i]=cipher[0]; //Change the copy, original text is unchanged
  248.             }
  249.             printf("%s\n", copy); //Once we've finalised our changes, display it.
  250.          }
  251.       }
  252.    }
  253. }