C: File I / O - пример кода из книги против реальности. Пропустить .txt? - PullRequest
0 голосов
/ 12 апреля 2020

В настоящее время я изучаю главу 13 из книги C Primer Plus (6-е издание) от Prata, листинг 13.2 на странице 574, реализованной в кодовых блоках с использованием g cc. Код показан ниже. У меня есть текстовый файл с именем eddy.txt (но Win10 опускает, показывая окончание .txt, поэтому он показывает только вихревой). Программа использует этот текстовый файл в качестве аргумента через argc / argv [], считывает строку и сохраняет измененную версию в новый файл, называемый eddy.red

Проходя через объяснение книги, новый текстовый файл должен называться "eddy.red". Однако новый текстовый файл на моем компьютере называется "eddy.txt.red"

. У кого-нибудь из вас есть объяснение, почему существует разница между моим выводом? а книжный пример? Это зависит от машины / компилятора? Похоже, что ".txt" исходного файла eddy.txt попал в имя строки, поэтому при создании вывода новый файл будет называться "eddy.txt" + ". Red" = "eddy.txt .red». Это немного прискорбно, потому что было бы здорово, если бы новый файл был напрямую сохранен как файл .txt, что было бы в случае, если бы я просто выбрал имя для нового файла, например, «Alex»: fopen («Alex .txt "," w ") вместо fopen (имя," w ").

Спасибо,

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

#define LEN 50
/*
From C Primer Plus. Listing 13.2
*/

int main(int argc, char * argv[])
{
    FILE *in;
    FILE *out;
    int ch;
    char name[LEN];
    int count = 0;

    if(argc < 2)
    {
        fprintf(stderr, "Usage: %s filename\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if((in=fopen(argv[1],"r"))==NULL)
    {
        fprintf(stderr,"Couldn't open the file \"%s\"\n",argv[1]);
        exit(EXIT_FAILURE);
    }

    strncpy(name,argv[1],LEN-5);
    name[LEN-5] = '\0';
    strcat(name,".red");
    if((out=fopen(name,"w"))==NULL)
    {
        fprintf(stderr,"Cannot create output file\n");
        exit(EXIT_FAILURE);
    }
    // copy data
    while((ch=getc(in))!=EOF)
    {
        if(count++ % 3 == 0)
        {
            putc(ch, out);
        }
    }
    if(fclose(in)!=0 || fclose(out)!=0)
    {
        fprintf(stderr,"Error in closing files\n");
    }
    return 0;
}

1 Ответ

0 голосов
/ 12 апреля 2020

Если strlen(argv[1]) меньше LEN-5, то добавление ".red" не вызовет никаких проблем: достаточно места для хранения 4 символов и окончательного '\0'.
Но если argv[1] длиннее, тогда может произойти переполнение name.
Именно поэтому strncpy() используется с LEN-5 вместо strcpy().
Но strncpy() не гарантирует, что результирующая строка будет завершена нулем, если максимальная емкость достигнута.
Тогда можно (даже если не совсем правильно) поместить '\0' пять символов перед концом (name[LEN-5] = '\0';).
Таким образом, мы уверены, что в худшем случае мы можем добавить ".red" (даже если имя файла несколько урезано).

Во многих случаях, когда имя файла короче, все это не имеет никакого эффекта, поскольку уже существует '\0' до LEN-5 .
То есть "eddy.txt" станет "eddy.txt.red".

...