簡體   English   中英

從文件中讀取日文字符的問題 - C.

[英]Issue reading Japanese characters from file - C

我正在編寫一個程序,它讀取一個有近200萬行的文件。 該文件的格式為整數ID選項卡,其中包含藝術家姓名字符串。

6821361 Selinsgrove High School Chorus
10151460    greek-Antique
10236365    jnr walker & the all-stars
6878792 Grieg - Kraggerud, Kjekshus
6880556 Mr. Oiseau
6906305 stars on 54 (maxi single)
10584525    Jonie Mitchel
10299729    エリス レジーナ/アントニオ カルロス ジョビン

上面是一個示例,其中包含文件中的一些項目(不是某些行不遵循特定格式)。 我的程序工作文件,直到它從示例到達最后一行然后它無休止地打印エリス レジーナ/アントニオ カルロス ジョビ\\343\\203

struct artist *read_artists(char *fname)
{
    FILE *file;
    struct artist *temp = (struct artist*)malloc(sizeof(struct artist));
    struct artist *head = (struct artist*)malloc(sizeof(struct artist));
    file = fopen("/Users/Daniel/Library/Developer/Xcode/DerivedData/project_Audioscrobbler_Artists-hgwyqpinuoxayzbmvarcjxryqnrz/Build/Products/Debug/artist_data.txt", "r");
    if(file == 0)
    {
        perror("fopen");
        exit(1);
    }
    int artist_ID;
    char artist_name[650];
    while(!feof(file))
    {
        fscanf(file, "%d\t%65[^\t\n]\n", &artist_ID, artist_name);
        temp = create_play(artist_ID, artist_name, 0, -1);
        head = add_play(head, temp);
        printf("%s\n", artist_name);
    }
    fclose(file);
    //print_plays(head);
    return head;
}

以上是我從文件中讀取的代碼。 你能幫忙解釋一下是什么問題嗎?

正如評論所指出的,一個問題是while(!feof(file))鏈接內容將詳細解釋為什么這不是一個好主意,但總的來說,引用鏈接中的一個答案:

(!FEOF(文件))...

...是錯誤的,因為它測試了一些無關緊要的東西,並且無法測試你需要知道的東西。 結果是您錯誤地執行了代碼,該代碼假定它正在訪問已成功讀取的數據,而事實上這種情況從未發生過。 - Kerrek SB

在您的情況下,這種用法不會導致您的問題,但正如Kerrek解釋可能發生的那樣, 掩蓋它。

您可以用fgets(...)替換它:

char lineBuf[1000];//make length longer or shorter for your purpose
file = fopen("/Users/Daniel/Library/Developer/Xcode/DerivedData/project_Audioscrobbler_Artists-hgwyqpinuoxayzbmvarcjxryqnrz/Build/Products/Debug/artist_data.txt", "r");
if(!file) return -1;
while(fgets (lineBuf, sizeof(lineBuf), file))
{
    //process each line here
    //But processing Japanese characters
    //will require special considerations.
    //Refer to the link below for UNICODE tips
}

C和C ++中的Unicode ...

特別是,您需要使用足以包含要處理的不同大小字符的變量類型。 該鏈接非常詳細地討論了這一點。

這是一段摘錄:

 "char" no longer means character I hereby recommend referring to character codes in C programs using a 32-bit unsigned integer type. Many platforms provide a 

“wchar_t”(寬字符)類型,但不幸的是要避免它,因為一些編譯器只分配16位 - 不足以表示Unicode。 無論您需要傳遞單個字符,請將“char”更改為“unsigned int”或類似字符。 “char”類型唯一剩下的用法是指“byte”。

編輯:
在上面的注釋中,您說明了它失敗的字符串是66個字節長 因為您正在讀取'char'數組,所以在包含最后一個必要字節之前,完成字符所需的字節被截斷一個字節。 ASCII字符可以包含在單個char空間中。 日文字符不能。 如果您使用的是unsigned int數組而不是char數組,則會包含最后一個字節。

OP的代碼失敗,因為沒有檢查fscanf()的結果。

fscanf(file, "%d\t%65[^\t\n]\n", &artist_ID, artist_name);

fscanf()讀取了"エリス レジーナ/アントニオ カルロス ジョビン" 65個char 然而,這個以UTF8編碼的字符串長度為66.最后一個'ン'是代碼227,131,179(八進制343 203 263),只有最后兩個被讀取。 打印artist_name ,將顯示以下內容。

エリス レジーナ/アントニオ カルロス ジョビ\343\203

現在開始問題了。 最后一個char 179保留在file 在下一個 fscanf() ,它失敗,因為char 179沒有轉換為int"%d" )。 所以fscanf()返回0.由於代碼沒有檢查fscanf()的結果,它沒有意識到artist_IDartist_name從之前遺留下來,因此打印相同的文本。

作為feof()是從不為真char 179沒有被消耗,我們有無限循環。

while(!feof(file))隱藏了這個問題,但沒有引起它。

@ryyker提出的fgets()是一種很好的方法。 另一個是:

while (fscanf(file, "%d\t%65[^\t\n]\n", &artist_ID, artist_name) == 2) {
    temp = create_play(artist_ID, artist_name, 0, -1);
    head = add_play(head, temp);
    printf("%s\n", artist_name);
    }

IOWs,驗證*scanf()的結果。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM