fwscanf 无法在 C 中正确读取 UTF-8 CSV 文件

问题描述 投票:0回答:2

该程序只能使用C标准的库。

我正在尝试使用

fwscanf
在 C 中读取 UTF-8 编码的 CSV 文件,但我在读取过程中遇到了问题。该文件包含带有字符串和以逗号分隔的浮点值的行。这是演示该问题的最小示例:

#include <stdio.h>
#include <wchar.h>
#include <locale.h>

#define MAX_STRING_LENGTH 31

int main() {
    setlocale(LC_ALL, "en_US.UTF-8");
    FILE *file = fopen("input.csv", "r, ccs=UTF-8");
    if (file == NULL) {
        fwprintf(stderr, L"Error opening file.\n");
        return 1;
    }

    wchar_t string[MAX_STRING_LENGTH];
    float frequency;
    int row = 0;

    while (!feof(file)) {
        row++;
        int result = fwscanf(file, L"%30[^,],%f,", string, &frequency);
        
        if (result == 2) {
            wprintf(L"Row %d: String = '%ls', Frequency = %.4f\n", row, string, frequency);
        } else if (result == 1) {
            wprintf(L"Row %d: String = '%ls', Frequency not read\n", row, string);
        } else if (result == EOF) {
            break;
        } else {
            wprintf(L"Error reading row %d\n", row);
            wchar_t c;
            // Skip the rest of the line
            while ((c = fgetwc(file)) != L'\n' && c != WEOF);
        }
    }

    fclose(file);
    return 0;
}

示例输入.csv:

hello,1.0000
world,0.5000
how,0.7500
are,0.2500
you,1.0000
?,0.5000

预期输出:

Row 1: String = 'hello', Frequency = 1.0000
Row 2: String = 'world', Frequency = 0.5000
Row 3: String = 'how', Frequency = 0.7500
Row 4: String = 'are', Frequency = 0.2500
Row 5: String = 'you', Frequency = 1.0000
Row 6: String = '?', Frequency = 0.5000

我面临的问题是 fwscanf 无法正确读取文件。它要么读取不正确的值,要么根本无法读取。我尝试过使用不同的区域设置和文件打开模式,但问题仍然存在。

c string file while-loop char
2个回答
0
投票

参数

string
L"%30[^,],%f,"
格式字符串不一致。
%[
需要一个指向
char
数组的指针,该数组将接收从流读取的宽字符到其多字节表示形式的转换。

您想要执行一项非常不同的任务:将 UTF-8 编码的输入流转换为宽字符串。 您应该使用

fscanf("%30l[^,],%f,", string, &frequency)
来代替。


0
投票

诸如

fwscanf()
之类的面向广泛的I/O函数不适合您的用例。 他们期望输入为一系列宽字符(其中实现有一定的自由度来定义其含义),但 UTF-8 输入不是这样。 实现可能会有所不同,但您的
fwscanf
调用可能会尝试读取文件,就好像它是用 UCS-2 编码的一样。

C 具有“多字节字符”的含义,与“宽字符”分开且不同。 前者由两个或多个

char
单元组成,它们最自然地存储在
char
数组中,可能散布有单字节字符。 后者由单个
wchar_t
组成,并且最自然地存储在
wchar_t
数组中,在这种情况下,它们不能散布单字节字符。

您的 UTF-8 输入最适合前者,并且面向字节的 I/O 函数最适合读取和写入它们。 (终端或其他显示设备负责“解释”代码序列,以便呈现相应的图形表示。)顺便说一句,C 从 C11 开始就有 UTF-8 文字,它们对应于 char 的数组.

所以,

你正在尝试做不必要的额外努力

。 使用窄 I/O 函数和常规字符串,而不是宽导向 I/O 函数和宽字符串。

此外,

    考虑不使用
  • fscanf

    (也不是

    fwscanf
    )这些看似很难正确使用。 可能的替代方案之一是使用
    fgets()
    一次读取一行,然后使用
    sscanf()
    解析每一行。
    
    

  • while(!feof(file))总是错的

© www.soinside.com 2019 - 2024. All rights reserved.