我有一个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)
答案 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语言并使用高级语言。您仍然必须知道文件编码-但寿命(至少)要容易一个数量级。