【问题标题】:How can I print non English characters taken from a text file in c++?如何打印从 C++ 文本文件中提取的非英文字符?
【发布时间】:2018-04-13 14:58:30
【问题描述】:

我正在尝试编写一个简单的 c++ 程序。


目标:打开一个现有的文本文件,获取姓名和姓氏并将它们保存到姓名和姓氏字符串中。打印姓名和姓氏并跳到下一行。重复直到文件结束。

我有两个问题

我正在使用最新更新的 Windows 8.1 和 Visual Studio 2017。

主要代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include "stdafx.h"
#include <iostream>
using namespace std;


int main() {
FILE *fPtr;



if ((fPtr = fopen("newStudentsList.txt", "r")) == NULL) {
    cout << "File could not be opened.\n";
    system("pause");
}


else {
    char *name = new char[100];
    char *surname = new char[100];

    rewind(fPtr);

    while (!feof(fPtr)) {

        fscanf(fPtr, "%s\t%s\n", name, surname);
        cout << name << " " << surname << endl;
    }

    system("pause");
}
return 0;
}

在输出中,我无法正确看到土耳其语字符。这是我的第一个问题。


我的第二个问题是我不能正确地取名字和姓氏,因为在文本文件中它们不是用相同的制表符或空格写的,有些人有一个名字,有些人有两个名字。


所有文件都是here


如何打印非英文字符?


如何正确取名和姓氏?

【问题讨论】:

  • 请一次只问一个问题,另见stackoverflow.com/help/how-to-ask
  • 为什么不用fstream来处理文件,而是用c风格的FILE,这样会更有效率
  • @J.Snipe 这无关紧要。每个问题你应该只问 1 个问题。
  • @J.Snipe 混合 C 和 C++ 功能是一个非常糟糕的主意。您应该使用streams 打开/写入文件,如in this C++ tutorial 所示。无论编码如何,您都可以使用ifstream 读取非Unicode 文件。您可以使用wifstream 读取UTF16 文件。 UTF8 文件被视为
  • @J.Snipe 然后使用ifstream 从中读取 std::string 和 char 数据。 C++ 仍然没有 UTF8 字符串的特殊类型。 UTF8 文件应该像 ASCII 文件一样被读取和处理。

标签: c++ visual-studio file utf-8


【解决方案1】:

首先,不要在 C++ 程序中使用 C 函数。 C++ 有不同的特性、不同的抽象和不同的库。使用 C 构造会阻止您使用它们。

C++ 使用streams 通过网络等方式读取/写入文件、内存和字符串缓冲区。它有大量算法需要流和/或迭代器作为输入。

它还具有处理单字节 (std::string)、多字节 (std::wstring)、UTF16 (std::u16string) 和 UTF32 (std::u32string) 库的内置字符串类型.您可以在代码中指定这样的string literals。它甚至还有一种带有 auto 关键字的类型推断形式。

C++ 仍然没有有 UTF8 的类型。程序员应将 UTF8 字符串和文件视为单字节数据,并使用charstd::string 来存储它们。这些值应根据需要转换为其他代码页或 Unicode 类型。

这意味着您无需执行任何其他操作即可将 UTF8 文件的内容显示到控制台。代码取自Input/Output with files教程:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main () {
  string line;
  ifstream myfile ("newStudentsList.txt");
  if (myfile.is_open())
  {
    while ( getline (myfile,line) )
    {
      cout << line << '\n';
    }
    myfile.close();
  }

  else cout << "Unable to open file"; 

  return 0;
}

默认情况下,控制台使用系统区域设置的代码页。您可以通过键入将其更改为 UTF8 代码页:

chcp 65001

在运行您的应用程序之前。 UTF8 字符串应该正确显示假设控制台字体包含正确的字符

更新

可以指定 UTF8 literals 但存储还是char,例如:

const char* str1 = u8"Hello World";  
const char* str2 = u8"\U0001F607 is O:-)";  
const char*     s3 = u8"? = \U0001F607 is O:-)"; 

auto str1 = u8"Hello World";  
auto str2 = u8"\U0001F607 is O:-)";  

【讨论】:

  • 感谢您的正确回答。我只是无法得到最后一部分。我应该在哪里输入 chcp 65001 ?
  • 在控制台窗口中,在您运行程序之前。这允许 控制台 为您的文本使用正确的代码页。
【解决方案2】:

每当我需要在控制台程序中输出非 ASCII 字符时,我只需将控制台模式设置为支持 UNICODE:

_setmode(_fileno(stdout), _O_U16TEXT);

完成此操作后,宽字符识别代码将“按预期”工作,即此代码:

std::wcout << L"\x046C" << std::endl;
wprintf(L"\x046C\n");

会及时输出一个古老的西里尔字母“big yus”:Ѭ

记得包含这些文件:

#include <io.h>
#include <fcntl.h>

这里有一个简短的测试程序供你玩:

#include <conio.h>
#include <iostream>
#include <io.h>
#include <fcntl.h>
void main(){
    _setmode(_fileno(stdout), _O_U16TEXT);
    std::wcout << L"\x046C" << std::endl;
    wprintf(L"\x046C\n");
}

【讨论】:

  • OP 正在读取 UTF8 字符,而不是 UTF16。 wcoutwprintf 等用于双字节字符和 UTF16。在 C++11 及更高版本中,UTF16 的正确类型是 char16_t、u16string
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多