C ++:std :: string问题

时间:2010-08-14 15:21:15

标签: c++ string encoding

我有这个简单的代码:

#include <iostream>
#include <fstream>

using namespace std;

int main(void)
{
    ifstream in("file.txt");
    string line;
    while (getline(in, line))
    {
        cout << line << "    starts with char: " << line.at(0) << " " << (int) line.at(0) << endl;
    }
    in.close();
    return 0;
}

打印:

  0.000000 0.000000 0.010909 0.200000    starts with char:   32
A 0.023636 0.000000 0.014545 0.200000    starts with char: A 65
B 0.050909 0.000000 0.014545 0.200000    starts with char: B 66
C 0.078182 0.000000 0.014545 0.200000    starts with char: C 67

...

, 0.152727 0.400000 0.003636 0.200000    starts with char: , 44
< 0.169091 0.400000 0.005455 0.200000    starts with char: < 60
. 0.187273 0.400000 0.003636 0.200000    starts with char: . 46
> 0.203636 0.400000 0.005455 0.200000    starts with char: > 62
/ 0.221818 0.400000 0.010909 0.200000    starts with char: / 47
? 0.245455 0.400000 0.009091 0.200000    starts with char: ? 63
¡ 0.267273 0.400000 0.005455 0.200000    starts with char: � -62
£ 0.285455 0.400000 0.012727 0.200000    starts with char: � -62
¥ 0.310909 0.400000 0.012727 0.200000    starts with char: � -62
§ 0.336364 0.400000 0.009091 0.200000    starts with char: � -62
© 0.358182 0.400000 0.016364 0.200000    starts with char: � -62
® 0.387273 0.400000 0.018182 0.200000    starts with char: � -62
¿ 0.418182 0.400000 0.009091 0.200000    starts with char: � -62
À 0.440000 0.400000 0.012727 0.200000    starts with char: � -61
Á 0.465455 0.400000 0.014545 0.200000    starts with char: � -61

奇怪......我怎样才能真正得到string的第一个角色?

提前致谢!

4 个答案:

答案 0 :(得分:8)

您正在获取字符串中的第一个字符。

但看起来字符串是UTF-8字符串(或者可能是其他多字节字符格式)。

这意味着os打印的每个符号(字形)由1个(或更多字符)组成 如果是UTF-8,则ASCII(0-127)范围之外的任何字符实际上由2个(或更多字符)组成,字符串打印代码正确地解释了这一点。但字符打印代码无法正确解码大于127的单个字符。

我个人认为动态宽度字符格式在程序内部使用并不是一个好主意(它们可以用于传输和存储),因为它们使字符串操作更加复杂。我建议您将字符串转换为固定宽度格式以进行内部处理,然后将其转换回UTF-8进行存储。

我个人会在内部使用UTF-16(或UTF-32,具体取决于wchar_t)(是的,我从技术上知道UTF-16不是固定宽度,但在所有合理的教学情况下,它是固定宽度(当我们包括沙子时) -script然后我们可能需要使用UTF-32))。您只需要使用适当的codecvt方面为输入/输出流注入自动转换。在内部,代码可以被操作,因为单个字符使用wchar_t类型。

答案 1 :(得分:1)

该文件采用UTF-8编码。使用诸如ICU之类的Unicode库来访问代码点:

#include <iostream>
#include <fstream>
#include <utility>

#include "unicode/utf.h"

using namespace std;

const pair<UChar32, int32_t>
getFirstUTF8CodePoint(const string& str) {
  const uint8_t* ptr = reinterpret_cast<const uint8_t*>(str.data());
  const int32_t length = str.length();
  int32_t offset = 0;
  UChar32 cp = 0;
  U8_NEXT(ptr, offset, length, cp);
  return make_pair(cp, offset);
}

int main(void)
{
    ifstream in("file.txt");
    string line;
    while (getline(in, line))
    {
      pair<UChar32, string::size_type> cp = getFirstUTF8CodePoint(line);
      cout << line << "    starts with char: " << line.substr(0, cp.second) << " " << static_cast<unsigned long>(cp.first) << endl;
    }
    in.close();
    return 0;
}

答案 2 :(得分:0)

我认为最后的字符属于扩展的ASCII表,C ++不支持

ASCII Table

编辑1:从快速查看看,底部的字符似乎也不在扩展ASCII中。也许看看马丁约克所说的话。

答案 3 :(得分:0)

string是char的容器,只有一个字节。它应该只用于Ascii字符串或二进制数据。 在这种情况下,任何不应该使用Unicode,使用wstring,wchar_t的容器。

但是你的Unicode文本编码的问题仍然存在,为此,请参阅上面的答案。