2016-01-20 22 views
-3

我是新來的文件I/O流,我想編寫一個程序,它轉換字符(由「texti.txt」讀),如「A,A,U,U ,ö,Ö「到」ae,Ae,ue,Ue,oe,Oe「並將它們寫入一個名爲」texto.txt「的新文件中。文件I/O:兩種文件pointes的

第一個問題: 可以像我一樣在同一時間有兩個文件指針(在每個文件上)可以嗎?

第二個問題: 我在做什麼錯誤的字符比較在switch語句? VS2015警告說箱子2和3已經存在(參照情況1)

Thirt問題 是否fpo(文件指針到輸出文件)自動writig炭遞增本身?

問題四: VS2015警告:

C4996 '的fopen':此函數或變量可能是不安全的。考慮使用fopen_s代替。要禁用棄用,請使用_CRT_SECURE_NO_WARNINGS。詳細信息請參見在線幫助。

我應該使用另一個函數嗎?

int main() 
{ 
    char c; 
    FILE *fpi; 
    FILE *fpo; 
    fpi = fopen("texti.txt","r"); 
    fpo = fopen("texto.txt", "w"); 
    if (fpi == NULL) 
     fprintf(stderr, "Fehler beim Lesen"); 
    while (!feof(fpi)) 
    { 
     c = fgetc(fpi); 
    switch (c) 

{ 
    case 'ä'||'Ä':  
     fputc('a', fpo); 
     fputc('e', fpo); 
     break; 

    case 'ö'||'Ö': 
     fputc('o', fpo); 
     fputc('e', fpo); 
     break; 

    case 'ü' || 'Ü': 
     fputc('u', fpo); 
     fputc('e', fpo); 
     break; 

    default: 
     fputc((c), fpo); 
    } 
    fpi++; 
} 
fclose(fpi); 
fclose(fpo); 

}

+3

您認爲,fpi ++會做什麼?另外,'c'應該是一個'int',你不檢查你的第二個'fopen'的結果。 – pzaenger

+0

一次一個問題。 –

+3

'foef' does [not work](http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong),正如你顯然期望的那樣。還要注意非ASCII字符編碼。這很可能無法按預期工作。至少你需要'char16_t'或'char32_t'來做到這一點。 – Olaf

回答

1

,你想(通過打開文件的過程中允許的最大數量的限制,但在大多數現代操作系統這個數字運行到數千)你可以有很多打開的文件指針。儘管如此,你應該記得關閉它們。

至於「遞增」文件指針,請記住,儘管類型被稱爲FILE *,這實際上並不指向內容的文件的,它指向的是<stdio.h>用來處理文件的內部管理體制。因此,像fpi ++這樣的東西不會更新內部文件位置指針(這是你想要做的);它只是使fpi指向一些其他FILE結構。雖然有合理的理由來做到這一點(例如指向FILE *數組的指針),但在文件內移動並不是這樣完成的。

如果您確實需要移動到文件中,那麼可以使用名爲fseek()的功能來執行此操作。然而,讀取或寫入(即調用fread()fwrite()fgets()fprintf()getc()(及其等價fgetc()),putc()(及其等價fputc()),你可以想像,任何其他功能上所代表的文件執行I/O FILE *值)已經更新內部文件指針,指向操作處理的數據之後。換句話說,當你讀或寫一個字符時,內部文件指針已經指向該字符之後。你不需要,也不應該嘗試自己更新它,因爲它已經爲你完成了。

由於編碼,字符比較可能會失敗 - 雖然表示通常的ASCII字符(代碼點32到126;基本字母,數字等)的標準方式非常標準,但國際字符沒有這個豪華。你需要找出文件使用什麼編碼,並手動處理該編碼;可能通過使用原始字符數字而不是字符符號。如果你想研究這些,還有廣泛的人物功能來幫助你。 編輯:我只注意到case標籤中的'C' || 'c'表示法。這只是計算爲1,因爲在編譯時解決了標籤中的任何常量表達式(並且根本不允許使用非常量表達式)。您需要多個case標籤來匹配多個值;你不能在那裏使用表達式。

最後,VS警告是虛假的,因爲fopen()是標準庫調用。儘管(在這種情況下爲<stdio.h>),請記住#include相應的文件。

+0

所以我可以比較Chars與它的ASCII碼?像:if(c == 66){} –

+1

你可以這樣做(事實上,在幾乎每個相關的平臺上,它與if(c =='B'){/ * something * /}')是一樣的,但請記住,您需要知道確切的編碼點。 ASCII上升到127;在那之後,它不是人的土地(因爲每個供應商都以不同的方式填充128-255空間),除非你知道你正在處理的文本的確切編碼。 (無論如何,請記住'char'是一個數字類型,因此任何在數字上有效的操作在'char'上都是有效的。) – aaaaaa123456789

2

實際上有許多不同的問題出現,你應該專注於一次一個,並張貼不同的問題,如果他們是不同的像你。

我會回答問題,關於switch語句。答案是如果你想在一個案例中使用多個值,你不能。但是,您可以依靠的事實,案件告吹下來,如果沒有break語句,然後你可以做如

switch (c) 
{ 
case 'ä': 
case 'Ä': 
    // Code for the ä or Ä case 
    break; 

... 
} 

你可以使用tolowertoupper

switch (tolower(c)) 
{ 
case 'ä': 
    // Code for the ä or Ä case 
    break; 

... 
} 

關於什麼是錯case 'ä'||'Ä'一點解釋。

會發生什麼情況是,編譯器看到'ä' || 'Ä'布爾表達,並用C一切非零被認爲是真正的。同樣在C布爾true被認爲等於1,這意味着您的案件中的表達式等於1 || 1這是真的,因此1,所以您的所有案件都是case 1

+1

從技術上講,''ä'|| 'Ä''將字符評估爲文件編碼中的任何代碼點(而不是1)...雖然最終結果是_is_ 1,因爲它是對兩個非零值進行布爾或運算。 – aaaaaa123456789

+0

這是我正在尋找的答案! –

+0

@ aaaaaa123456789啊,你是對的,我應該編輯我的答案是正確的。 :) –