我目前正在学习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.red"。这有点不幸,因为如果新文件直接保存为.txt文件,那将是非常棒的,如果我只为新文件选择一个名称,例如"Alex":fopen("Alex.txt","w"(而不是fopen。
谢谢你,
#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 filenamen", 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] = ' ';
strcat(name,".red");
if((out=fopen(name,"w"))==NULL)
{
fprintf(stderr,"Cannot create output filen");
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 filesn");
}
return 0;
}
如果strlen(argv[1])
小于LEN-5
,则追加".red"
不会引起任何麻烦:有足够的存储4个字符和最终的CCD_ 4
但如果argv[1]
较长,则name
溢出可能发生
这就是为什么strncpy()
与LEN-5
一起使用而不是strcpy()
但是strncpy()
不能保证生成的字符串如果达到最大容量,将被null终止
然后放置' '
是安全的(即使不是真正正确的(结束前五个字符(name[LEN-5] = ' ';
(
通过这种方式,我们确信在最坏的情况下,我们可以附加".red"
(即使文件名被截断(。
在许多情况下,当文件名较短时,所有这些没有效果,因为之前已经有' '
LEN-5
因此"eddy.txt"
将变为"eddy.txt.red"
。