0

我想根据具有不同扩展名的基本文件名命名输出文件。在 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
4

5 回答 5

6

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 必须足够大以包含附加的扩展名 - 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");

与上述相同的警告也适用。

于 2012-08-06T21:20:34.970 回答
6

那是因为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_afilename_b并且filename_c是长度至少为 的缓冲区n+4

(你也可以使用sprintf,但小心一点总是好的。)

于 2012-08-06T21:21:34.877 回答
2

我会说你的输出非常合理:

char * strcat ( char * destination, const char * source );

将源字符串的副本附加到目标字符串。目标中的终止空字符被源的第一个字符覆盖,并且一个新的空字符附加在目标中两者连接形成的新字符串的末尾。

因此, 指向的字符数组filename既可以从连接结果返回,strcat也可以用连接结果进行修改。

非常简单的解决方法是在修改之前记住文件名长度,然后:

filename[filename_length_before_modification] = '\0';

这将有效地减少附加的扩展名并让你回到起点

于 2012-08-06T21:21:39.560 回答
2

标准 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.
于 2012-08-06T21:26:03.390 回答
1

一种更有效的方式。它每次只复制扩展名。如果我们假设只有最后一个字符发生变化,它可以变得更加高效(参见 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.
于 2012-08-07T02:50:51.240 回答