Возникли проблемы при переносе данных из моего второго текстового файла во второй массив символов с использованием аргументов командной строки - PullRequest
0 голосов
/ 24 июня 2018

Точная проблема, с которой я столкнулся, заключается в том, что мы были назначены для создания программы, которая имела 2 аргумента командной строки, оба из которых были текстовыми файлами.Код, который у меня есть для arg [1], работает нормально, он читает текстовый файл и сохраняет его в массиве.Как только он сохраняется в массиве с именем key, он проходит цикл, который оставляет только буквенные символы и меняет прописные буквы на строчные.Еще раз, это работает нормально, когда я тестирую его и распечатываю окончательный массив с именем key.Когда я использую тот же код для arg [2], первый цикл (while (! Feof (file2))) даже не копирует содержимое другого текстового файла в массив, называемый plain.Он копирует весь контент, но добавляет ▒ в конце, когда я распечатываю обычный массив, чтобы проверить, есть ли у меня все символы там, прежде чем запускать его через цикл, который оставляет в нем только буквенные символы.Если я переключаю порядок файлов при вводе их в терминал, тогда второй файл работает нормально с кодом arg [1], но тогда другой файл не работает с кодом arg [2].Я использую mobaxterm, поэтому я ввожу его как "./a.out k1.txt p1.txt" без цитат, конечно.Я также прокомментировал код, который удаляет неальфа-символы в arg [2], просто чтобы попытаться выяснить, почему цикл while не правильно хранит содержимое файла.

Вот содержимое текстовых файлов

k1.txt (вместо пробела представьте, что он переходит на следующую строку):

bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.combbbbbbbbb

p1.txt:

"Если вы обнаружите, что тратите почти все свое время на теорию, начните обращать внимание на практические вещи, это улучшит ваши теории. Если вы найдетечто вы проводите почти все свое время на практике, начните обращать внимание на теоретические вещи, это улучшит вашу практику ».- Дональд Кнут

Кстати, это назначение шифрования, а k1 - это ключ, а p1 - простой текст.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

int main(int argc, char **argv) {

    printf( "\ncommandline arguments including program name:\n\n");
    int i;
    for ( i = 0; i < argc; i++ ) {
                      printf( "argument %d: %s\n", i, argv[ i ] );
    }
    printf( "\n");

    char* fname = argv[ 1 ];
    FILE *file = fopen( fname, "r" );
    char key[512];
    int x,y, z=0;

    if ( file == 0 )
    {
                      printf( "Could not open file\n" );
    } else {
                      printf( "File opened successfully\n" );

                      while(!feof(file))
                         {
                            fscanf(file, "%c", &key[z]);
                            z++;
                         }fscanf(file, "%c", &key[z]);

                            for(x=0; key[x] != '\0'; x++)
                            {
                               while(!((key[x] >= 'a' && key[x] <= 'z') || (key[x] >= 'A' && key[x] <= 'Z') || key[x] == '\0'))
                               {
                                  for(y=x; key[y] != '\0'; ++y)
                                     {
                                        key[y]=key[y+1];
                                     }
                                  key[y] = '\0';
                               }
                               key[x] = tolower(key[x]);
                            }

                            printf("Key text:\n%s\n", key);
                            fclose( file );
    }

    char* fname2 = argv[ 2 ];
    FILE *file2 = fopen( fname2, "r" );
    char plain[512];
    int j,k, l=0;


    if ( file2 == 0)
    {
       printf("Could not open file\n");
    }else {
       printf("File opened successfully\n");

                      while(!feof(file2))
                         {
                            fscanf(file2, "%c", &plain[l]);
                            l++;
                         }fscanf(file2, "%c", &plain[l]);
                           /* for(j=0; key[j] != '\0'; j++)
                            {
                               while(!((plain[j] >= 'a' && plain[j] <= 'z') || (plain[j] >= 'A' && plain[j] <= 'Z') || plain[j] == '\0'))
                               {
                                  for(k=j; plain[k] != '\0'; ++k)
                                     {
                                       plain[k]=plain[k+1];
                                     }
                                  plain[k] = '\0';
                               }
                               plain[j] = tolower(plain[j]);
                            }*/

                            printf("Plain text:\n%s\n", plain);
                            fclose(file2);
    }


return 0;
}

1 Ответ

0 голосов
/ 24 июня 2018

feof

Проверить индикатор конца файла Проверяет, установлен ли индикатор конца файла, связанный с потоком, возвращая значение, отличное от нуля, если оно есть.

Этот индикатор обычно устанавливается предыдущей операцией в потоке, который пытался прочитать в конце файла или после него.

Обратите внимание, что индикатор внутренней позиции потока может указывать на конец файла для следующей операции, но, тем не менее, индикатор конца файла не может быть установлен, пока операция не попытается прочитать в этой точке. [Акцент мой]

Теперь давайте посмотрим, как будет работать этот цикл:

                      while(!feof(file))
                     {
                        fscanf(file, "%c", &key[z]);
                        z++;
                     }fscanf(file, "%c", &key[z]);

Предположим, что fscanf() прочитал последний символ файла. После этого индикатор внутренней позиции потока указывает на EOF, но feof() вернет 0, поскольку в потоке не было выполнено ни одной операции чтения, которая установит индикатор конца файла. Следовательно, управление переходит в цикл и fscan() будет пытаться читать из file. Поскольку EOF достигнут, fscan() установит индикатор конца файла. Теперь EOF установлен, поэтому feof() вернет ненулевое значение и цикл завершится. Следовательно, при использовании feof() у вас всегда будет дополнительная итерация цикла while.
После встречи с EOF вы все еще пытаетесь читать из потока file:

fscanf(file, "%c", &key[z]);

Здесь также fscanf() вернет EOF, потому что нечего читать из потока file. Это утверждение значит меньше.

В C строки - это фактически одномерный массив символов, оканчивающийся нулевым символом \0. fscanf() не добавляет автоматически нулевой символ в конце при чтении из потока с использованием спецификатора формата %c. Таким образом, массив символов key и plain не имеет нулевого символа в конце прочитанных символов, и если вы попытаетесь напечатать их, используя %s, вы можете получить некоторые ненужные символы в выводе.

Вы можете сделать:

while ((ret = fscanf(file, "%c", &key[z])) != EOF) {
    z++;
}
key[z] = '\0';

Вы также можете прочитать строку символов из file, используя спецификатор формата %s, например:

fscanf(file, "%511s", key);

С помощью спецификатора формата %s вам не нужен цикл, и в конце сохраненной последовательности автоматически добавляется завершающий нулевой символ.

Хорошо бы добавить проверку на максимальный символьный модификатор, который на 1 меньше длины входного буфера (в вашем случае это 511).

Кроме того, вы также можете использовать fgets() для чтения из файла.


Проверьте это:

while (! Feof (file)) всегда неверно?
Чтение из файла с использованием fgets

...