2010-11-15 96 views
0

我的目標是收集輸入並打開基於該輸入的文件。我可以傳遞一個字符串到fopen()嗎?在c

FILE* 
open_input_file (char* fileName) //opens source file to be read 
{ 
return fopen(fileName, "r"); 
} 

在前面的函數中,我從用戶收集輸入並將其保存到fileName。當我調試程序時,它告訴我fopen正在返回NULL。這不是我想要的,我不確定問題出在哪裏。

int main(void) 
{ FILE* inFile = NULL; 
    char infileName[32] = {'\0'}; 
    gather_input(infileName); // infileName is an output parameter for this 
    inFile = open_input_file(infileName); 
} 

我不知道是什麼問題。有什麼想法嗎?

回答

2

如果fopenreturns NULL,則打開失敗。 errno將持有failure codestrerror(errno)將返回爲什麼打開失敗的簡短說明。

#include <errno.h> 
#include <string.h> 

... 

int main(void) 
{ FILE* inFile = NULL; 
    char infileName[32] = {'\0'}; 
    gather_input(infileName); // infileName is an output parameter for this 
    if (!(inFile = open_input_file(infileName))) { 
     fprintf(stderr, "Error opening '%s': %s\n", 
       infileName, strerror(errno)); 
    } else { 
     // open successful 
     ... 
    } 
} 

題外話

gather_input更好地確保infileName是空值終止,以防止緩衝區溢出。最簡單的方法是將文件名緩衝區的大小定義爲宏,並將最後一個字符設置爲0.

#define FILENAMELEN 32 
void gather_input(char infileName[]) { 
    ... 
    infileName[FILENAMELEN-1]=0; 
} 

int main(void) 
{ FILE* inFile = NULL; 
    char infileName[FILENAMELEN] = {'\0'}; 

這不是很靈活。您可以改爲將文件名緩衝區的大小傳遞給gather_input

#define LENGTH(a) (sizeof(a)/sizeof(a[0])) 
void gather_input(char infileName[], size_t len) { 
    ... 
    infileName[len-1]=0; 
} 

int main(void) 
{ FILE* inFile = NULL; 
    char infileName[32] = {'\0'}; 
    gather_input(infileName, LENGTH(infileName)); // infileName is an output parameter for this 

到設定的最後一個字符,如果使用標準的字符串操作函數的替代,是使用strl*函數(strlcpy and strlcat),而不是其無界表親。如果您沒有使用strl*,則應該使用strncpystrncat

+0

我剛剛在gather_input函數中添加了一個錯誤檢查,以確保infileName以null結尾。這似乎並沒有解決問題。我還添加了你的代碼(#included errno.h並添加了if語句),但我不太確定那裏發生了什麼。錯誤消息應該打印在哪裏? – Nate 2010-11-15 06:22:08

+0

空終止事件與您所面臨的問題有關,並且更多地與防止緩衝區溢出有關(請參閱更新後的答案)。 RE:哪裏。如果你是通過命令行在終端中運行它的話。如果你是從調試器運行這個,在控制檯中。 – outis 2010-11-15 06:30:29

+0

這是什麼意思,在終端中,還是在控制檯中?出於某種原因,當我調試時,程序跳過代碼中的if語句。我將代碼發佈到pastebin(http://pastebin.com/Qbrh1v4A)上。儘管我認爲我沒有忽略任何重要的事情,但我有這樣的機會。如果你願意,你可以看一下,我會很感激的,但是如果你不願意,我絕對明白。 – Nate 2010-11-15 06:42:19

2
  1. 您是否檢查過硬盤上是否存在inFilename指向的文件?

  2. 在您的調試器中檢查infileName的值,或將printf語句顯示在屏幕上。 printf(「'%s'\ n」,infileName);

  3. 您是否在open_input_file()調用中的文件中調用了fclose()。也許文件仍然被鎖定?

編輯:我剛剛檢查了代碼。我修改了你的english_to_morse()函數。 1. 聲明比更容易遵循。 2. fgetc()返回一個int而不是char。

在初始化的頂部我加了這個。這會初始化數組中的每個字符串和未定義的「。??。」字符串。這將使得更容易找到奇怪的錯誤,因爲數組中的所有內容至少都已初始化。

我修改了代碼的不同部分,但您應該可以關注。

initialize_morse_alphanum (char morseStrings[91][6]) 
    { 
     for (int i=0;i<91;i++) 
      strcpy(morseStrings[i], ".??."); 

     .... 
     .... 



    void 
    english_to_morse(FILE* inputFile, FILE* outputFile, char morseStrings[91][6]) 
    { int convert; 

     convert = fgetc(inputFile); 
     while (convert != EOF) 
     { 
      fputs(morseStrings[convert], outputFile); 
      fputc(' ', outputFile); 
      printf ("%s ", morseStrings[convert]); 
      convert = fgetc(inputFile); 
     } 
    } 


open_output_file (char* fileName) //opens destination file to be written 
{ FILE* handle = NULL; 
    handle = fopen (fileName, "w"); <---- Remove the * from filename 
    return handle; } 

此外,正如在不同的答案中提到的,最好在代碼的不同區域添加一些邊界檢查。目前它很容易崩潰。如果我的輸入文件包含小寫字母'a'(ascii 96),則您的程序將訪問超出範圍的內存。所以你應該添加一行if(convert> ='0'& & convert < ='Z')在某處。我會讓你解決這個問題。

+0

1.是的。 2.剛剛實施,並顯示預期值。 3.沒有。我在open_input_file()之後的main()中調用了fclose()(儘管它在遇到運行時錯誤之前從未達到過這個點) – Nate 2010-11-15 06:12:00

+0

open_output_file(char * fileName)//打開要寫入的目標文件 {\t FILE * handle = NULL; \t handle = fopen(* fileName,「w」); \t return handle; } 您需要更改中間行來處理= fopen(filename,「w」);/ie。刪除* – 2010-11-15 07:10:18

+0

我還建議遵循的一個好習慣是,您一次編寫一個函數,在開始編寫下一個函數之前進行編譯,然後對其進行完全測試。這樣你就會發現錯誤。在這種情況下,程序的不同區域出現小錯誤,並且使測試和調試更加困難。這是你學會隨着時間的推移做得很好的事情,但現在是一個好習慣。 – 2010-11-15 07:37:15

0

確保gather_input正常工作。這可能是一個問題,因爲你正在嘗試閱讀你正在寫的文件?在這種情況下,請嘗試關閉並再次打開流。

+0

我不認爲gather_input是問題。你是什​​麼意思我試圖讀我正在寫的文件?我什麼時候在那個文件中寫作? – Nate 2010-11-15 06:25:28

相關問題