2011-09-06 63 views
0

該程序想要從文件讀取。該文件中的內容是字符串「Hello,world」。然後判斷字符串的每個字符,以查看字符是否大於或等於常量字符'e',如果字符符合條件,則按字母順序將字符更改爲其前一個字符(例如,'b'更改到'一','E'改爲'D')。最後,將更改的文件內容輸出到屏幕上。同時在一個流中使用fread和fwrite導致問題

問題是,fwrite和fread是如何工作的?爲什麼我不能擺脫變量pos2來簡化表達式。如果有人能幫忙,非常感謝!

#include <stdio.h> 

int main() 

{ 
    FILE *fp; 
    char s[20]; 
    char t[20]; 
    char transfer; 
    int i; 
    int pos; // storing the position of the file before reading from the file 
    int pos1; // check the position of the file 
    int pos2; // storing the position of the file after reading from the file 
#pragma region create a file named "Hello", write "Hello, world" into the file, close it 
    if ((fp = fopen("Hello", "wb"))== NULL) 
    { 
     printf("can't open file\n"); 
     exit(0); 
    } 
    strcpy(s, "Hello, world"); 
    fwrite(s, sizeof(char)*20, 1, fp); 
    fseek(fp, 0, SEEK_SET); 
    fclose(fp); 
#pragma endregion create a file named "Hello", write "Hello, world" into the file, close it 
#pragma region read from the file named "Hello", deal with its current, write the change into the file. 
    if ((fp = fopen("Hello", "rb+")) == NULL) 
    { 
      printf("can't open file\n"); 
      exit(1); 
    } 
    i = 0; 
    while(i < 20) 
    { 
      // 提問,該處爲何不能利用fwrite的自動定位免去註釋掉的語句行(即使用了pos2的語句行)。 
      // Here is the problem. since the fread and fwrite function can move the position of the 
      // file, I think I can get rid off the following commented two sentences with the 
      // variable pos2 in it 
      pos = ftell(fp);  // storing the position before reading from file 
      fread(&transfer, sizeof(char), 1, fp); // the position of the file moved to the next char 
      // pos2 = ftell(fp); // storing the position after reading from file 
      pos1 = ftell(fp); 
      if (transfer >= 'e') // if the character greater or equal to 'e' minus 1. 
      { 
       transfer -= 1; 
      } 
      fseek(fp, pos, SEEK_SET); // back to the position where the character is read to change the char 
      fwrite(&transfer, sizeof(char), 1, fp);// the position of the file moved to the next char 
      // fseek(fp, pos2, SEEK_SET); // 
      pos1 = ftell(fp); 
      i++; 
    } 
    fseek(fp, 0, SEEK_SET); 
    fclose(fp); 
#pragma endregion read from the file named "Hello", deal with its current, write the change into the file. 
#pragma region read from the file named "Hello", output the changed string 
    if((fp = fopen("Hello", "rb")) == NULL) 
    { 
      printf("Can't open file\n"); 
      exit(2); 
    } 
    fread(t, sizeof(char)*20, 1, fp); 
    printf("The output is: %s \n", t); 
// the right output is (the two sentences above with pos2 in it is commented) : 
// The output is: Hdkkn,vnqkd 
// the wrong output is (the two sentences above with pos2 in it isn't commented): 
// The output is: Hddddddddddddddddddd燙燙燙燙Hello, world 
    fseek(fp, 0, SEEK_SET); 
    fclose(fp); 
#pragma endregion read from the file named "Hello", output the changed string 
    system("pause"); 
} 
+0

您最初將20個字節寫入文件,但's'變量僅用13個字符進行初始化。其他7個垃圾 - 應該考慮的東西。由於書寫也提高了文件的位置,所以你需要存儲pos2的標記(但是你可以完成'fseek(fp,pos1,SEEK_SET)'而不是'fseek(fp,pos2,SEEK_SET)') – nos

+0

是的,你是對。我只希望人們可以輕鬆閱讀代碼。變量pos1的使用是顯示文件位置。從文件讀取後,pos2用於存儲文件的位置,以便我可以返回到該位置。結果證明我認爲在從文件中讀取時可能有一個指針來推進文件,並且在寫入文件時有另一個指針來推進它。我沒有經驗,我靜態分配了字符串的長度來存儲文件的內容。 – toolchainX

+0

@Vicky感謝您的格式化。既然這是我第一次使用這個網站,我會在這裏做的更好。 – toolchainX

回答

0

我並沒有真正明白爲什麼你想要評論這兩條線。因爲無論你評論他們還是評論他們,什麼都不會改變。你已經擺脫了你的代碼中的pos2(這是你問的)。

所以,如果你使用下面的代碼爲while循環

pos = ftell(fp);  // storing the position before reading from file 
fread(&transfer, sizeof(char), 1, fp); 
pos1 = ftell(fp); 
if (transfer >= 'e') // if the character greater or equal to 'e' minus 1. 
{ 
    transfer -= 1; 
} 
fseek(fp, pos, SEEK_SET); 
fwrite(&transfer, sizeof(char), 1, fp); 
i++; 

然後你拿「的輸出是:Hdkkn,vnqkd」,這是預期的結果。

你也可以從文件中的每一行讀取數組並對其進行操作,然後將其寫回到文件中。通過這種方式,它可以是更通用的,你不必使用像「20」這樣的幻數。

編輯:

我用gcc 4.5.2在我的Linux平臺。我不想在其他平臺上發表評論,但正如我之前提到的,您可以將該行放入緩衝區,然後在操作後將其寫回。你可以嘗試用你的while循環替換下面的代碼:

char line[20] = {0}; 

fread(line, sizeof(char), 20, fp); 

for(i = 0; i < strlen(line); i++) 
{ 
    if(line[i] >= 'e') 
     line[i] -= 1; 
} 

fseek(fp, 0, SEEK_SET); 
fwrite(line, sizeof(char), strlen(line), fp); 

通過這種方式,你可以擺脫許多變量。這是你的選擇。

+0

感謝您的幫助。在我的編譯器(vs 2008)中,如果我沒有像上面那樣使用變量pos2,我得到的結果是Hdddddddddddddddddddd燙燙燙燙你好,世界。然後我改變了一個編譯器(MinGW中的gcc)。比我得到這樣的結果:Hddddddddddddddddddd你好,世界。最後我想在linux(cc編譯器)中試用它。我得到了正確的答案(不使用變量pos2):Hdkkn,vnqkd。我不知道它是否是編譯器中的錯誤。我想知道你使用的是什麼編譯器? – toolchainX

+0

您也可以在Windows平臺上實際失敗的地方調試程序。請分享它我不知道爲什麼。 –

+0

您對代碼的更改有效。但是我只是想知道爲什麼我的代碼沒有變量'pos2'無法工作,當我調試代碼時,發生了一些事情:變量'transfer'首先得到一個值'H',因爲'H'小於'e'什麼都沒有改變。然後'transfer'得到一個等於'e'的值'e',然後轉移的值變成'd'。在下面的迭代中,在負運算之前'transfer'的值總是'e',然後在操作之後它變爲'd'。在文件位置的操縱中一定有錯誤。但我無法弄清楚。 – toolchainX