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

如何读取具有特殊字符的文件?-C,c,unicode,special-characters,C,Unicode,Special Characters,我有一个countries.txt文档,其中列出了西班牙语国家的名称。这意味着例如有“')和“ñ”字符 我有一个小函数,用来计算文档中的行数,它最初是用fgets()函数制作的,我对它进行了编辑,使它使用fgetws(),因为我知道特殊字符应该存储在wchar\u t变量中 int linesCount = 0; wchar_t line[MAX_SIZE]; while(fgetws(line, sizeof(line), f) != NULL){ lin

我有一个countries.txt文档,其中列出了西班牙语国家的名称。这意味着例如有“')和“ñ”字符

我有一个小函数,用来计算文档中的行数,它最初是用
fgets()
函数制作的,我对它进行了编辑,使它使用
fgetws()
,因为我知道特殊字符应该存储在
wchar\u 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);
}
这是countries.txt的第一部分:

Aruba
Angola
Albania
Andorra
Argelia
Armenia
Austria
Alemania
Antártida
Argentina
程序在到达“Antártida”时崩溃,该“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)

保存在dis上的文件不使用“wchars”-它将以“编码”方式编码,通常是utf-8或拉丁语-1

您可能得到的是,“西班牙语”没有提供有关字符集编码的信息-因此,尽管调用`setlocale'时没有出现错误,但您可能正在尝试读取一个utf-8文件(具有多字节编码),该文件采用字符映射(每个字符一个字节)编码

如果您只需要计算行数,只需使用字符,您的程序就会按预期工作

因此,与其尝试猜测,不如现在就阅读以下内容:

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


然后,如果你有一个“现实世界”的任务,必须处理这么简单的国际文本文件,我强烈建议你离开C语言,使用更高级的语言。你仍然需要知道文件编码——但生活将变得简单(至少)一个数量级。

文件在dis上保存时,不要使用“wchars”-它将以“编码”进行编码,通常是utf-8或拉丁语-1

您可能得到的是,“西班牙语”没有提供有关字符集编码的信息-因此,尽管调用`setlocale'时没有出现错误,但您可能正在尝试读取一个utf-8文件(具有多字节编码),该文件采用字符映射(每个字符一个字节)编码

如果您只需要计算行数,只需使用字符,您的程序就会按预期工作

因此,与其尝试猜测,不如现在就阅读以下内容:

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


然后,如果你有一个“现实世界”的任务,必须处理这么简单的国际文本文件,我强烈建议你离开C语言,使用更高级的语言。你仍然需要知道文件编码——但生活将变得简单(至少)一个数量级。

好吧,
valgrind
输出不是很有帮助,除非你包括分配你正在使用的内存的代码部分?(如果这是您的全部代码,则它必须是有问题的无掩码系统分配。)请提供。文件
countries.txt
的字符编码是什么?
LC_CTYPE
环境变量的值是多少?您应该以二进制模式将文件读取为
char
,然后自己进行字符集转换,这样您就知道发生了什么。@DavidC.Rankin我用更多信息完成了这篇文章,我认为这会使valgrind输出更有用。我相信您的选择是
“es_es.UTF-8”
“es_es”
(适用于ISO-8859-1)或可能的
“es”_ES@euro“
(适用于ISO-8859-15)(尽管
“es”
部分可能因您的位置而异)那么,
valgrind
输出不是很有帮助,除非您包括分配您正在使用的内存的代码部分?(如果这是您的全部代码,那么它必须是有问题的无掩码系统分配。)请提供。文件
countries.txt
的字符编码是什么?
LC\u CTYPE
环境变量的值是什么?您应该以二进制模式将文件读取为
char
,然后自己进行字符集转换,这样您就知道发生了什么。@DavidC.Rankin我用更多信息完成了这篇文章我认为它使valgrind输出更有用我相信您的选择是
“es_es.UTF-8”
“es_es”
(对于ISO-8859-1)或可能的
“es”_ES@euro“
(适用于ISO-8859-15)(尽管
“es”
零件可能因位置而异)