fgetws无法读取Linux上的非英文字符

时间:2015-06-30 11:49:53

标签: c linux

我有一个基本的C程序,它从包含工作目录中数百行的文本文件中读取一些行。这是代码:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <string.h>
#include <locale.h>
#include <wchar.h>
#include <wctype.h>
#include <unistd.h>

int main(int argc, const char * argv[]) {
    srand((unsigned)time(0));
    char *nameFileName = "MaleNames.txt";
    wchar_t line[100];
    wchar_t **nameLines = malloc(sizeof(wchar_t*) * 2000);
    int numNameLines = 0;
    FILE *nameFile = fopen(nameFileName, "r");
    while (fgetws(line, 100, nameFile) != NULL) {
        nameLines[numNameLines] = malloc(sizeof(wchar_t) * 100);
        wcsncpy(nameLines[numNameLines], line, 100);
        numNameLines++;
    }
    fclose(nameFile);

    wchar_t *name = nameLines[rand() % numNameLines];
    name[wcslen(name) - 1] = '\0';
    wprintf(L"%ls", name);

    int i;
    for (i = 0; i < numNameLines; i++) {
        free(nameLines[i]);
    }
    free(nameLines);
    return 0;
}

它基本上是逐行读取我的文本文件(定义为宏,它存在于工作目录中)。休息是无关紧要的。它在我的Mac上运行完美和正常(使用llvm / Xcode)。当我尝试编译(没有什么花哨,再次,gcc main.c)并在Linux服务器上运行它时,它:

  • 存在错误代码2(意味着没有读取行)。
  • 只读取我文件中的前3行,数行。

导致这种不确定(和不正确)行为的原因是什么?我已尝试评论第一行(随机种子)并再次编译,总是退出并返回代码为2。

随机方法和阅读文件之间的关系是什么,以及我为什么会出现这种行为?

更新:我已mallocsizeof(wchar_t) * 100修复sizeof(wchar_t) * 50。它没有改变任何东西。我的行最多约15个字符,并且有少于2000行(保证)。

更新2:

  • 我已使用-Wall编译,没有问题。
  • 我已使用-Werror编译,没有问题。
  • 我跑valgrind也没发现任何泄漏。
  • 我已使用gdb调试,它只是没有进入while循环(fgetws调用返回0)。

更新3:我在Linux上遇到浮点异常,因为numNameLines为零。

更新4 :我验证我对MaleNames.txt具有读取权限。

更新5:我发现重音的非英文字符(例如Â)在阅读线条时会出现问题。 fgetws停止了他们。我尝试过设置区域设置(分别为setlocale(LC_ALL, "en.UTF-8");setlocale(LC_ALL, "tr.UTF-8");),但没有成功。

2 个答案:

答案 0 :(得分:3)

fgetws()正在尝试读取多达100个宽字符。循环中的malloc()调用分配50个宽字符。

wcscpy()调用会复制读取的所有宽字符。如果已读取超过50个宽字符(包括终止nul),则wcscpy()将超出分配的缓冲区。这导致了不确定的行为。

而不是在循环中乘以50,乘以100.或者,更好的是,计算字符串读取的长度并使用它。

除上述内容外,如果文件包含超过2000行,您的代码也会溢出缓冲区。你的循环需要检查它。

代码中的许多函数都可能失败,并会返回一个值来表示。您的代码没有检查任何此类故障。

在OS X下运行的代码是偶然的。行为未定义,这意味着当使用任何编译器构建时,任何主机系统都可能出现故障。似乎在一个系统上正确运行,而在另一个系统上失败,实际上是对未定义行为的有效响应集。

答案 1 :(得分:0)

找到解决方案。从一开始就是关于语言环境的。经过实验和数小时的研究,我偶然发现了这一点:http://cboard.cprogramming.com/c-programming/142780-arrays-accented-characters.html#post1066035

  

#include&lt; locale.h&gt;

     

setlocale(LC_ALL,&#34;&#34;);

将语言环境设置为空字符串可以立即解决我的问题。