Thread: using fgets for getting multiple strings (one time pad encryption code)

  1. #1
    Registered User
    Join Date
    May 2016
    Posts
    11

    using fgets for getting multiple strings (one time pad encryption code)

    I am new to C programming. Please i need your help with the following: after compiling & running the code i wrote(one time pad encryption) on devc++ it doesn't get the two strings:it takes one string , then it shows the program is not responding. I was asked to use the fgets function, not scanf or gets, but even so i tried the gets function. It was returning answers as NULL.
    Code:
    #include<stdio.h> 
    #include<stdlib.h> 
    #include<string.h> 
    #define clear_buffer while(getchar()!='\n'); 
    char encrypt(char texte[100],char cle[100]){ 
    char encrypted; 
    int i=0; 
    while(texte[i]!='\0' && cle[i]!='\0'){ 
        encrypted=(texte[i]+cle[i])%26; 
        i++; 
    return encrypted;   
    } 
    } 
    char decrypt(char encrypted[100],char cle[100]){ 
    char decrypted; 
    int i=0; 
    while(encrypted[i]!='\0' && cle[i]!='\0'){ 
        decrypted=(encrypted[i]-cle[i])%26; 
        i++; 
    return decrypted; 
    } 
    } 
    int main() 
    { 
    char reponse,texte[100],cle[100],encrypted[100]; 
    int i=0; 
    do{ 
    printf("Voulez vous crypter ou decrypter un texte?(Ecrire C pour crypter et D pour decrypter)\n"); 
    scanf("%c",&reponse); 
    }while (reponse!='C'&& reponse!='D'&& reponse!='c'&& reponse!='d');//controle pour obliger l'utilisateur à donner une reponse valide 
    if(reponse=='C'||reponse=='c'){ 
    printf("Donner un texte a crypter\n"); 
    fgets(texte,100,stdin); 
    while(texte[i]!=0) 
    i++; 
    if (i>0 && texte[i-1]!='\n') 
    clear_buffer; 
    printf("Donner une cle de meme taille\n"); 
    fgets(cle,100,stdin); 
    i=0; 
    while(cle[i]!=0) 
    i++; 
    if (i>0 && cle[i-1]!='\n') 
    clear_buffer; 
    printf("Le texte crypte est:%s\n",encrypt(texte,cle)); 
    
    }else{ 
    printf("Donner un texte (deja crypte) à decrypter\n"); 
    fgets(encrypted,100,stdin); 
        i=0; 
    while(encrypted[i]!=0) 
    i++; 
    if (i>0 && encrypted[i-1]!='\n') 
    clear_buffer; 
    printf("Donner la cle (deja utilisee pour crypter\n"); 
    fgets(cle,100,stdin); 
        i=0; 
    while(cle[i]!=0) 
    i++; 
    if (i>0 && cle[i-1]!='\n') 
    clear_buffer; 
    printf("Le texte decrypte est:%s\n",decrypt(encrypted,cle)); 
    } 
    system("pause"); 
    return 0; 
    }

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Just looking things over, your program has the problems described on the following pages:



    Though the first problem may not show up until you try to fool the program by not entering C or D when it asks you to. The page says you should "either use scanf to read everything or nothing," which I actually agree on. One preferred suggestion would be this:
    Code:
    do{ 
       printf("Voulez vous crypter ou decrypter un texte?(Ecrire C pour crypter et D pour decrypter)\n"); 
       fgets(texte, sizeof texte, stdin);
       response = texte[0];
    } while (reponse!='C' && reponse!='D' && reponse!='c' && reponse!='d');
    // continue here
    There of course may be some improvements you wish to make, like ensuring that texte[1] is '\n', and if it isn't, then rejecting the response.

    This problem is also solved by using clear_buffer; after each scanf call, or writing the scanf call as:
    Code:
     scanf(" %c", &response);
    If you take the preferred suggestion to the first problem, the second problem may be solved automatically. Choosing not to do that, you could strategically place clear_buffer; statements in between scanf and fgets calls.

    Other things: 1) What happened to the indent style... 2) Why are all the string sizes magic numbers.
    Last edited by whiteflags; 05-14-2016 at 05:06 PM.

  3. #3
    Registered User
    Join Date
    May 2016
    Posts
    11

    Question i tried the code now

    Quote Originally Posted by whiteflags View Post
    Just looking things over, your program has the problems described on the following pages:



    Though the first problem may not show up until you try to fool the program by not entering C or D when it asks you to. The page says you should "either use scanf to read everything or nothing," which I actually agree on. One preferred suggestion would be this:
    Code:
    do{ 
       printf("Voulez vous crypter ou decrypter un texte?(Ecrire C pour crypter et D pour decrypter)\n"); 
       fgets(texte, sizeof texte, stdin);
       response = texte[0];
    } while (reponse!='C' && reponse!='D' && reponse!='c' && reponse!='d');
    // continue here
    There of course may be some improvements you wish to make, like ensuring that texte[1] is '\n', and if it isn't, then rejecting the response.

    This problem is also solved by using clear_buffer; after each scanf call, or writing the scanf call as:
    Code:
     scanf(" %c", &response);
    If you take the preferred suggestion to the first problem, the second problem may be solved automatically. Choosing not to do that, you could strategically place clear_buffer; statements in between scanf and fgets calls.

    Other things: 1) What happened to the indent style... 2) Why are all the string sizes magic numbers.
    Thank your for your help.
    I modified the code & tried it. It now gets the text properly but shows not responding after entering the word & the key.
    Any ideas?
    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #define clear_buffer while(getchar()!='\n');
    char encrypt(char texte[100],char cle[100]){
        char encrypted;
        int i=0;
        
        while(texte[i]!='\0' && cle[i]!='\0'){
            encrypted=(texte[i]+cle[i])%26;
            i++;
        }
        return encrypted;    
        
        }
    char decrypt(char encrypted[100],char cle[100]){
        char decrypted;
        int i=0;
        
        while(encrypted[i]!='\0' && cle[i]!='\0'){
            decrypted=(encrypted[i]-cle[i])%26;
            i++;
        }
        return decrypted;
        
    }
    int main()
    {
        char reponse,texte[100],cle[100],encrypted[100];
        int i=0;
        
        do{
            printf("Voulez vous crypter ou decrypter un texte?(Ecrire C pour crypter et D pour decrypter)\n");
            fgets(texte,sizeof texte,stdin);
            reponse=texte[0];
        }while (reponse!='C'&& reponse!='D'&& reponse!='c'&& reponse!='d');//controle pour obliger l'utilisateur à donner une reponse valide
        if(reponse=='C'||reponse=='c'){
            printf("Donner un texte a crypter\n");
            fgets(texte,100,stdin);
            while(texte[i]!=0)
                i++;
            if (i>0 && texte[i-1]!='\n')
                clear_buffer;
            printf("Donner une cle de meme taille\n");
            fgets(cle,100,stdin);
            i=0;
            while(cle[i]!=0)
                i++;
            if (i>0 && cle[i-1]!='\n')
                clear_buffer;
            printf("Le texte crypte est:%s\n",encrypt(texte,cle));
        
        }else{
            printf("Donner un texte (deja crypte) à decrypter\n");
            fgets(encrypted,100,stdin);    
            i=0;
            while(encrypted[i]!=0)
                i++;
            if (i>0 && encrypted[i-1]!='\n')
                clear_buffer;
            printf("Donner la cle (deja utilisee pour crypter\n");
            fgets(cle,100,stdin);
            i=0;
            while(cle[i]!=0)
                i++;
            if (i>0 && cle[i-1]!='\n')
                clear_buffer;
            printf("Le texte decrypte est:%s\n",decrypt(encrypted,cle));
        }
        system("pause");
        return 0;
    }
    Last edited by techlover1; 05-15-2016 at 12:31 AM.

  4. #4
    Registered User
    Join Date
    May 2016
    Posts
    11
    Quote Originally Posted by whiteflags View Post
    Just looking things over, your program has the problems described on the following pages:



    Though the first problem may not show up until you try to fool the program by not entering C or D when it asks you to. The page says you should "either use scanf to read everything or nothing," which I actually agree on. One preferred suggestion would be this:
    Code:
    do{ 
       printf("Voulez vous crypter ou decrypter un texte?(Ecrire C pour crypter et D pour decrypter)\n"); 
       fgets(texte, sizeof texte, stdin);
       response = texte[0];
    } while (reponse!='C' && reponse!='D' && reponse!='c' && reponse!='d');
    // continue here
    There of course may be some improvements you wish to make, like ensuring that texte[1] is '\n', and if it isn't, then rejecting the response.

    This problem is also solved by using clear_buffer; after each scanf call, or writing the scanf call as:
    Code:
     scanf(" %c", &response);
    If you take the preferred suggestion to the first problem, the second problem may be solved automatically. Choosing not to do that, you could strategically place clear_buffer; statements in between scanf and fgets calls.

    Other things: 1) What happened to the indent style... 2) Why are all the string sizes magic numbers.
    And concerning indenting, i don't know why when doing copy paste here it is gone .

  5. #5
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    It looks like you have a segmentation fault. I found it with my debugger:
    Code:
    Program received signal SIGSEGV, Segmentation fault.
    0x75e18ff0 in strlen () from C:\WINDOWS\SysWOW64\msvcrt.dll
    (gdb) bt
    #0  0x75e18ff0 in strlen () from C:\WINDOWS\SysWOW64\msvcrt.dll
    #1  0x004037dd in __mingw_pformat ()
    #2  0x00402003 in __mingw_vprintf ()
    #3  0x004013df in printf (__format=0x4080f7 <__register_frame_info+4227319> "Le texte crypte est:%s\n") at c:/tdm-gcc-32/include/stdio.h:256
    #4  0x00401693 in main () at techloveotp.c:56
    You're probably not used to reading backtraces, but that's okay. The problem occurs on line 56, which makes sense because higher in the trace there was a problem with printf.

    Now that I take a good look at your code, you have to rework some things. Let's take a look at how you call encrypt and decrypt.
    Code:
    printf("Le texte crypte est:%s\n", encrypt(texte, cle));
    printf("Le texte decrypte est:%s\n", decrypt(encrypted, cle));
    The problem with this code is that both encrypt and decrypt return a char, a single character, when printf requires a string for %s. You need to store the cipher text in one of the strings, either texte or cle, and return a pointer to the first character in the string.

  6. #6
    Registered User
    Join Date
    May 2016
    Posts
    11

    Question Thanks i modified the code.but still not working properly

    Quote Originally Posted by whiteflags View Post
    It looks like you have a segmentation fault. I found it with my debugger:
    Code:
    Program received signal SIGSEGV, Segmentation fault.
    0x75e18ff0 in strlen () from C:\WINDOWS\SysWOW64\msvcrt.dll
    (gdb) bt
    #0  0x75e18ff0 in strlen () from C:\WINDOWS\SysWOW64\msvcrt.dll
    #1  0x004037dd in __mingw_pformat ()
    #2  0x00402003 in __mingw_vprintf ()
    #3  0x004013df in printf (__format=0x4080f7 <__register_frame_info+4227319> "Le texte crypte est:%s\n") at c:/tdm-gcc-32/include/stdio.h:256
    #4  0x00401693 in main () at techloveotp.c:56
    You're probably not used to reading backtraces, but that's okay. The problem occurs on line 56, which makes sense because higher in the trace there was a problem with printf.

    Now that I take a good look at your code, you have to rework some things. Let's take a look at how you call encrypt and decrypt.
    Code:
    printf("Le texte crypte est:%s\n", encrypt(texte, cle));
    printf("Le texte decrypte est:%s\n", decrypt(encrypted, cle));
    The problem with this code is that both encrypt and decrypt return a char, a single character, when printf requires a string for %s. You need to store the cipher text in one of the strings, either texte or cle, and return a pointer to the first character in the string.
    Here is my new code:
    Code:
    #include<stdio.h>#include<stdlib.h>
    #include<string.h>
    #define clear_buffer while(getchar()!='\n');
    char* encrypt(char texte[],char cle[]){
    	char *encrypted;
    	int i=0;
    	while(texte[i]!='\0' && cle[i]!='\0'){
    		encrypted[i]=(texte[i]-65+cle[texte[i]-65])%26;
    		i++;
    	}
    	encrypted[i+1]='\0';
    	return encrypted;	
    	
    	}
    char* decrypt(char encrypted[],char cle[]){
    	char *decrypted;
    	int i=0;
    	
    	while(encrypted[i]!='\0' && cle[i]!='\0'){
    		decrypted[i]=(encrypted[i]-cle[i])%26;
    		i++;
    	}
    	decrypted[i+1]=0;
    	return decrypted;
    	
    }
    int main()
    {
    	char reponse,texte[100],cle[100],encrypted[100];
    	int i=0;
    	
    	do{
    		printf("Voulez vous crypter ou decrypter un texte?(Ecrire C pour crypter et D pour decrypter)\n");
    		scanf("%c",&reponse);
    	}while (reponse!='C'&& reponse!='D'&& reponse!='c'&& reponse!='d');//controle pour obliger l'utilisateur à donner c ou d
    	if(reponse=='C'||reponse=='c'){
    			clear_buffer;//vider le buffer apres le scanf de la reponse
    		printf("Donner un texte a crypter\n");
    		fgets(texte,100,stdin);
    		while(texte[i]!=0)
    			i++;
    		if (i>0 && texte[i-1]!='\n')
    			clear_buffer;
    		printf("Donner une cle de meme taille\n");
    		fgets(cle,100,stdin);
    		i=0;
    		while(cle[i]!=0)
    			i++;
    		if (i>0 && cle[i-1]!='\n')
    			clear_buffer;
    		printf("Le texte crypte est:%s\n",encrypt(texte,cle));
    	
    	}else{
    			clear_buffer;//vider le buffer apres le scanf de la reponse
    			//do{
    		printf("Donner un texte (deja crypte) à decrypter\n");
    		fgets(encrypted,100,stdin);	
    		i=0;
    		while(encrypted[i]!=0)
    			i++;
    		if (i>0 && encrypted[i-1]!='\n')
    			clear_buffer;
    		printf("Donner la cle (deja utilisee pour crypter\n");
    		fgets(cle,100,stdin);
    		i=0;
    		while(cle[i]!=0)
    			i++;
    		if (i>0 && cle[i-1]!='\n')
    			clear_buffer;
    	//	}while(sizeof encrypted!=sizeof cle);
    		printf("Le texte decrypte est:%s\n",decrypt(encrypted,cle));
    	}
    	system("pause");
    	return 0;
    }
    The problem now is with the final output: after i enter the word & key to be encrypted, i get some weird question marks instead of the ciphertext.

  7. #7
    Registered User
    Join Date
    May 2016
    Posts
    11
    Any ideas?
    thank you in advance

  8. #8
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    The problem now is with the final output: after i enter the word & key to be encrypted, i get some weird question marks instead of the ciphertext.
    You still aren't following my advice. I said you need to use texte or cle.

  9. #9
    Registered User
    Join Date
    May 2016
    Posts
    11
    Quote Originally Posted by whiteflags View Post
    You still aren't following my advice. I said you need to use texte or cle.
    i am sorry. i haven't understanded well. Could you clarify more?
    & by the way here is a screenshot of the input & output.using fgets for getting multiple strings (one time pad encryption code)-output-ex2-jpg

  10. #10
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Quote Originally Posted by techlover1 View Post
    i am sorry. i haven't understanded well. Could you clarify more?
    You need to rewrite both functions using these two strings only:
    Code:
    char* encrypt(char texte[],char cle[])
    char* decrypt(char encrypted[],char cle[])
    If you cannot, then you must pass in a third string, to be the memory space for the result, and return that string.

    Other ways to do this are needlessly complicated for you right now.

    & by the way here is a screenshot of the input & output.using fgets for getting multiple strings (one time pad encryption code)-output-ex2-jpg
    Well, thank you. It would have been additionally helpful to know what you wanted to see, if the program were correct. This way, if I or someone else works on the problem, we know we have a working solution before we post more advice.

  11. #11
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  12. #12
    Registered User
    Join Date
    May 2016
    Posts
    11
    Now the problem of unreadable password was solved.
    The other problem is when decrypting a ciphertext already encrypted with my program it gives a word with a letter different than the original one ;so word->encrypted ... then encrypted->decrypted gives decrypted!=word,and even on paper the ciphertext should be different than the one i'm getting

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. can you only use AES encryption on strings?
    By Anddos in forum C++ Programming
    Replies: 2
    Last Post: 10-05-2013, 07:06 PM
  2. XOR encryption is null-terminating my strings!
    By steez in forum C Programming
    Replies: 6
    Last Post: 05-31-2011, 04:16 PM
  3. Execution Time - Rijandael encryption
    By gamer4life687 in forum C++ Programming
    Replies: 5
    Last Post: 09-20-2008, 09:25 PM
  4. Confusion (Encryption of Strings)
    By Necrofear in forum C++ Programming
    Replies: 0
    Last Post: 05-03-2007, 01:13 PM
  5. Help with Simple encryption using c-style strings
    By sdevil in forum C++ Programming
    Replies: 1
    Last Post: 02-20-2006, 11:48 PM

Tags for this Thread