我正在尝试编写一个C程序来连接N个文件,我应该从键盘读取它们,然后获取从FILE1到n开始的所有内容并将它们放在一个NEWFILE上,我的程序连接所有N个文件但顺序不是从1到n。例如:
I input N=3 and I put three files:
text1.txt (inside the file I have "We cannot")
text2.txt ("live")
text3.txt ("without water.")
and then save the concatination on a finalresult.txt
现在我的 Finalresult.txt 应该是:
We cannot
live
without water.
但我的结果是:
withoutwater. We cannot live
这是我的完整程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int number;
scanf("%d", &number);
int i;
char a[number][50];
char help[50];
for(i=0; i<number; i++)
{
scanf("%s", help);
strcpy(a[i], help);
}
printf("Concating the content of %d files ...\n", number);
FILE * filer, * filew;
int numr,numw;
char buffer[64];
for(i=0; i<number; i++)
{
filer = fopen(a[i], "rt");
if(filer == NULL)
{
fprintf(stderr, "open read file error.\n");
exit(1);
}
filew = fopen("finalresult.txt","a+t");
if(filew==NULL) {
fprintf(stderr,"open write file error.\n");
exit(1);
}
while(feof(filer)==0) {
numr=fread(buffer,1,100,filer);
if(numr!=100) {
if(ferror(filer)) {
fprintf(stderr,"read file error.\n");
exit(1);
}
}
numw=fwrite(buffer,1,numr,filew);
if(numw!=numr) {
fprintf(stderr,"write file error.\n");
exit(1);
}
}
}
fclose(filer);
fclose(filew);
return 0;
}
最佳答案
你可以重写这个
char a[number][50];
char help[50];
for(i=0; i<number; i++)
{
scanf("%s", help);
strcpy(a[i], help);
}
作为
char a[number][50];
for(i=0; i < number; ++i)
scanf("%s", a[i]);
您不需要另一个中间缓冲区。另请记住,“%s”
仅匹配非空字符,如果您的文件名有空字符,
scanf
不会读取整个输入并在输入中留下额外的字符
缓冲区,从而扰乱下一个 scanf
调用。这里最好使用
fgets
。
char a[number][50];
for(i = 0; i < number; ++i)
{
if(fgets(a[i], sizeof a[i], stdin) == NULL)
{
fprintf(stderr, "Could not read the filename\n");
exit(1);
}
a[i][strcspn(a[i], "\n")] = 0; // removing newline
}
我还没有看到 fopen
的模式 't'
,它是模式的扩展吗
对于Windows?
您的代码存在问题,因为您正在调用
filew = fopen("finalresult.txt","a+t");
在循环内部,但你永远不会在循环内部关闭它。 FILE* 文件
被缓冲,
这意味着当您使用 fprintf(file,...)
或 fwrite(..., file)
内容被缓冲并且内容以物理方式写入文件中
稍后,例如当缓冲区已满或您使用 fflush(filew) 时。所以
当您在执行 fflush
或 fclose
之前 fopen
相同的文件时,旧的
缓冲的内容保留在缓冲区中,并在稍后的时间点写入(在
程序退出时的情况),从而覆盖您的新内容。您的新内容
都会有同样的命运。最后你会变得一团糟,因为内容
在程序结束时被覆盖。这就是为什么你会看到“垃圾”
文件。
因此,您必须先执行 fclose
,然后再使用相同的文件名执行 fopen
,或者
最好在循环之前执行fopen
。
此检查也不正确:
if(numr!=100) {
if(ferror(filer)) {
fprintf(stderr,"read file error.\n");
exit(1);
}
}
只有当文件大小是 100 的倍数时,这才是正确的。如果不是,
最后一个 block 将少于 100 个字节,您将结束程序,
即使 fread
没有错误。
所以我会像这样重写你的程序:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(void)
{
size_t num_of_files;
printf("Enter the number of files: ");
fflush(stdout);
if(scanf("%zu", &num_of_files) != 1)
{
fprintf(stderr, "Could not read the number of files\n");
exit(1);
}
int c;
// clearing the input buffer
while((c = getchar()) != '\n' && c != EOF);
char fnames[num_of_files][50];
for(size_t i = 0; i < num_of_files; ++i)
{
printf("Enter the filename %zu: ", i+1);
fflush(stdout);
if(fgets(fnames[i], sizeof fnames[i], stdin) == NULL)
{
fprintf(stderr, "Could not read the filename\n");
exit(1);
}
fnames[i][strcspn(fnames[i], "\n")] = 0; // removing newline
}
FILE *filew = fopen("finalresult.txt", "wt");
if(filew == NULL)
{
fprintf(stderr, "Could not open file finalresult.txt for writing: %s\n",
strerror(errno));
exit(1);
}
for(size_t i = 0; i < num_of_files; ++i)
{
FILE *filer = fopen(fnames[i], "rt");
if(filer == NULL)
{
fprintf(stderr, "could not open %s for reading, skipping: %s\n",
fnames[i], strerror(errno));
continue;
}
char buffer[100];
size_t len;
while((len = fread(buffer, 1, sizeof buffer, filer)) != 0)
{
if(fwrite(buffer, 1, len, filew) != len)
{
fprintf(stderr, "Error writing finalresult.txt\n");
fclose(filer);
fclose(filew);
exit(1);
}
}
if(!feof(filer))
fprintf(stderr, "file %s could not be read completely\n", fnames[i]);
fclose(filer);
}
fclose(filew);
return 0;
}
关于c - 我想连接 n 个文件,但连接顺序不正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48968479/