Чтение в многострочном файле, сохранение в одном массиве c

Я пытаюсь читать в многострочном файле.

"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?

Я надеялся сохранить его в одном массиве, без malloc, максимальный размер файла составляет 500 символов. Затем мне нужно пройти через массив и xor каждого символа с помощью одного из 2 ключей.

Моя проблема в том, что я не могу собрать его в один массив. Я искал, прежде чем задал тупой вопрос. Вот код, который у меня есть.

#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;
}

Я прокомментировал часть, с которой мне нужна рука. Любой ответ будет оценен. Это работа в процессе, не будь слишком строг ко мне. Благодарю.

3 ответа

Это одно из обстоятельств, когда ввод строки - это не то, что вам нужно (обычно это происходит при чтении всего текстового файла). Однако, поскольку вы хотите прочитать весь файл одновременно, вам необходимо ввести символ. Вот один подход к чтению всего файла в input (просто убедитесь, что ввод достаточно большой, чтобы вместить файл - возможно, проверьте с stat):

char input[1024] = {0};  /* initializing all elements null insurses null-termination */
...
size_t index = 0;
while ((input[index++] = fgetc (finp)) != EOF);

Когда файл читается в input, input уже null-terminated поэтому его можно рассматривать как строку с соответствующим приведением. index содержит количество прочитанных символов (лайк strlenесли бы были 25 Чарс читать, index будет 25 представление символов в элементах 0-24).

Когда вы читаете символы в массив, вы также захотите убедиться, что прочитанное число не превышает размер вашего массива, чтобы предотвратить запись за конец вашего массива. Вместо того, чтобы жестко задавать размер в объявлении массива, вы можете создать #define в начале вашего кода, который предоставляет удобное значение для проверки (а также предоставляет единственное место для удобной настройки размера массива при необходимости):

#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;
    }
}

Наконец, я знаю, что ты сказал "no malloc", но при чтении файлов и т. д., где длина может варьироваться, это именно та ситуация, когда динамическое распределение / перераспределение обеспечивает гибкость. Вы можете выделить место просто с помощью malloc или же calloc (преимущество установки всех символов в 0) и продолжайте читать так же, как и в случае статического объявления. Однако здесь, когда index == MAXS-А ты просто realloc чтобы обеспечить больше места и продолжать читать.

Так что при вызове функции шифрования она работает нормально

"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?

Но при использовании расшифровки кажется, что чтение зашифрованного файла сбрасывает и скремблирует последние несколько символов.

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

должен выйти

How doth the little crocodile
Improve his shining tail,
And pour the waters of the Nile
On every golden scale!

но когда я запускаю программу масштабирования! изменяется на scall, и когда я печатаю содержимое input[] до того, как он попадет в функцию расшифровки, он показывает, что символы удаляются. Не совсем уверен, почему чтение нормального файла в не имеет проблем, но зашифрованный файл работает неправильно. Вот что я получил так далеко:

#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");
}

Ваш for цикл должен выглядеть примерно так

for(i = 0, x = total_length - length; x < total_length; i++, x++){
    input[x] = line[i];
    }
}

Вы могли бы пропустить for цикл полностью и просто объединить строки с

char line[500], input[500] = ""; // initialize to an empty string
...
strcat(input, line); // instead of the for loop


Также,

а) это хорошая практика для инициализации total_length в ноль, как

int i, length, total_length = 0, x;

б) твой fgets должен получить макс. 500 знаков, а не 501; было бы еще лучше не жестко кодировать размер:

while(fgets(line, sizeof(line), finp) != NULL){
Другие вопросы по тегам