C - Работа с fopen, fclose, fputc и т.д.

Наконец-то я получил этот код, работающий с одним аргументом в моей командной строке, то есть с одним файлом для работы, хотя я разработал код с концепцией работы с неограниченным количеством файлов. Что он делает, так это берет некоторое количество текстовых файлов X, содержащих слова, разделенные пробелами, и заменяет пробелы на \n, создавая таким образом список слов. Хотя он успешно завершает первый аргумент, он просто игнорирует второй.

Еще одна небольшая проблема заключается в том, что он также печатает какую-то мусорную букву в конце, букву Y с двумя точками над ней; Я предполагаю, что какой-то символ EOF, но я не могу остановить это!

int main(int argc, char** argv) {
    FILE *fpIn, *fpOut;
    int i, j;
    j = 1;
    char c;
    char myString[256];

    printf("%d", argc);
    printf("\n");
    printf("The following arguments were passed to main(): ");
                for(i=1; i<argc; i++) printf("%s ", argv[i]);
    printf("\n");

    while(argc--) {
        for(i = 1; i < argc; i++) {
            fpIn = fopen(argv[j], "rb");
            snprintf(myString, 256, "%s~[%d]", argv[j], i);
            fpOut= fopen(myString, "wb");
            while (c != EOF) {
                c = fgetc(fpIn);
                if (isspace(c)) 
                    c = '\n';
                fputc(c, fpOut );
            }
            j++;
        }
    }
    return 0;
}

person PnP    schedule 27.12.2011    source источник
comment
возможный дубликат Работа с текстовыми файлами Two. Ваш принятый ответ на этот вопрос объясняет, почему вы получаете этот лишний мусорный символ. Ваш код по-прежнему неверен в этом вопросе.   -  person Greg Hewgill    schedule 28.12.2011
comment
Да, это был мой предыдущий пост, хотя я добился некоторого прогресса, но обычно не получаю ответов на старые посты, поэтому я подумал, что могу написать еще один :)   -  person PnP    schedule 28.12.2011
comment
Я не очень понимаю, почему, если честно   -  person PnP    schedule 28.12.2011
comment
Короче говоря, обратите внимание на правило: Никогда не записывайте значение EOF в файл. Как это может произойти в вашем коде? (Это так, вам придется выяснить, как это исправить.)   -  person Greg Hewgill    schedule 28.12.2011
comment
Я все еще не могу заставить его работать с несколькими аргументами:/   -  person PnP    schedule 28.12.2011


Ответы (1)


Функции getchar(), getc() и fgetc() (или макросы) возвращают int, а не char.

Вы должны использовать:

int c;

while ((c = fgetc(fpIn)) != EOF)
{
    if (isspace(c))
        c = '\n';
    fputc(c, fpOut);
}

Подумай об этом; функции должны иметь возможность возвращать любой допустимый char и EOF (отличный от любого допустимого значения char. Таким образом, по определению возвращаемое значение не может быть char...

Что произойдет, если вы используете char?

  • Ваш исходный код не инициализировал c перед его тестированием (поэтому цикл может прерваться раньше).
  • Ваш код не проверял c сразу после чтения EOF (поэтому он может печатать мусорный символ, часто ÿ, СТРОЧНУЮ ЛАТИНСКУЮ БУКВУ Y С ДИЭРЕЗИСОМ, U+00FF).
  • Если ваш тип char не имеет знака, вы никогда не увидите EOF.
  • Если ваш тип char подписан, некоторые допустимые символы (часто снова ÿ)) будут неправильно интерпретированы как EOF.

Я все еще не могу заставить его работать с несколькими аргументами.

Проблема в том, что у вас запущен двойной цикл:

int i, j;
j = 1;

while (argc--)
{
    for (i = 1; i < argc; i++)
    {
        fpIn = fopen(argv[j], "rb");
        ...process fpIn...
        j++;
    }
}

Предположим, вы вызываете команду с двумя именами файлов; затем argc == 3.

После первого прохождения цикла while argc == 2. Затем вы выполняете цикл for, где i принимает значение 1; вы открываете argv[1] (потому что j == 1). Вы обрабатываете этот файл; затем увеличьте j до 2, прежде чем также увеличить i, также до 2. Второй раз вокруг цикла for i == 2, как и argc, поэтому цикл for завершается. Цикл while снова уменьшает argc до 1, но проверяет, что 2 != 0. Однако цикл for устанавливает i = 1, а затем завершается, поскольку i == argc. Цикл while уменьшает argc до 1 и повторяется.

Вы можете использовать цикл while или цикл for, но вам не нужны оба.

Итак, либо:

for (i = i; i < argc; i++)
{
    ...process argv[i]...
}

Or:

while (--argc > 0)
{
    ...process *++argv...
}

Я бы использовал цикл for.

person Jonathan Leffler    schedule 28.12.2011
comment
Спасибо, я добавил проверку, чтобы увидеть, был ли это EOF в моем текущем цикле, если ( c == EOF) {break;} Это исправлено! - person PnP; 28.12.2011
comment
Я все еще не могу заставить его работать с несколькими аргументами:/ - person PnP; 28.12.2011