vendredi 7 août 2020

Conversions between int array and string going haywire in C, what's wrong?

I'm trying to make a simplistic shift cipher with 4 possible shift values, to test my abilities with pointers and arrays.

However, trying to decode gives ' ? ' values, i.e, values that are not valid ASCII characters.

So, something is probably erroneous in the encrypt(), decrypt() or pin() functions...

But try as I might, I can find nothing...

int *pin() 
{
    
    int num,q=0; static int pins[6];

    
    printf("Enter 6-digit PIN : ");
    scanf("%d", &num);

    
    for(register int i = 100000 ; i >= 1 ; i = (i/10)) // i is position of digit.
    {
        int d = ((num - (num % i)) / i); // d stores 'digit' ( divides quotient of (num % i) by i) 
        pins[q] = d; q++;
        num = (num - ( d * i )); 
    }
    

    return pins ; // pointer to static array storing digits of PIN 
} 

//----------

void encrypt()
{
    
    char msg[3001], ch; // msg take max 3000 chars 
    int *keys, i,key[6], en[3001],len,d; // en stores encoded ints, len tracks freq of chars encoded


    printf("\n"); 
    keys = pin();
    for (i=0;i<6;i++){
        key[i] = *(keys + i); //puts each digit in a local array.
    }
    getchar(); //absorbs \n produced after pin()
    
    
    printf("\nType Message - \n\n"); 
    fgets(msg,sizeof(msg),stdin); // stores message in msg
    len = strlen(msg); // gets length of string  
    if(msg[len-1] == '\n')
         msg[len-1] = '\0'; // to remove \n added by fgets()
    len -- ; // len reduced to position of char before '\0'
    
    int pk = key[2] + key[3]; // prime key = 3rd digit + 4th digit
    int ke = key[0] + key[1] + key[2]; int ko = key[3] + key[4] + key[5]; int km = key[0] * key[5]; //keys if num is even or key if number is odd, or if it is a multiple of digits. 
    for(i=0;msg[i]!='\0';i++)
    {
        ch=msg[i];
        if((ch%key[1])==0 || (ch%key[4])==0)
            d = ( km - ch );

        else if ((prime(ch))==0)
            d = ch - pk;
        else {
            if((i%2) == 0)
            d = ch - ke;
            else 
            d = ch - ko;
        }

        en[i] = d;
    }
    
    
    printf("\nEncoded message -\n\n");
    for(i= (len-1) ;i >= 0; i--) // prints till last actual char, blocks garbage vals
    {
        printf("%d ", en[i]);
    }
    printf("-222\n"); //used to terminate input in decrypt()

}

//---------

void decrypt()
{
    char msg[3001],ch;
    int *keys, i,key[6], en[3000],d,len,count=0,s_en[3000];
    
    
    printf("\n");
    keys = pin();
    for (i=0;i<6;i++){
        key[i] = *(keys + i);
    }
    
    
    printf("\nEnter encrypted message -\n\n");
    getchar();
    
    int pk = key[2] + key[3]; // prime key = 3rd digit + 4th digit
    int ke = key[0] + key[1] + key[2]; int ko = key[3] + key[4] + key[5]; int km = key[0] + key[5];     
    for(i=0; i < 3000;i++)
    {
        scanf("%d",&d);

        if(d==-222)
            break; 
        else{           
            en[i] = d;
            len++;
        }
    }
    d = 0;
    for(i = len;i>=0;i-- )
    {
        s_en[d] = en[i]; d++;
    }
    s_en[d+1]=-222;

    for(i =0;s_en[i] != -222;i++)
    {
        d = s_en[i];
        if(((km-d)%key[1])==0 || ((km-d)%key[4]) ==0)
            ch = (km - d);
        else if((prime(d+pk))==0)
            ch =(d + pk);
        else{
            if((i%2)==0)
                ch = (d+ke);
            else
                ch = (d+ko);
        }
        msg[i] = ch;
    }
    msg[i+1] = '\0';

    printf("\nDecrypted message -\n\n");
    puts(msg);
}

int prime(int n){ 
    register unsigned i;
    register unsigned short flag = 0;
    
    if(n>1) {
        for (i = 2; i <= (sqrt(n)); ++i) { // checks for factors from 2 to sqrt of number. 
            if (n % i == 0) {
                flag = 1; // flag made 1 , number is composite 
                break;
            }
        }
    }
    else
        flag = 1;
    
    return flag; // if flag == 0, n is prime !
}

In theory at least, the encrypt function does the following :

  • Checks if ASCII val of char is multiple of 2nd or 5th digit of PIN. If yes, the ASCII val is subtracted from the product of 1st and 6th digit of PIN.
  • Checks if ASCII val of char is prime. If yes, this val is reduced by sum of 3rd and 4th digit of key. If not, moves to next condition.
  • For chars fulfilling none of the above, the position of the char is checked. If even, it is reduced by sum of 1st, 2nd and 3rd digit of PIN and if odd, it is reduced by sum of 4th, 5th and 6th digit. If not, moves to next condition.
  • Stores the int vals produced by the following statements in an int array, which is then printed in reverse and then a termination character (-222) is added at the end.

In theory, the decrypt function reverses the above processes when supplied with the correct pin.

Aucun commentaire:

Enregistrer un commentaire