![](/img/trans.png)
[英]C program returns bad file descriptor on creating file with char * as filename
[英]C: creating new file extensions based on a filename
我想基于具有不同扩展名的基本文件名来命名输出文件。 在C伪代码中:
a_file = fopen(filename + ".dt1","wt");
b_file = fopen(filename + ".dt2","wt");
c_file = fopen(filename + ".dt3","wt");
我尝试使用strncat
跟随此示例,但是我的程序始终追加到filename
。
f1=fopen(strcat(filename,".dt1"),"wt");
f2=fopen(strcat(filename,".dt2"),"wt");
f3=fopen(strcat(filename,".dt3"),"wt");
输出:
filename.dt1
filename.dt1.dt2
filename.dt1.dt2.dt3
我需要最终结果看起来像:
filename.dt1
filename.dt2
filename.dt3
考虑到strcat
将扩展名附加到给定的字符串,因此您的代码按预期工作。 您只使用一个字符串,因此扩展名彼此堆叠。
这是一种方法,可以修改发布的代码,该代码使用单个字符串作为filename
:
size_t len = strlen(filename);
f1 = fopen(strcat(filename, ".dt1"), "wt");
filename[len] = '\0';
f2 = fopen(strcat(filename, ".dt2"), "wt");
filename[len] = '\0';
f3 = fopen(strcat(filename, ".dt3"), "wt");
将此索引设置为\\0
有效地将filename
截断为filename
调用之间的原始字符串。
请注意, filename
必须足够大以包含附加的扩展名-可以容纳4个其他字符-并且这样做,您将在打开每个文件后丢失中间文件名。
或者,如果您的扩展名仅在最后一个字符不同:
size_t len = 0;
f1 = fopen(strcat(filename, ".dt1"), "wt");
len = strlen(filename);
filename[len - 1] = '2';
f2 = fopen(filename), "wt");
filename[len - 1] = '3';
f3 = fopen(filename, "wt");
适用与上述相同的警告。
这是因为strcat
直接写入第一个字符串的缓冲区。
最简单的方法可能是使用snprintf
将两个字符串连接在一起:
snprintf(filename_a, n+4, "%s.dt1", filename);
snprintf(filename_b, n+4, "%s.dt2", filename);
snprintf(filename_c, n+4, "%s.dt3", filename);
在这里, filename
的长度为n
(包括尾随\\0
),而filename_a
, filename_b
和filename_c
是长度至少为n+4
缓冲区。
(您也可以使用sprintf
,但是小心总是好。)
我会说您的合理输出:
char * strcat ( char * destination, const char * source );
将源字符串的副本附加到目标字符串。 目标中的终止空字符将被源的第一个字符覆盖,并且新的空字符将附加到由目标中的两个字符串串联而成的新字符串的末尾。
因此, filename
所指向的字符数组既从strcat
返回,又被并置结果修改。
非常简单的解决方法是在修改之前记住文件名的长度,然后:
filename[filename_length_before_modification] = '\0';
这将有效地减少附加的扩展名,并使您回到起点
标准C库有点麻烦,但这就是我要这样做的方式。
char *fn = malloc(strlen(filename+5)); // Allocate a string with enough space
// for the extensions.
sprintf(fn, "%s.dt1", filename); // Copy the name with extensions into fn.
a_file = fopen(fn,"wt"); //
sprintf(fn, "%s.dt2", filename); //
b_file = fopen(fn,"wt"); //
sprintf(fn, "%s.dt3", filename); //
c_file = fopen(fn,"wt"); //
free(fn); // Free the memory gained from malloc.
更有效的方法。 每次仅复制扩展名。 如果我们假设仅最后一个字符发生更改,那么它可以变得更加高效(请参阅pb2q的第二个解决方案 )。
(未经测试,可能减少了一个)
size_t len = strlen(filename);
char *buf = malloc(len+4); // Allocate a string with enough space for the
// extensions.
strcpy(buf, filename);
char *ext = buf+len // Get a pointer to where the extension starts.
strcpy(ext, ".dt1"); // Copy the name with extensions into fn.
FILE *a_file = fopen(buf, "wt"); //
strcpy(ext, ".dt2"); //
FILE *b_file = fopen(buf, "wt"); //
strcpy(ext, ".dt3"); //
FILE *c_file = fopen(buf, "wt"); //
free(buf); // Free the memory gained from malloc.
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.