LINUX.ORG.RU

Неправильная длина строки std::string в C++

 


3

1
#include <iostream>
#include <string>

using namespace std;

string getStringInEnglish()
{
	return "Masha was walking on the highway.";
}

string getStringInRussian()
{
	return "Шла Маша по шоссе.";
}

int main()
{
	//В строке всего 18 символов, а показывет 32
	cout << getStringInRussian().length() << endl;

	//Показывает правильно
	cout << getStringInEnglish().length() << endl;
	
	return 0;
}
★★

Последнее исправление: Razip (всего исправлений: 1)
Ответ на: комментарий от mashina

По факту оканчивается. c_str это &str[0] Куча кода завязано на это поведение, если еще не стандартизировали, то это довольно странно.

Reset ★★★★★
()
Ответ на: комментарий от Reset

По факту оканчивается

И по факту не оканчивается. std::string это operator[](size_t), at(size_t) + итераторы. c_str() прослойка совместимости для сишных строк и ноль есть только там.

mashina ★★★★★
()
Ответ на: комментарий от mashina

Во всех работает именно так как я говорю. &str[0] == c_str(). Напиши программу из двух строк и проверь. Тебе не кажется, что странно в памяти держать две строки одна из которых с нулем на конце исключительно для совместимости с Си ?

Reset ★★★★★
()
Ответ на: комментарий от Reset

Тогда давай реализацию где это не так.

gcc 2.95.3

const _CharT* rope<_CharT,_Alloc>::c_str() const {
    if (0 == _M_tree_ptr) {
        _S_empty_c_str[0] = _S_eos((_CharT*)0);  // Possibly redundant,
                                             // but probably fast.
        return _S_empty_c_str;
    }
    __GC_CONST _CharT* __old_c_string = _M_tree_ptr->_M_c_string;
    if (0 != __old_c_string) return(__old_c_string);
    size_t __s = size();
    _CharT* __result = _Data_allocate(__s + 1);
    _S_flatten(_M_tree_ptr, __result);
    __result[__s] = _S_eos((_CharT*)0);
#   ifdef __GC
        _M_tree_ptr->_M_c_string = __result;
#   else
      if ((__old_c_string =
             _S_atomic_swap(&(_M_tree_ptr->_M_c_string), __result)) != 0) {
        // It must have been added in the interim.  Hence it had to have been
        // separately allocated.  Deallocate the old copy, since we just
        // replaced it.
        destroy(__old_c_string, __old_c_string + __s + 1);
        _Data_deallocate(__old_c_string, __s + 1);
      }
#   endif
    return(__result);
}

i-rinat ★★★★★
()
Ответ на: комментарий от peregrine

для работы с юникодом использовать что-то более подходящее, например, Glib::ustring для GTK или QString для Qt.

Зародилась у меня мысль задерайвить basic_string<> со своим типом данных. С переопределением всех нужных операторов. Чисто поспотыкаться на граблях, понять, так сказать, процесс.

KennyMinigun ★★★★★
()
Ответ на: комментарий от intelfx

Т. е. std::wstring::length() тоже может отличаться от количества символов?..

Да всё просто, посмотри на конструкторы basic_string, метод assign.

При создании можно указать размер больше, чем надо:

const char src[] = "Hello, World!\0 Rise And shine!"; // strlen() == 13
string s(src, sizeof(src));                           // .length() == 31

http://ideone.com/UcPi3t

KennyMinigun ★★★★★
()
Ответ на: комментарий от Reset

string хранит всё что угодно, в том числе и нули в середине, но всегда оканчивается нулем.

Найн: http://en.cppreference.com/w/cpp/string/basic_string/data

(until C++11)
The returned array is not required to be null-terminated. If empty() returns true, the pointer is a non-null pointer that should not be dereferenced.

(since C++11)
The returned array is null-terminated, that is, data() and c_str() perform the same function. If empty() returns true, the pointer points to a single null character.

KennyMinigun ★★★★★
()

Если писать продукт серьезный и особенно планируется кроссплатформенность, просто не использовать юникодные символы в исходниках никогда. Хранить в ресурсных файлах, gettext как то абстрагироваться, чтобы была прослойка. Узнать количество символов конечно бывает нужно порой, тут надо смотреть по задаче, известна ли котировка и тд. Если просто выводить то устройство само позаботится ну или в зависимости от устройства

LeoK
()
Ответ на: комментарий от comp00

Использовать регулярки для оперирования подстроками это мощно.

какие минусы? Давай сравним что-ли. Только с условием, что строка в UTF-8.

emulek
()
Ответ на: комментарий от mix_mix

С++ к 2015 году из коробки так и не умеет в юникод (с полноценной поддержкой в STL).

И что именно должно быть в STL?

DarkEld3r ★★★★★
()
Ответ на: комментарий от mix_mix

что такое длина строки в случае юникода, если учесть, что ф͎̤̻͓̽̍̇̐ͩ̅͒о̀̃̋̐р̧̳͉̦̀͊м̬̞͙̯̾̎ͯ̑͒͌а̞̲̊л͉̱̎̅͂͛ь͙̥̦ͯ̿̈ͦ̅ͬн̝̟͎̺͎̥ͪо͖̲̟̦͒̋̔е͚̺̺̭͇̃̀̓̓̊̀͛ ̙̭̯͂̿̒̽ͨͩ̚к̇ͧͪͦͨͧ̚о̗͈̥͇͇̎ͩ̒̑ͪ̉л̢̲̈́̑̆̉ͧ͗и̇̏̌͋ͥ̇҉̘͕̞͚̲̲͕ч͕̻͖̦͍͑ͬ̂̓͂̉ͅе̙̘̦̍ͨ̽̍͑͐͠с̨̆ͤ̎̆̿т͊̌ͨͣ̒̈́͏͍в͎̭͉͍̥̘̈́̑ͨ̓о̎̐̽ͥ̿̚ ̵̤̥͚͖̹ю̫̙͈͉ͯ͂̒н̡̲̳̖̘͖̻и̺̖͕̤̼̮̬ͭ͆ͦк̎͒ͤ҉͉͓̹̞̞о̪̞̕д̠̝̯̰͕͎ͩ̋ͣ̚о͍̪͈͍͍͈̬̕в̗̫̝̔ы̵͍͔̣х͔̪̓ ͓͖͔͕̝͓̍̈̏ͫͤ͠с̳̠͍͎ͯӥ̬̅м̤̻̙̳̭̠̉͌̀̄̇͆̕в̸̻͖̤̰̯̱͐ͩ̎ͬͩо̨̩̿ͩ͌ͥͤͤͦл̠͎͊̈̓ͪ̀͡о̧̝̙̆ͥв̗̬͎͔̭̩̪ͦ̏͌̔̌͂ͩ ̦͚͔͉̩͌ͫ͛ͭ̔ͯ̔ͅв҉ ̮̯͎ͨ̚о͙ͪͫ̇б͖̯̭̩̮̬͐ͪ̃͆̋щ̳̺̭̝͓̪̓е̬̤͔̠͍̻̉ͧ̊ͧͧͫ̍͢м̤͓̮̖͈̯͂ ̪̤̬͔̘̭ͧ̒ͨ̂ͮ̊ͧс̪̱̭̥ͦ̂̃͂͊̄̉л̰͉̤͂ͮ̾͂̀у̤͎̻̾ч̷̒а̣̝̩͟е̰̭̏̀ ͎̮͈̗̳н̢̘͎̥̘̱̉̔̓иͧ͆ͤ̐ͮ̂̾͏̼͓̳͖к̭̀а͈к̞͕̬͚͉̞̾͊ ̥̟͙̦̹̥ͯͤ̈̎̋̚н̟̘̜ͣͭ͐̽е̍ͩ̊̑͒͏̩͉̖͚̯̜ ̝̥̠̯̘͖с͙̯о̬͈͇̐̊̈ͤͧо̸̖̘̺̖̟̳̂̃ͬ̍͊͆͌т̮̰̱͇̥н͍̬̗̠ͦ̆̈о̲͉̯͓̯̀ͅс̢͉̜̰͔̓и̠͙̦̫̒̿͒ͣ̈́т̛̩̳͍͖̹̑сͨ̔̌̓͒҉̻я ̗̺̭͈̩̩̌̍̆̊͑͠с̳̭̯͓̰̬̌̐̆̂̔̒ ̮͕̀ͮͭ̚в͓͞и̴̃̍̈ͯз̥͊ͩу̼̲͉̙̌̄̂ͦͤ̈́͆ӓ̧̠͚̝͕̫́̂ͪ̈̈ͣл̸̫̥̬̼͈̖̦̏̐ͦ̚ь̖͋͆̈͐̚͜н̔ͯ͒̇̍͊̏о̆̎͏̪й͇͕̱̥͉̑̒ ͚̱͇̥̪̟ͫ̂͊ͦ͡д͔̠͖̐͒ͦ̒л̡͕̃и̶̝̝͙̪̝̯̏ͫͅн̞̱̮̍о͆͏̖̳̤̦͓й̣̞͚͈̱̙͓͑̈́ ̫ͧ́͆̐с̵т͍̼̜̺͞р̡̭͕̱̺͉͕ͭ̀̋ͤ̄̚ӧ̵̞̥̣̫̣̀ͥͬ͒̈́̍к̞̘̟̣̙̝͖ͦ̉̽̍͆̔͊͡и͚̍̐?̴͔͓̼̹̭̜̟

next_time ★★★★★
()
Ответ на: комментарий от Eddy_Em

«хрюникод» прекрасно и безопасно работает в консольном вводе - выводе и конкатенации. если же в программе используется какая-то другая работа со строками, то очевидно, это обработчик текста и без юникода там уже не обойтись.

next_time ★★★★★
()
Ответ на: комментарий от next_time

Какую ты чушь говоришь! У меня CGI'шки отлично в КОИ8 работают. И поиск по БД (sqlite в той же КОИ8) превосходно пашет!

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

это не обработчики текста. и там кроме ввода-вывода ничего не нужно => прекрасно будет работать и с юникодом.

next_time ★★★★★
()
Ответ на: комментарий от next_time

не обработчики текста

Угу, парсинг POST/GET — не обработка текста?

прекрасно будет работать и с юникодом

Зачем? Я не знаю китайского → китайской версии CGI писать не буду → хрюникод не понадобится!

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Угу, парсинг POST/GET — не обработка текста?

а что там вам нужно парсить?

next_time ★★★★★
()
Ответ на: комментарий от next_time

не умеет regex не работает нормально юникодом, там куча багов, по крайней мере, в реализации gcc

я НЕ про std::regex, а про man 3 regex (это glibc). Там всё нормально с юникодом, попробуй sed например.

Вот символы начиная с №5, 27штук:

$ echo "ф͎̤̻̽̍̇̐ͩ̅͒о̀̃̋̐р̧̳͉̦̀͊м̬̞͙̯̾̎ͯ̑͒͌а̞̲̊л͉̱̎̅͂͛ь͙̥̦ͯ̿̈ͦ̅ͬн̝̟͎̺͎̥ͪо͖̲̟̦͒̋̔е͚̺̺̃̀̓̓̊̀͛ ̙̭̯͂̿̒̽ͨͩ̚к̇ͧͪͦͨͧ̚о̗͈̥͇̎ͩ̒̑ͪ̉л̢̲̈́̑̆̉ͧ͗и̇̏̌͋ͥ̇҉̘͕̞ч͕̻͖̦͑ͬ̂̓͂̉е̙̘̦̍ͨ̽̍͑͐͠с̨̆ͤ̎̆̿т͊̌ͨͣ̒̈́͏͍в͎̭͉͍̥̘̈́̑ͨ̓о̎̐̽ͥ̿̚ ̵̤̥͚͖̹ю̫̙͈͉ͯ͂̒н̡̲̳̖̘͖̻и̺̖͕̤̼̮̬ͭ͆ͦк̎͒ͤ҉͉͓̹̞̞о̪̞̕д̠̝̯̰͕͎ͩ̋ͣ̚о͍̪͈͍͍͈̬̕в̗̫̝̔ы̵͍͔̣х͔̪̓ ͓͖͔͕̍̈̏ͫͤ͠с̳̠͍͎ͯӥ̬̅м̤̻̙̉͌̀̄̇͆̕в̸̻͖̤̰͐ͩ̎ͬͩо̨̩̿ͩ͌ͥͤͤͦл̠͎͊̈̓ͪ̀͡о̧̝̙̆ͥв̗̬͎ͦ̏͌̔̌͂ͩ ̦͚͌ͫ͛ͭ̔ͯ̔ͅв҉ ̮̯͎ͨ̚о͙ͪͫ̇б͖̯̭̩̮͐ͪ̃͆̋щ̳̺̭̝͓̪̓е̬̤̉ͧ̊ͧͧͫ̍͢м̤͓̮̖͈̯͂ ̪̤̬ͧ̒ͨ̂ͮ̊ͧс̪̱̭ͦ̂̃͂͊̄̉л̰͉̤͂ͮ̾͂̀у̤͎̻̾ч̷̒а̣̝̩͟е̰̭̏̀ ͎̮͈̗̳н̢̘͎̥̘̱̉̔̓иͧ͆ͤ̐ͮ̂̾͏̼͓к̭̀а͈к̞͕̬͚͉̞̾͊ ̥̟͙̦ͯͤ̈̎̋̚н̟̘̜ͣͭ͐̽е̍ͩ̊̑͒͏̩͉̖͚ ̝̥̠̯̘͖с͙̯о̬͈͇̐̊̈ͤͧо̸̖̘̂̃ͬ̍͊͆͌т̮̰̱͇̥н͍̬̗̠ͦ̆̈о̲͉̯͓̯̀ͅс̢͉̜̰͔̓и̠͙̦̫̒̿͒ͣ̈́т̛̩̳͍͖̹̑сͨ̔̌̓͒҉̻я ̗̺̭͈̌̍̆̊͑͠с̳̭̯͓̌̐̆̂̔̒ ̮͕̀ͮͭ̚в͓͞и̴̃̍̈ͯз̥͊ͩу̼̲͉̌̄̂ͦͤ̈́͆ӓ̧̠͚̝́̂ͪ̈̈ͣл̸̫̥̬̼͈̏̐ͦ̚ь̖͋͆̈͐̚͜н̔ͯ͒̇̍͊̏о̆̎͏̪й͇͕̱̥͉̑̒ ͚̱͇̥̪ͫ̂͊ͦ͡д͔̠͖̐͒ͦ̒л̡͕̃и̶̝̝͙̪̝̯̏ͫͅн̞̱̮̍о͆͏̖̳̤̦͓й̣̞͚͈̱̙͓͑̈́ ̫ͧ́͆̐с̵т͍̼̜̺͞р̡̭͕̱ͭ̀̋ͤ̄̚ӧ̵̞̥̀ͥͬ͒̈́̍к̞̘ͦ̉̽̍͆̔͊͡и͚̍̐?̴͔͓̼̹̭̜̟" |\
sed -r 's/.{5}(.{27}).*/\1/'
о̀̃̋̐р̧̳͉̦̀͊м̬̾̎ͯ̑͒͌

Да, gnu sed юзает glibc regex. В C/C++ юзай regcomp(3), regexec(3) и т.п.

А как длину узнать — без понятия, мне оно не нужно. Обычно нужно что-то вроде «поменять Маша или Машка на Света, или Светка соответственно». Такого рода замены в русском дьявольски сложны (например «Муж Маши» → «Муж Светы», окончание другое уже, потому-что «жи-ши пиши с „и“»), и без регекспов можно и не лезть, да и с регекспами не очень. Впрочем, например числительные сделать можно(что-бы «3 яблокА» и «1 яблокО»).

emulek
()
Ответ на: комментарий от emulek

кстати вот возможности регулярок:

$ echo "ф͎̤̻̽̍̇̐ͩ̅͒о̀̃̋̐р̧̳͉̦̀͊м̬̞͙̯̾̎ͯ̑͒͌а̞̲̊л͉̱̎̅͂͛ь͙̥̦ͯ̿̈ͦ̅ͬн̝̟͎̺͎̥ͪо͖̲̟̦͒̋̔е͚̺̺̃̀̓̓̊̀͛ ̙̭̯͂̿̒̽ͨͩ̚к̇ͧͪͦͨͧ̚о̗͈̥͇̎ͩ̒̑ͪ̉л̢̲̈́̑̆̉ͧ͗и̇̏̌͋ͥ̇҉̘͕̞ч͕̻͖̦͑ͬ̂̓͂̉е̙̘̦̍ͨ̽̍͑͐͠с̨̆ͤ̎̆̿т͊̌ͨͣ̒̈́͏͍в͎̭͉͍̥̘̈́̑ͨ̓о̎̐̽ͥ̿̚ ̵̤̥͚͖̹ю̫̙͈͉ͯ͂̒н̡̲̳̖̘͖̻и̺̖͕̤̼̮̬ͭ͆ͦк̎͒ͤ҉͉͓̹̞̞о̪̞̕д̠̝̯̰͕͎ͩ̋ͣ̚о͍̪͈͍͍͈̬̕в̗̫̝̔ы̵͍͔̣х͔̪̓ ͓͖͔͕̍̈̏ͫͤ͠с̳̠͍͎ͯӥ̬̅м̤̻̙̉͌̀̄̇͆̕в̸̻͖̤̰͐ͩ̎ͬͩо̨̩̿ͩ͌ͥͤͤͦл̠͎͊̈̓ͪ̀͡о̧̝̙̆ͥв̗̬͎ͦ̏͌̔̌͂ͩ ̦͚͌ͫ͛ͭ̔ͯ̔ͅв҉ ̮̯͎ͨ̚о͙ͪͫ̇б͖̯̭̩̮͐ͪ̃͆̋щ̳̺̭̝͓̪̓е̬̤̉ͧ̊ͧͧͫ̍͢м̤͓̮̖͈̯͂ ̪̤̬ͧ̒ͨ̂ͮ̊ͧс̪̱̭ͦ̂̃͂͊̄̉л̰͉̤͂ͮ̾͂̀у̤͎̻̾ч̷̒а̣̝̩͟е̰̭̏̀ ͎̮͈̗̳н̢̘͎̥̘̱̉̔̓иͧ͆ͤ̐ͮ̂̾͏̼͓к̭̀а͈к̞͕̬͚͉̞̾͊ ̥̟͙̦ͯͤ̈̎̋̚н̟̘̜ͣͭ͐̽е̍ͩ̊̑͒͏̩͉̖͚ ̝̥̠̯̘͖с͙̯о̬͈͇̐̊̈ͤͧо̸̖̘̂̃ͬ̍͊͆͌т̮̰̱͇̥н͍̬̗̠ͦ̆̈о̲͉̯͓̯̀ͅс̢͉̜̰͔̓и̠͙̦̫̒̿͒ͣ̈́т̛̩̳͍͖̹̑сͨ̔̌̓͒҉̻я ̗̺̭͈̌̍̆̊͑͠с̳̭̯͓̌̐̆̂̔̒ ̮͕̀ͮͭ̚в͓͞и̴̃̍̈ͯз̥͊ͩу̼̲͉̌̄̂ͦͤ̈́͆ӓ̧̠͚̝́̂ͪ̈̈ͣл̸̫̥̬̼͈̏̐ͦ̚ь̖͋͆̈͐̚͜н̔ͯ͒̇̍͊̏о̆̎͏̪й͇͕̱̥͉̑̒ ͚̱͇̥̪ͫ̂͊ͦ͡д͔̠͖̐͒ͦ̒л̡͕̃и̶̝̝͙̪̝̯̏ͫͅн̞̱̮̍о͆͏̖̳̤̦͓й̣̞͚͈̱̙͓͑̈́ ̫ͧ́͆̐с̵т͍̼̜̺͞р̡̭͕̱ͭ̀̋ͤ̄̚ӧ̵̞̥̀ͥͬ͒̈́̍к̞̘ͦ̉̽̍͆̔͊͡и͚̍̐?̴͔͓̼̹̭̜̟" | sed -r 's/\W//g'
формальноеколичͅествоюникодовыхсимволовͅвобщемслучаеникакнесоотноͅситсясвизуальнойдлиͅнойстроки
emulek
()
Ответ на: комментарий от Eddy_Em

Зачем? Я не знаю китайского → китайской версии CGI писать не буду → хрюникод не понадобится!

русского ты тоже не знаешь?

emulek
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.