首页 > 解决方案 > C: 文件 I/O - 来自书籍与现实的代码示例。省略.txt?

问题描述

我目前正在学习 Prata 的 C Primer Plus(第 6 版)一书的第 13 章,第 574 页的清单 13.2 在使用 gcc 的代码块中实现。代码如下所示。我有一个名为 eddy.txt 的文本文件(但 Win10 省略了显示 .txt 结尾,所以它只显示 eddy)。程序通过 argc/argv[] 将此文本文件用作参数,读取字符串并将修改后的版本保存到名为 eddy.red 的新文件中

通过书上的解释,新的文本文件应该叫做“eddy.red” 但是,我机器上的新文本文件叫做“eddy.txt.red”

你们中有人解释为什么我的输出和书中的例子有区别吗?它依赖于机器/编译器吗?好像原来文件eddy.txt的“.txt”已经进入了字符串名,所以输出的时候,新文件会叫“eddy.txt”+“.red”=“eddy.txt” 。红色的”。这有点不幸,因为如果将新文件直接保存为 .txt 文件会很棒,如果我只是为新文件选择一个名称,例如 "Alex": fopen("Alex .txt","w") 而不是 fopen(name, "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;
}

标签: cfilefopenfclosestrncpy

解决方案


如果strlen(argv[1])小于LEN-5,则追加 ".red"不会造成任何麻烦:有足够的存储空间可容纳 4 个字符和最后的'\0'.
但如果argv[1]更长,则name 可能发生溢出。
这就是为什么strncpy()使用 withLEN-5而不是 strcpy().
strncpy()不保证如果达到最大容量,结果字符串将以空值结尾。 然后将五个字符放在末尾 ( ) 之前
是安全的(即使不是真的正确)。 这样我们就可以确定在最坏的情况下我们可以追加 (即使文件名被截断)。'\0'name[LEN-5] = '\0';
".red"

在许多情况下,当文件名较短时,所有这些都不起作用,因为已经有一个'\0'before LEN-5
所以"eddy.txt"会变成"eddy.txt.red"


推荐阅读