C ++: std :: string проблема - PullRequest
1 голос
/ 14 августа 2010

У меня есть этот простой код:

#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 ]

8 голосов
/ 14 августа 2010

Вы получаете первый символ в строке.

Но похоже, что строка является строкой UTF-8 (или, возможно, некоторым другим многобайтовым символьным форматом).

Это означает, что каждый символ (глиф), который напечатан os, состоит из 1 (или более символов).
Если это UTF-8, то любой символ, находящийся за пределами диапазона ASCII (0-127), фактически состоит из 2 (или более символов), и код печати строки правильно его интерпретирует. Но для кода печати символов невозможно правильно дешифровать один символ, который больше 127.

Лично я считаю, что форматы символов с динамической шириной не очень хорошая идея для внутреннего использования в программе (они подходят для транспортировки и хранения), поскольку они значительно усложняют манипуляции со строками. Я бы порекомендовал вам преобразовать строку в формат с фиксированной шириной для внутренней обработки, а затем преобразовать ее обратно в UTF-8 для хранения.

Лично я бы использовал UTF-16 (или UTF-32 в зависимости от того, что такое wchar_t) (да, я знаю, что технически UTF-16 не является фиксированной шириной, но при всех разумных обстоятельствах обучения это фиксированная ширина (когда мы включаем песок) -скрипт тогда нам может понадобиться использовать UTF-32)). Вам просто нужно наполнить поток ввода / вывода соответствующим фасетом codecvt для автоматического перевода. Внутренним кодом можно манипулировать, поскольку отдельные символы используют тип wchar_t.

1 голос
/ 14 августа 2010

Файл имеет кодировку UTF-8. Используйте библиотеку Unicode, такую ​​как ICU , чтобы получить доступ к кодовым точкам:

#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;
}
0 голосов
/ 14 августа 2010

строка - это контейнер для символа, который составляет всего один байт. Он должен использоваться только для строк Ascii или двоичных данных. Все, что не в этом случае, должно использовать Unicode, используя wstring, контейнер для wchar_t.

Но проблема того, как кодируется ваш текст в Юникоде, все еще существует, для этого см. Ответы выше.

0 голосов
/ 14 августа 2010

Я думаю, что последние символы принадлежат расширенной таблице ASCII, что C ++ не поддерживает

ASCII Таблица

Edit1: Нет, при быстром взгляде символы внизу также не отображаются в Extended ASCII. может быть, проверить, что сказал Мартин Йорк.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...