Reputation: 11
I'm tryin to read in a multiline file.
"Will you walk a little faster?" said a whiting to a snail,
"There's a porpoise close behind us, and he's treading on my
tail.
See how eagerly the lobsters and the turtles all advance!
They are waiting on the shingle-will you come and join the
dance?
I was hoping to store it in a single array, no malloc, max size of the file is 500 chars. Then I need to go through the array and xor each char with one of 2 keys.
My problem is that I can't seem to get it into a single array. I searched before I asked a dumb question. Heres the code I have so far.
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>
//encryption and decryption fnct prototypes go here
void encrypt(FILE * input, char a, char b);
void decrypt(FILE *cypher,char a, char b);
int main(int argc, char *argv[] ){
FILE *finp, *fkey;
char left, right, key1, key2, operation, key[2];
char line[500], input[500];
int i = 0, length, total_length, x;
//read in file store as key1 and key2
if( (fkey = fopen(argv[3], "r")) == NULL){
puts( "Key file could not be opened");
exit (1);
}
else{
//get 1st char and store in key 1
if(fgets( key, 2, fkey ) != NULL){
key1 = key[0];
}
//get 2nd char in store in key 2
if(fgets( key, 2, fkey ) != NULL){
key2 = key[0];
}
//close keyfile
if( fclose( fkey ) == EOF)
puts("error in closing key file");
}
if( (finp = fopen(argv[2], "r") ) == NULL){
puts("input file could not be opened\n");
}
else{
//this right here is what I'm confused about
while(fgets(line, 501, finp) != NULL){
length = strlen(line);
total_length += strlen(line);
//for loop to write char by char from line to input
//get length of input in loop as well
for(x = total_length - length; x < total_length; x++){
input[x] = line[x];
}
}
printf("%d\n", total_length);
for(x = 0; x < total_length; x++)
printf("%c", input[x]);
//end confusion**************
operation = tolower( (int) argv[1]);
if( ((int)argv[1]) == 'd' ){
//call decrypt fnct
}
else if( ((int)argv[1]) == 'e' ){
//call encrypt fnct
}
}
if( fclose( finp ) == EOF)
puts("error in closing input file");
return 0;
}
I commented the portion I need a hand with. Any reply would be appreciated. It is a work in progress, don't be too hard on me. Thanks.
Upvotes: 1
Views: 1075
Reputation: 11
So when calling the encrypt function it works fine on
"Will you walk a little faster?" said a whiting to a snail,
"There's a porpoise close behind us, and he's treading on my
tail.
See how eagerly the lobsters and the turtles all advance!
They are waiting on the shingle-will you come and join the
dance?
But when using decrypt it seems like reading the encrypted file in is dropping and scrambling the last few characters.
N:)N9ImU%DmM$U9M(.S"B"E$M(+L=S"W(%H>>I$O$O*9@$Ma+O)``=N8SmU%DmV,U(S>"GmU%Dmo$M(+OmD;D?XmF"M)D#>B,M( f
is supposed to come out to
How doth the little crocodile
Improve his shining tail,
And pour the waters of the Nile
On every golden scale!
but when I run the program scale! is changed to scall and when I print the contents of input[] before it hits the decrypt function it shows that characters are being dropped. Not really sure why reading a normal file in has no problem but the encrypted file isn't working right. Here's what I got so far:
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<string.h>
//encryption and decryption fnct prototypes go here
void encrypt(char in[], char a, char b, int size);
void decrypt(char in[],char a, char b, int size);
int main(int argc, char *argv[] ){
FILE *finp, *fkey;
char left, right, key1, key2;
char file[501] = {""}, input[501] = {""}, key[2];
int length = 0, operation;
//read in file store as key1 and key2
if( (fkey = fopen(argv[3], "r")) == NULL){
puts( "Key file could not be opened\n");
exit (1);
}
else{
//get 1st char and store in key 1
if(fgets( key, 2, fkey ) != NULL){
key1 = key[0];
}
//get 2nd char in store in key 2
if(fgets( key, 2, fkey ) != NULL){
key2 = key[0];
}
//close keyfile
if( fclose( fkey ) == EOF){
puts("error in closing key file\n");
exit(1);
}
}
//attempt to open input file
if( (finp = fopen(argv[2], "r") ) == NULL){
puts("input file could not be opened\n");
exit(1);
}
//if opening the file works
else{
//code in question*******************
//read the file in line by line
while(fgets(file, 501, finp) != NULL){
//keep track of the length of the input
length += strlen(file);
//concatenate file into input
strcat(input, file);
}
//end code in question****************
//tests
printf("%d\n", length);
printf("%s", input);
//make the e or d lowercase in case a D or E is entered
operation = tolower( (int)(argv[1][0]) );
//if it calls for decryption, call the decrypt fnct
if( operation == 'd' ){
decrypt(input, key1, key2, length);
}
//if it calls for encryption, cal the encrypt fnct
if( operation == 'e' ){
encrypt(input, key1, key2, length);
}
}
if( fclose( finp ) == EOF){
puts("error in closing input file\n");
exit(1);
}
return 0;
}
//encrypt fnct
void encrypt(char in[], char a, char b, int size){
char left, right;
int x = 0;
FILE * fout;
if((fout = fopen("out.txt", "a")) == NULL){
printf("Problem opening output file\n");
exit(1);
}
if(size % 2 == 0){
if((fout = fopen("out.txt", "a")) == NULL){
printf("Problem opening output file\n");
exit(1);
}
for(x = 1; x < size - 1; x += 2){
//create out.txt overwrite the previous version on first iteration
if(x == 1){
if((fout = fopen("out.txt", "w")) == NULL){
printf("Problem opening output file\n");
exit(1);
}
}
else if(x == 3){
//second iteration close out.txt
if(fclose( fout ) == EOF){
puts("Problem closing output file\n");
exit(1);
}
//reopen out.txt to append only
if((fout = fopen("out.txt", "a")) == NULL){
printf("Problem opening output file\n");
exit(1);
}
}
left = in[x - 1];
right = in[x];
left ^= b;
right ^= a;
putc(left, fout);
putc(right, fout);
}
}
else{
for(x = 1; x < size - 3; x += 2){
if(x == 1){
if((fout = fopen("out.txt", "w")) == NULL){
printf("Problem opening output file\n");
exit(1);
}
}
else if(x == 3){
//second iteration close out.txt
if(fclose( fout ) == EOF){
puts("Problem closing output file\n");
exit(1);
}
//reopen out.txt to append only
if((fout = fopen("out.txt", "a")) == NULL){
printf("Problem opening output file\n");
exit(1);
}
}
left = in[x - 1];
right = in[x];
left ^= b;
right ^= a;
putc(left, fout);
putc(right, fout);
}
x += 1;
left = in[x];
left ^= b;
left ^= a;
putc(left, fout);
}
if(fclose( fout ) == EOF){
puts("Problem closing output file\n");
exit(1);
}
printf("out.txt created\n");
}
//decrypt fnct
void decrypt(char in[], char a, char b, int size){
char left, right;
int x = 0;
FILE * fout;
if((fout = fopen("out.txt", "a")) == NULL){
printf("Problem opening output file\n");
exit(1);
}
if(size % 2 == 0){
if((fout = fopen("out.txt", "a")) == NULL){
printf("Problem opening output file\n");
exit(1);
}
for(x = 1; x < size; x += 2){
//create out.txt overwrite the previous version on first iteration
if(x == 1){
if((fout = fopen("out.txt", "w")) == NULL){
printf("Problem opening output file\n");
exit(1);
}
}
else if(x == 3){
//second iteration close out.txt
if(fclose( fout ) == EOF){
puts("Problem closing output file\n");
exit(1);
}
//reopen out.txt to append only
if((fout = fopen("out.txt", "a")) == NULL){
printf("Problem opening output file\n");
exit(1);
}
}
left = in[x - 1];
right = in[x];
left ^= b;
right ^= a;
putc(left, fout);
putc(right, fout);
}
}
else{
for(x = 1; x < size - 1; x += 2){
if(x == 1){
if((fout = fopen("out.txt", "w")) == NULL){
printf("Problem opening output file\n");
exit(1);
}
}
else if(x == 3){
//second iteration close out.txt
if(fclose( fout ) == EOF){
puts("Problem closing output file\n");
exit(1);
}
//reopen out.txt to append only
if((fout = fopen("out.txt", "a")) == NULL){
printf("Problem opening output file\n");
exit(1);
}
}
left = in[x - 1];
right = in[x];
left ^= b;
right ^= a;
putc(left, fout);
putc(right, fout);
}
x += 1;
left = in[x];
left ^= a;
left ^= b;
putc(left, fout);
}
if(fclose( fout ) == EOF){
puts("Problem closing output file\n");
exit(1);
}
printf("out.txt created\n");
}
Upvotes: 0
Reputation: 84579
This is one of the circumstances where line-input is not what you want (generally it is when reading an entire text file). However, since you want to read the entire file at once, you need character input. Here is one approach to reading the entire file into input
(just make sure input is large enough to hold the file -- perhaps check with stat
):
char input[1024] = {0}; /* initializing all elements null insurses null-termination */
...
size_t index = 0;
while ((input[index++] = fgetc (finp)) != EOF);
When the file is read into input
, input
is already null-terminated
so it can be treated as a string with appropriate cast. index
holds the number of characters read. (like strlen
, if there were 25
chars read, index
will be 25
representing characters in elements 0-24
).
As you read the characters into the array, you will also want to check that the number read hasn't exceeding the size of your array to prevent a write beyond the end of your array. Rather than hardcoding the size in the declaration of the array, you can create a #define
at the start of your code that provides a convenient value to check against (as well as providing a single place to conveniently adjust the size of the array if necessary):
#define MAXS 1024
...
char input[MAXS] = {0}; /* initializing all elements null insurses null-termination */
...
size_t index = 0;
while ((input[index++] = fgetc (finp)) != EOF) {
if (index == MAXS) {
fprintf (stderr, "error: file array size exceeded. (%d bytes read)\n", MAXS);
break;
}
}
Lastly, I know you said "no malloc"
, but when reading files, etc. where the length can vary, this is the precise situation where dynamic allocation/reallocation provides flexibility. You can allocate space simply with either malloc
or calloc
(advantage of setting all characters to 0
) and proceed to read just as you would with the static declaration. However, here, when index == MAXS
, you simply realloc
to provide more space and keep reading.
Upvotes: 1
Reputation: 5132
Your for
loop should look something like
for(i = 0, x = total_length - length; x < total_length; i++, x++){
input[x] = line[i];
}
}
You could skip the for
loop entirely and just concatenate the strings with
char line[500], input[500] = ""; // initialize to an empty string
...
strcat(input, line); // instead of the for loop
Also,
a) it is a good practice to initialize total_length
to zero, like
int i, length, total_length = 0, x;
b) your fgets
should get max. 500 characters, not 501; it would be even better not to hard-code the size:
while(fgets(line, sizeof(line), finp) != NULL){
Upvotes: 0