Чтение в многострочном файле, сохранение в одном массиве 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){