如何读取带有特殊字符的文件? - C

时间:2020-04-21 04:18:47

标签: c unicode special-characters

我有一个country.txt文件,其中以西班牙语列出了国家/地区的名称。这意味着例如有“”和“”字符。

我有一个小函数,用于计算文档中的行数,该函数最初是由fgets()函数制成的,由于我了解特殊字符,因此我对其进行了编辑,使其使用fgetws()应该存储在wchar_t变量中。

  int linesCount = 0;
    wchar_t line[MAX_SIZE];

    while(fgetws(line, sizeof(line), f) != NULL){
        linesCount++;
    }
    rewind(f);

    return linesCount;
}

1)如果函数找到包含“´”的字符串,程序将崩溃。 2)如果没有找到任何特殊字符,则valgrind会发现更多的内存泄漏,而不是如果至少有一个特殊字符(如“ñ”)则为1。

这是主要内容:

int main (void)
{
 setlocale(LC_ALL, "spanish");
 countries = fopen("countries.txt", "r");
 int counCount = count_lines(countries);
 fclose(countries);
}

这是country.txt的第一部分:

Aruba
Angola
Albania
Andorra
Argelia
Armenia
Austria
Alemania
Antártida
Argentina

程序到达带有“á”字母的“Antártida”时崩溃。

我附上了valgrind显示的错误:

1 errors in context 1 of 1:
==16211== Conditional jump or move depends on uninitialised value(s)
==16211==    at 0x4FCB443: __wmemchr_avx2 (memchr-avx2.S:97)
==16211==    by 0x4EBE164: _IO_getwline_info (iogetwline.c:86)
==16211==    by 0x4EBDD2C: fgetws (iofgetws.c:53)
==16211==    by 0x108BC3: count_lines (people_generator.c:10)
==16211==    by 0x108B3C: main (main.c:15)
==16211==  Uninitialised value was created by a heap allocation
==16211==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==16211==    by 0x4EBB858: _IO_wfile_doallocate (wfiledoalloc.c:79)
==16211==    by 0x4ECA378: _IO_doallocbuf (genops.c:365)
==16211==    by 0x4EC172B: _IO_wfile_underflow (wfileops.c:179)
==16211==    by 0x4EBF691: _IO_wdefault_uflow (wgenops.c:204)
==16211==    by 0x4EBE1C0: _IO_getwline_info (iogetwline.c:61)
==16211==    by 0x4EBDD2C: fgetws (iofgetws.c:53)
==16211==    by 0x108BC3: count_lines (people_generator.c:10)
==16211==    by 0x108B3C: main (main.c:15)

1 个答案:

答案 0 :(得分:0)

文件始终保留在dis上,请勿使用“ wchars”-它将以“编码”(通常是utf-8或latin-1)进行编码。

您可能会得到的是,“西班牙语”没有提供有关字符集编码的信息-因此,尽管在调用`setlocale时没有出现错误,但是您很可能试图读取utf-8文件(一种多字节编码),以及一个charmap(每个字符一个字节)编码。

如果仅需计数行,则只需使用char,程序便会按预期运行。

因此,与其尝试猜测,不如立即阅读以下内容:https://www.joelonsoftware.com/2003/10/08/the-absolute-minimum-every-software-developer-absolutely-positively-must-know-about-unicode-and-character-sets-no-excuses/

之后,您应该可以使用其他工具来确定文件编码,然后在set-locale调用中设置正确的编码。 “ es_ES.UTF-8”或“ es_ES.ISO8859-1”之一应该起作用。

然后,如果您有一个“现实世界”的任务,必须如此简单地处理国际文本文件,那么我强烈建议您远离C语言并使用高级语言。您仍然必须知道文件编码-但寿命(至少)要容易一个数量级。

相关问题