[英]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.