C Board  

Go Back   C Board > General Programming Boards > C Programming

Reply
 
LinkBack Thread Tools Display Modes
Old 05-22-2007, 04:44 AM   #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?
Abda92 is offline   Reply With Quote
Old 05-22-2007, 04:51 AM   #2
CSharpener
 
vart's Avatar
 
Join Date: Oct 2006
Posts: 5,336
first of all - you should not call the fopen twice...
And I'm not so sure about replacing characters on place...
__________________
If I have eight hours for cutting wood, I spend six sharpening my axe.
vart is offline   Reply With Quote
Old 05-22-2007, 04:52 AM   #3
Deathray Engineer
 
MacGyver's Avatar
 
Join Date: Mar 2007
Posts: 3,211
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.
__________________
MacGyver is offline   Reply With Quote
Old 05-22-2007, 04:52 AM   #4
Math wizard
 
Join Date: Dec 2006
Location: Minot, ND, USA
Posts: 521
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.17 GHz C2D CPU, 4 GB DDRII800 RAM (3 GB effective), X-Fi Platinum sound, GeForce 7600 GT, 1920x1440 resolution, 250 GB HDD, Visual C++ 2008 Express
ulillillia is offline   Reply With Quote
Old 05-22-2007, 05:00 AM   #5
Woof, woof!
 
zacs7's Avatar
 
Join Date: Mar 2007
Location: Australia
Posts: 3,295
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... */
__________________
"I.T. gets the chicky-babes" - M. Kelly
bakefile | vim

Last edited by zacs7; 05-22-2007 at 05:05 AM.
zacs7 is offline   Reply With Quote
Old 05-22-2007, 05:18 AM   #6
Mad
 
OnionKnight's Avatar
 
Join Date: Jan 2005
Location: Umeå, Sweden
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.
OnionKnight is offline   Reply With Quote
Old 05-22-2007, 06:05 AM   #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.
Abda92 is offline   Reply With Quote
Old 05-22-2007, 06:08 AM   #8
Deathray Engineer
 
MacGyver's Avatar
 
Join Date: Mar 2007
Posts: 3,211
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
__________________
MacGyver is offline   Reply With Quote
Old 05-22-2007, 09:32 AM   #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.
Abda92 is offline   Reply With Quote
Old 05-22-2007, 11:21 AM   #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.
Abda92 is offline   Reply With Quote
Old 05-22-2007, 11:27 AM   #11
Deathray Engineer
 
MacGyver's Avatar
 
Join Date: Mar 2007
Posts: 3,211
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.
__________________
MacGyver is offline   Reply With Quote
Old 05-22-2007, 11:41 AM   #12
Registered User
 
Join Date: Sep 2006
Posts: 230
But don't pointers pass the address automatically?

Thanks for replying.
Abda92 is offline   Reply With Quote
Old 05-22-2007, 12:02 PM   #13
Deathray Engineer
 
MacGyver's Avatar
 
Join Date: Mar 2007
Posts: 3,211
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.
__________________
MacGyver is offline   Reply With Quote
Old 05-22-2007, 12:07 PM   #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.
Abda92 is offline   Reply With Quote
Old 05-22-2007, 12:12 PM   #15
Deathray Engineer
 
MacGyver's Avatar
 
Join Date: Mar 2007
Posts: 3,211
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.
MacGyver is offline   Reply With Quote
Reply

Thread Tools
Display Modes

Forum Jump

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


All times are GMT -6. The time now is 06:37 PM.


Powered by vBulletin® Version 3.8.1
Copyright ©2000 - 2010, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.3.2

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22