gpt4 book ai didi

c - fgetws 无法在 Linux 上读取非英文字符

转载 作者:行者123 更新时间:2023-11-30 20:05:26 26 4
gpt4 key购买 nike

我有一个基本的 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"); )但没有成功。

最佳答案

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

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

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

与上述无关,如果文件包含超过 2000 行,您的代码也会溢出缓冲区。您的循环需要检查这一点。

代码中的许多函数可能会失败,并且会返回一个值来指示这一点。您的代码不会检查任何此类失败。

你的代码在 OS X 下运行是偶然的。该行为是未定义的,这意味着使用任何编译器构建时,在任何主机系统上都有可能失败。看起来在一个系统上运行正确,但在另一个系统上运行失败,实际上是对未定义行为的一组有效响应。

关于c - fgetws 无法在 Linux 上读取非英文字符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31137471/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com