2012-08-06 243 views
0

我想根據具有不同擴展名的基本文件名命名輸出文件。在C僞代碼:C:根據文件名創建新的文件擴展名

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

我試着用以下strncatthis的例子,但我的程序不斷追加到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 
+0

無法u使用一個不同的變量的每個時間,從而具有一個變量作爲文件名和使用存儲在文件名相同的字符串根據自其他類型的strcat的幫助,它改變目標字符串的內容 – chaitanya 2012-08-06 21:20:54

+0

你不能每次增加最後一個字符嗎? – 2012-08-06 21:28:26

回答

2

類,但這是我會這樣做的方式。

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. 
+0

謝謝。你的代碼工作正常,雖然沒有解釋。 :(你的代碼與上面的pb2q和Sebastian PaaskeTørholm的解釋幫助我理解了strcat是如何工作的。 – user785179 2012-08-06 22:35:23

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必須大到足以容納附加擴展 - 房間其它字符 - 並且通過這樣做,你會打開每個文件後丟失中間的文件名。

或者,如果您的附加信息將在最後一個字符區別僅在於:

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

同樣的警告與上述申請。

+1

注意他爲什麼會得到他的問題可能會有幫助。他將它們附加在彼此之上,因爲他正在重複使用相同的字符串,而不是創建源字符串。 – kurtzbot 2012-08-06 21:22:34

+1

我們對如何爲「filename」分配存儲空間一無所知 - 緩衝區溢出的可能性很大,並且它會很大。 – marko 2012-08-06 21:28:00

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_bfilename_c是長度的緩衝區至少n+4

(你也可以使用sprintf,但它總是好要小心。)

+0

+1:更好的是,如果他的編譯器支持C99,就是使用'snprintf' – pmg 2012-08-06 21:22:45

+0

@pmg:我正要用它來更新它。 :) – 2012-08-06 21:24:00

+0

我使用的是Visual Studio 2010,它不知道函數snprintf。我只是用sprintf。 – user785179 2012-08-06 22:07:47

2

你的差不多合理的輸出,我會說:

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

將源字符串的副本到目標字符串。目標中的終止空字符被源的第一個字符覆蓋,並且在由目標中的兩個串聯形成的新字符串的末尾附加新的空字符。

所以,由filename指向的字符數組都從strcat返回,並且獲得連接結果的修改。

非常簡單的解決方法是要記住文件名長度修改前,然後:

filename[filename_length_before_modification] = '\0'; 

,這將有效地削減附加擴展,讓你回到起點與標準C庫痛

+0

如何查找「文件名」(數組)的長度?我假設做一些像int len = sizeof(filename)?然後filename [int] ='\ 0'? – user785179 2012-08-06 21:28:36

+0

更好地使用strlen(文件名)。 sizeof(文件名)最好可以返回數組的總大小,然後你將寫入超過其邊界。取決於你如何聲明它可能也只是返回sizeof(char *) – 2012-08-06 21:30:36

1

更有效的方法。它每次只複製擴展名。如果我們假設只有最後一個字符發生了變化,它可以變得更有效率(請參閱pb2q的second solution)。

(未經測試,關閉由一個有可能的)

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.