c - 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;
}
解决方案
如果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"
。
推荐阅读
- ios - 导航栏的 .isTranslucent 颜色的 rgb 等效颜色是什么?
- go - gob 编码崩溃
- r - R vlookup 结合 if...and
- javascript - 为什么当我使用键盘键导航时滚动不起作用
- mysql - 从第二个表中获取 3 列和多条记录的总和
- javascript - JavaScript:解决算法问题
- css - 在闪亮的文本行中更改一个单词/子字符串的字体
- java - 我对这段代码有疑问(无法解析方法:'equals(java.lang.String)
- angular - laravel JWTAuth::attempt 在 heroku 上崩溃
- javascript - 待办事项列表应用程序和列表项长度问题