Thread: Basic text file encoder

  1. #1
    Registered User
    Join Date
    Sep 2006
    Posts
    230

    Basic text file encoder

    Hi I've been working on a basic encrypting program that will read a character of a file at a time, complement it using the '~' operator, and print it into the file. Here's the code:
    Code:
    /* EncodingTest.c
    
       A program that encodes the text file
       D:\A and A\Programming\EncodingTest.txt
    
       by complementing all its bytes.
    
       It can also decrypt the file. the first character in the file
       informs the program if it is already encrypted or not. 'e' means
       it's encrypted, and 'd' means it's ready to be used (by the user).
    
       21/7/2007		By Abda92
    
       NOTE: I've used the term "crypt" for both encryption and decryption.
    */
    #include <stdio.h>
    
    void crypt (FILE *file);
    
    int main()
    {
    	char c;						/* character to be crypted */
    	FILE *file;					/* pointer to the file */
    
    	// Open the file
    	file = fopen("D:\\A and A\\Programming\\EncodingTest.txt", "w+");
    	if (fopen("D:\\A and A\\Programming\\EncodingTest.txt", "w+") != NULL)
    	{
    		printf("File opened successfully\n");
    	}
    	else
    	{
    		printf("Error openning file\n");
    		return 0;					/* Exit program */
    	}
    
    	/* Check whether file is encrypted or decrypted and start crypt() */
    	if ((c = getc(file)) == 'e')
    	{
    		printf("File is encrypted. would you like to decrypt\? (n = no, else yes)");
    		if ((c = getchar()) == 'n') return 0;			/* Exit program */
    		else
    		{
    			rewind(file);
    			putc('d', file);
    			crypt(file);
    		}
    	}
    	else if (c == 'd')
    	{
    		printf("File is decrypted. would you like to encrypt\? (n = no, else yes)");
    		if ((c = getchar()) == 'n') return 0;			/* Exit program */
    		else
    		{
    			rewind(file);
    			putc('d', file);
    			crypt(file);
    		}
    	}
    	else
    	{
    		printf("Error crypting file\n");
    	}
    
    	fclose(file);				/* close file */
    
    	return 0;					/* Exit program */
    }
    
    void crypt (FILE *file)
    {
    	char c;
    
    	c = getc(file);
    	while (c != EOF)			/* there is still something to input */
    	{
    		char t;
    
    		t = ~c;
    		putc(t, file);
    		c = getc(file);
    	}
    
    	printf("File cryption finished\n");
    }
    The problem is that the en/decrypting doesn't even start.
    As soon as it gets to the 36th line, none of the If statements execute and the else statement executes which only contains an output to the screen telling the user what happened, then the program terminates.

    I've tried forcing the en/decryption by removing the if statements. here's the new code:
    Code:
    /* EncodingTest.c
    
       A program that encodes the text file
       D:\A and A\Programming\EncodingTest.txt
    
       by complementing all its bytes.
    
       It can also decrypt the file. the first character in the file
       informs the program if it is already encrypted or not. 'e' means
       it's encrypted, and 'd' means it's ready to be used.
    
       21/7/2007		By Abda92
    */
    #include <stdio.h>
    
    void crypt (FILE *file);
    
    int main()
    {
    	char c;						/* character to be crypted */
    	FILE *file;					/* pointer to the file */
    
    	// Open the file
    	file = fopen("D:\\A and A\\Programming\\EncodingTest.txt", "w+");
    	if (fopen("D:\\A and A\\Programming\\EncodingTest.txt", "w+") != NULL)
    	{
    		printf("File opened successfully\n");
    	}
    	else
    	{
    		printf("Error openning file\n");
    		return 0;					/* Exit program */
    	}
    	
    	crypt(file);
    	fclose(file);				/* close file */
    
    	return 0;					/* Exit program */
    }
    
    void crypt (FILE *file)
    {
    	char c;
    
    	c = getc(file);
    	while (c != EOF)			/* there is still something to input */
    	{
    		char t;
    
    		t = ~c;
    		putc(t, file);
    		c = getc(file);
    	}
    
    	printf("File cryption finished\n");
    }
    Now the problem is that the program is just erasing the contents of the file making it blank. I've also tried replacing all the getc() with fgetc() and putc() with fputc() but that didn't fix it. can someone please help me find my problem?

  2. #2
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    first of all - you should not call the fopen twice...
    And I'm not so sure about replacing characters on place...
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  3. #3
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Ugh, you got a few problems. First, you're opening the file and storing the FILE * inside a variable called file. Then you reopen the same file AGAIN inside the if statement! That's wrong. The condition should be:

    Code:
    if(file)
    Next, even though you can open a file for reading and writing at the same time, this is not a good idea to do unless you really know what you're doing. If you don't take care to separate your input and output, you'll probably get something totally wrong, as you discovered.

    What you should probably do is open the original file for reading, create a separate file, and output the encrypted version to the new file. From there you can make a design decision. You could delete the original file and then rename the new one to the name of the old one, or you could just leave them both as they are and let the user do whatever with both files.

  4. #4
    Math wizard
    Join Date
    Dec 2006
    Location
    USA
    Posts
    582
    For one, you should avoid using EOF to control loops - read the FAQ for more details.
    High elevation is the best elevation. The higher, the better the view!
    My computer: XP Pro SP3, 3.4 GHz i7-2600K CPU (OC'd to 4 GHz), 4 GB DDR3 RAM, X-Fi Platinum sound, GeForce 460, 1920x1440 resolution, 1250 GB HDD space, Visual C++ 2008 Express

  5. #5
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Quote Originally Posted by ulillillia View Post
    For one, you should avoid using EOF to control loops - read the FAQ for more details.
    No you shouldn't, you should only avoid using feof() (feof checks a flag) to control loops, EOF is perfectly fine.
    Quote Originally Posted by Abda92
    Code:
    char c;
    
    c = getc(file);
    while (c != EOF)			/* there is still something to input */
    EOF doesn't fit into a char, also fgetc() returns a signed integer.

    Code:
    int c;
    while((c = fgetc(file)) != EOF)
    {
         /* blah... */
    Last edited by zacs7; 05-22-2007 at 05:05 AM.

  6. #6
    Registered User OnionKnight's Avatar
    Join Date
    Jan 2005
    Posts
    555
    Since reading a character causes your file offset to increment you will have to decrement it before outputting the new character if you wanted to replace it.

  7. #7
    Registered User
    Join Date
    Sep 2006
    Posts
    230
    Thank you everyone. I will start improving it now. I don't think I will take long.

    by the way, can someone please explain the difference between the getc() and putc(), and fgetc() and fputc().

    Thanks again.

  8. #8
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Quote Originally Posted by Abda92 View Post
    by the way, can someone please explain the difference between the getc() and putc(), and fgetc() and fputc().
    This page does a good job breaking down the differences:

    http://man.he.net/man3/getc

  9. #9
    Registered User
    Join Date
    Sep 2006
    Posts
    230
    Yes! Thank you everyone it worked! I'm still editing the src to provide more functionality and remove any unwanted code (I found lots).

    I will post the code once I'm finished with it.

    Thanks again everyone.

  10. #10
    Registered User
    Join Date
    Sep 2006
    Posts
    230
    All right I'm having one problem writing this program. I compile the code, got many errors and warnings, fixed them all up, and compiled it again.

    The compiler gave no errors while compiling. However, when i execute the program it gives me a weird error:
    Code:
    6 [main] a 1748 _cygtls::handle_exceptions: Error while dumping state (probably corrupted stack)
    Segmentation fault (core dumped)
    Here is my new source code:
    Code:
    /* EncodingTest.c
    
       A program that encodes the text file
       D:\A and A\Programming\EncodingTest.txt
    
       by complementing all its bytes.
    
       The new file is saved in the same directory as "EncodedTest.txt".
    
       It can also decrypt the file. the first character in the file
       informs the program if it is already encrypted or not. 'e' means
       it's encrypted, and 'd' means it's ready to be used.
    
       21/7/2007		By Abda92
    */
    #include <stdio.h>
    
    void crypt (FILE *source, FILE *target);
    char askUser (void);
    int readFile (char determin, FILE *rfile);
    int writeFile (char determin, FILE *wfile);
    
    int main()
    {
    	int i;								/* Temperary purposes */
    	char determin;						/* to hold whether user wants to encrypt or decrypt (e, d) */
    	FILE *rFile;					/* pointer to the file being read */
    	FILE *wFile;				/* pointer to the file being written to */
    
    	determin = askUser();
    
    	/* Open the file to be read */
    	i = readFile(determin, rFile);
    	if (i == '\0') return 0;
    
    	/* Open file to be written to */
    	i = writeFile(determin, wFile);
    	if (i == '\0') return 0;
    
    	/* start En/Decrypting */
    	crypt(rFile, wFile);
    
    	fclose(rFile);				/* close file */
    	fclose(wFile);				/* close file */
    
    	return 0;					/* Exit program */
    }
    
    void crypt (FILE *source, FILE *target)
    {
    	char c;
    
    	c = fgetc(source);
    	while (c != EOF)			/* there is still something to input */
    	{
    		fputc((~c), target);
    		c = fgetc(source);
    	}
    
    	printf("File cryption finished\n");
    }
    
    /* Ask user whether he would like to encrypt or decrypt */
    char askUser(void)
    {
    	char c;
    
    	while(1)
    	{
    		printf("What would you like to do\? (e = encrypt, d = decrypt)\n");
    
    		if ((c = getchar()) == 'e') return 'e';
    		else if (c == 'd') return 'd';
    		else printf("Invalid operation\n");
    	}
    }
    
    /* Open the file to be read. returns 1 if successful and NULL if unsuccsessful */
    int readFile(char determin, FILE *rfile)
    {
    	if (determin == 'e')
    	{
    		rfile = fopen("D:\\A and A\\Programming\\Decrypted.txt", "r");
    
    		if (rfile != NULL)
    		{
    			printf("\"Decrypted.txt\" opened successfully\n");
    			return 1;
    		}
    		else
    		{
    			printf("Error openning file\"Decrypted.txt\"\n");
    			return '\0';
    		}
    	}
    	else
    	{
    		rfile = fopen("D:\\A and A\\Programming\\Encrypted.txt", "r");
    
    		if (rfile != NULL)
    		{
    			printf("\"Encrypted.txt\" opened successfully\n");
    			return 1;
    		}
    		else
    		{
    			printf("Error openning file\"Encrypted.txt\"\n");
    			return '\0';
    		}
    	}
    }
    
    /* Open the file to be written to. returns 1 if successful and NULL if unsuccessful */
    int writeFile(char determin, FILE *wfile)
    {
    	if (determin == 'e')
    	{
    		wfile = fopen("D:\\A and A\\Programming\\Encrypted.txt", "w");
    
    		if (wfile != NULL)
    		{
    			printf("\"Encrypted.txt\" created successfully\n");
    			return 1;
    		}
    		else
    		{
    			printf("Error creating file \"Encrypted.txt\"\n");
    			return '\0';
    		}
    	}
    	else
    	{
    		wfile = fopen("D:\\A and A\\Programming\\Decrypted.txt", "w");
    
    		if (wfile != NULL)
    		{
    			printf("\"Decrypted.txt\" created successfully\n");
    			return 1;
    		}
    		else
    		{
    			printf("Error creating file \"Decrypted.txt\"\n");
    			return '\0';
    		}
    	}
    }
    I see no problems with this code. Can someone (or some people) please help me identify this problem? I will be really thankful.

  11. #11
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    OK, one major problem you have is that, both for readFile() and writeFile(), you're passing a FILE * into a function and hoping that it'll be altered in the calling function. This will not work.

    When you end up trying to encrypt/decrypt later on, the FILE *'s you pass stand a 99.999999999999% chance or so of being invalid because the changes you make inside the read and write functions are not reflected inside main(). Either open the files in main() and pass those handles to each function, or pass the address of the FILE *'s to your read and write functions. That means your read and write functions will accept FILE **'s. Your encrypt and decrypt functions can be left alone.

  12. #12
    Registered User
    Join Date
    Sep 2006
    Posts
    230
    But don't pointers pass the address automatically?

    Thanks for replying.

  13. #13
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Pointers are simply variables that hold addresses, so in that sense, yes. You're trying to change the value of a pointer, however, and that is different.

    Let's start a little bit further back with something simpler:

    Code:
    int changenum(int x)
    {
    	++x;
    }
    If I call that function like this:

    Code:
    int y = 5;
    changenum(y);
    printf("y = %d\n",y);
    What gets printed? 5 does. In order to change the variable inside the function that calls changenum(), you need to pass the address of it and have the function accept the pointer.

    Now take this example:

    Code:
    void openfile(FILE *f)
    {
    	f = fopen("bleh.txt","r");
    }
    If I call it like this:

    Code:
    FILE *in = NULL;
    openfile(in);
    What happens? Variable in will still be NULL after running that function. In order to change it, you have to pass its address like this:

    Code:
    FILE *in = NULL;
    openfile(&in);
    
    ....
    
    void openfile(FILE **f)
    {
    	*f = fopen("bleh.txt","r");
    }
    Obviously these are just examples, and not how I recommend it to be done.

  14. #14
    Registered User
    Join Date
    Sep 2006
    Posts
    230
    So do you suggest I create another two pointer variables that point to the two pointer variables? or just use the pointer operator '&'?

    Thank you for your help I really appreciate it.

  15. #15
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Personally, I think you should just open the two files in main() and then pass them to the other functions.

    If you really badly want to do it the other way, then you have to create a regular FILE * in main() and pass it's address via the & operator.

    Edit: Another alternative is to make your read and write functions return a FILE * instead of accept one. That way in main() you can just do something like:

    Code:
    int main(void)
    {
    	FILE *in = readFile(...);
    	...
    }
    
    ...
    
    FILE *readFile(char determin)
    {
    	...
    }
    If the function readFile() fails, you can return NULL. Then inside main(), you can check the value of the FILE * returned and see if there was an error by whether or not it's NULL.
    Last edited by MacGyver; 05-22-2007 at 12:16 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Can we have vector of vector?
    By ketu1 in forum C++ Programming
    Replies: 24
    Last Post: 01-03-2008, 05:02 AM
  2. gcc link external library
    By spank in forum C Programming
    Replies: 6
    Last Post: 08-08-2007, 03:44 PM
  3. Post...
    By maxorator in forum C++ Programming
    Replies: 12
    Last Post: 10-11-2005, 08:39 AM
  4. checking values in a text file
    By darfader in forum C Programming
    Replies: 2
    Last Post: 09-24-2003, 02:13 AM
  5. Outputting String arrays in windows
    By Xterria in forum Game Programming
    Replies: 11
    Last Post: 11-13-2001, 07:35 PM