2009-09-02 5 views
-1

У меня есть следующая строка:StD :: струны

index          0 1 2 3 4 5 6 7 
std::string myString with the content of "\xff\xff\xff\x00\xff\x0d\x0a\xf5" 

Когда я ссылаюсь на MyString [3], я получаю ожидаемый '\ x00' значение.

Но когда я имею в виду myString [5], я получаю два значения «\ x0d \ x0a» вместо «\ x0d».

Еще более интересным является значение myString [6], которое является «\ xf5». На этот раз это похоже на то, что \ x0d не существует, и на правильную позицию ссылались.

Мой вопрос будет таким: что особенного о символе \ x0d в объекте std: string? Почему это происходит при индексировании? Это как подсчет так:

index      0 1 2 3 4 5 5 6 
std::string myString = "\xff\xff\xff\x00\xff\x0d\x0a\xf5" 

В качестве комментария, символ «\ x0D» символ 13 ASCII символов «возврат каретки» и «\ x0a» является символом строки.

UPDATE: Может быть, std :: string считает «\ x0d \ x0a» единственным символом и, таким образом, занимает только одну позицию в строке? Является ли этот «\ x0d» символом «mystery» в отношении std :: string?

ДОПОЛНИТЕЛЬНАЯ ИНФОРМАЦИЯ: http://en.wikipedia.org/wiki/Newline

+5

Может вы это показывает в небольшой, полной, компилируемый программы? Я не понимаю, как вы получаете два символа при доступе к индексу 5. В конце концов оператор '[]' возвращает только один символ. – sbi

+0

is \ x0a line feed? Они могут рассматриваться как один символ, чтобы «разрыв строки» удерживал одинаковое количество индексов (один) в системах с различными стилями разрыва строки, хотя я действительно не уверен относительно внутренних действий std :: string, поэтому я не буду публиковать это как ответ. –

+0

Я буду продолжать добавлять дополнительную информацию к этому вопросу. Действительно, ваша догадка может быть правильной: '\ x0a' - это фид строки, и кажется, что std :: string рассматривает их как один символ: '\ x0d \ x0a'. – citn

ответ

9

Вы уверены, что это происходит с std::string? std::string::operator[] возвращает const char &, так как он может возвращать два символа ('\x0d'и'\x0a')?

Это означает, что "\x0d\x0a" обычно используется для окончаний строк под Windows, тогда как в Linux используется только '\x0a', поэтому преобразование первого в последнее относительно относительно под Windows - например, я думаю о поведении fopen при вызове с "wt". Я бы предположил, что что-то подобное происходит с тобой.

Редактировать: Исходя из ваших комментариев по исходному вопросу, я думаю, что могу догадаться, что происходит.

Я считаю, что ваша строка действительно не содержит того, что, по вашему мнению, содержит. Вы вводите в заблуждение, потому что механизм, который вы используете для вывода строки в файл (возможно, ofstream?) Выполняет перевод в конце строки. Это означает, что '\n' (код конца строки Unix) переводится в '\r\n' (код конца строки Windows). Цель перевода на конец строки - сделать код более переносимым между операционными системами. Вы можете заблокировать его, открыв файл в двоичный режим; для ofstream это делается путем указания флага ios_base::binary при открытии файла, но этот флаг не установлен по умолчанию.

(Смотрите эту Wikipedia article для получения дополнительной информации о отслуживших линии маркеров на разных операционных системах.)

Это то, что я считаю, что происходит.Ваша строка фактически содержит

index     0 1 2 3 4 5 6 
myString contents "\xff\xff\xff\x00\xff\x0a\xf5" 

Вы выводя это что-то вроде этого:

ofstream file("myfile.txt"); 
for(size_t i=0; i<myString.size(); i++) 
    ofstream << myString[i]; 

Из-за конца-линии перевода expalined выше, '\x0a' в myString[5] выводится наружу как '\x0d\x0a' и вот что вас смущает.

+0

Действительно, я использую аналогичный механизм: std :: ostringstream. Кроме того, если вы можете добавить дополнительную информацию об этом переводе для дальнейшего использования, я был бы вам признателен. Например, кто на самом деле это делает, и, возможно, несколько ссылок в Интернете. – citn

+0

Я добавил ссылку на всеобъемлющую статью в Википедии.Что касается того, где фактически завершен перевод на конец строки, это, вероятно, зависит от стандартной реализации библиотеки, но это, вероятно, происходит в 'ofstream' /' ostringstream' и т. Д. Или одном из их базовых классов. –

0

Возможно, вы злоупотребляете оператором [].

Оператор [] возвращает символ const. Однако вы, вероятно, используете это как указатель и, таким образом, получаете два символа - нам нужно увидеть ваш фактический код, чтобы подтвердить это.

0x00 - это нуль-терминатор для c-строки, поэтому, вероятно, для этого вы получаете только один (правильный) символ.

Что происходит, когда вы получаете [4]?

0

В визуальной студии 2008, \ x00 считается концом строки. Так myString.lenght возвращает 3. Когда вы пытаетесь получить доступ к myString [5], вы получаете сообщение об ошибке.

9

Единственное, что происходит не так здесь следующая строка не делать то, что вы ожидаете:

std::string myString = "\xff\xff\xff\x00\xff\x0d\x0a\xf5"; 

Это вызывает std::string(const char *) конструктор, который предназначен для преобразования заканчивающегося нуля строки C-стиль к C++ std::string. Этот конструктор считывает байты, начинающиеся с заданного указателя, и копирует их в новый std::string, пока не достигнет нулевого байта (\ x00). Это согласуется с поведением C-функций, таких как strlen().

Итак, когда сконфигурирован ваш myString, он состоит из строки длины 3 с байтами \ xff, \ xff, \ xff. Доступ к индексам, превышающим 2, позволяет получить доступ к байтам с конца массива (что в лучшем случае приведет к ошибке выполнения, а в худшем - к неопределенному поведению).

Обратите внимание, что std::string может содержать промежуточные нулевые байты, но вы не можете использовать вышеупомянутый конструктор для инициализации такой строки, потому что нулевые байты интерпретируются как завершение строки в стиле С передается в конструктор.

Было бы стоит попробовать ваш код еще раз с \ x00 байт изменено на что-то другое, просто чтобы посмотреть, как это отличается от того, что вы уже описали:

std::string myString = "\xff\xff\xff\x01\xff\x0d\x0a\xf5" 

Кроме того, проверьте myString.length() после указанного конструктора чтобы увидеть, что вы получаете.

+0

O.K. Смысл: std :: string :: string (const char *) ctor, итерации по C-Strings до '\ 0'. Имеет смысл, почему я видел поведение на MSVC. Мой плохой ... – Abhay

+0

Хорошая точка. Я предположил, что cmdev просто хотел показать нам содержимое строки и не дал нам код, который фактически используется для инициализации строки ... но если это фактическая инициализация , вы пригвоздили проблему. –

+0

Это правильно. То, что я хотел показать, было только содержанием строки. Точное назначение намного сложнее, чем простое задание. Я добавлю комментарий. – citn

2

Вы создаете строку следующего конструктора: string(char const *)

Он получает завершенный нуль строки C. Таким образом, он находит свою длину в соответствии с первым символом 0.

Вы должны использовать другой конструктор, который определяет размер: string(char const *,size_t n) по телефону:

std::string myString("\xff\xff\xff\x00\xff\x0d\x0a\xf5",8); 

См http://www.cplusplus.com/reference/string/string/string/ для дальнейшего чтения