C语言 fgetws无法在Linux上读取非英语字符

mum43rcc  于 2023-02-15  发布在  Linux
关注(0)|答案(3)|浏览(152)

我有一个基本的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) * 50修改为sizeof(wchar_t) * 100,没有任何变化,我的行最多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");),但不起作用。
hzbexzde

hzbexzde1#

fgetws()正在尝试读取最多100个宽字符。循环中的malloc()调用分配50个宽字符。
wcscpy()调用复制所有读取的宽字符。如果读取的宽字符超过50个(包括终止的nul),则wcscpy()将溢出分配的缓冲区。这将导致未定义的行为。
不要在循环中乘以50,而是乘以100。或者,更好的是,计算string read的长度并使用它。
独立于上述内容,如果文件包含超过2000行,代码也会溢出缓冲区。您的循环需要对此进行检查。
代码中的许多函数可能会失败,并将返回一个值来指示失败。代码不会检查任何此类失败。
你的代码在OS X下运行是偶然的。行为是未定义的,这意味着当用任何编译器构建时,在任何主机系统上都有可能失败。在一个系统上看起来运行正确,而在另一个系统上失败,实际上是对未定义行为的一组有效响应。

6l7fqoea

6l7fqoea2#

找到了解决办法。从一开始,一切都与地点有关。经过试验和几个小时的研究,我偶然发现了这个:www.example.comhttp://cboard.cprogramming.com/c-programming/142780-arrays-accented-characters.html#post1066035

包括< locale.h >

设置区域设置(LC_ALL,"");
将locale设置为空字符串立即解决了我的问题。

7xllpg7q

7xllpg7q3#

设置区域设置(LC_ALL,“”);也解决了我的问题

相关问题