简体   繁体   English

C:基于文件名创建新的文件扩展名

[英]C: creating new file extensions based on a filename

I would like to name output files based on a base filename with a different extension. 我想基于具有不同扩展名的基本文件名来命名输出文件。 In C psuedo-code: 在C伪代码中:

a_file = fopen(filename + ".dt1","wt");
b_file = fopen(filename + ".dt2","wt");
c_file = fopen(filename + ".dt3","wt");

I tried following this example using strncat , but my program keeps appending to filename . 我尝试使用strncat跟随示例,但是我的程序始终追加到filename

f1=fopen(strcat(filename,".dt1"),"wt");
f2=fopen(strcat(filename,".dt2"),"wt");
f3=fopen(strcat(filename,".dt3"),"wt");

This outputs: 输出:

filename.dt1
filename.dt1.dt2
filename.dt1.dt2.dt3

I need the end result to look like: 我需要最终结果看起来像:

filename.dt1
filename.dt2
filename.dt3

Your code is working as expected considering that strcat appends the extension to the given string. 考虑到strcat将扩展名附加到给定的字符串,因此您的代码按预期工作。 You're using only one string, and so the extensions get stacked upon one another. 您只使用一个字符串,因此扩展名彼此堆叠。

Here's one way to do this, amending your posted code which uses a single string for filename : 这是一种方法,可以修改发布的代码,该代码使用单个字符串作为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");

Setting this index to \\0 effectively truncates filename back to the original string between calls. 将此索引设置为\\0有效地将filename截断为filename调用之间的原始字符串。

Note that filename must be large enough to contain the appended extensions - room for 4 additional characters - and that by doing this you'll lose the intermediate file names after opening each file. 请注意, filename 必须足够大以包含附加的扩展名-可以容纳4个其他字符-并且这样做,您将在打开每个文件后丢失中间文件名。

Alternately, if your extensions will only differ in the last character: 或者,如果您的扩展名仅在最后一个字符不同:

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");

The same caveats as above apply. 适用与上述相同的警告。

That's because strcat writes directly to the buffer of the first string. 这是因为strcat直接写入第一个字符串的缓冲区。

The easiest way is probably to use snprintf to join the two strings together: 最简单的方法可能是使用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);

Here, filename is of length n (including the trailing \\0 ), and filename_a , filename_b and filename_c are buffers of length at least n+4 . 在这里, filename的长度为n (包括尾随\\0 ),而filename_afilename_bfilename_c是长度至少为n+4缓冲区。

(You could also use sprintf , but it's always good to be careful.) (您也可以使用sprintf ,但是小心总是好。)

Pretty much reasonable output of yours I would say: 我会说您的合理输出:

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

Appends a copy of the source string to the destination string. 将源字符串的副本附加到目标字符串。 The terminating null character in destination is overwritten by the first character of source, and a new null-character is appended at the end of the new string formed by the concatenation of both in destination. 目标中的终止空字符将被源的第一个字符覆盖,并且新的空字符将附加到由目标中的两个字符串串联而成的新字符串的末尾。

So, character array pointed to by filename is both returned from strcat and gets modified with concatenation result. 因此, filename所指向的字符数组既从strcat返回,又被并置结果修改。

Very easy fix is to remember filename length before modification and then: 非常简单的解决方法是在修改之前记住文件名的长度,然后:

filename[filename_length_before_modification] = '\0';

this will effectively cut appended extension and get you back to starting point 这将有效地减少附加的扩展名,并使您回到起点

Kind of a pain with standard C libs, but this is the way I would do it. 标准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.

A more efficent way. 更有效的方法。 It only copies the extension each time. 每次仅复制扩展名。 It can be made even more efficient if we assume that only the last character changes (see pb2q's second solution ). 如果我们假设仅最后一个字符发生更改,那么它可以变得更加高效(请参阅pb2q的第二个解决方案 )。

(Untested, off by one likely) (未经测试,可能减少了一个)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM