A ListIterator
позволяет добавлять или удалять элементы в списке. Предположим, у вас есть список объектов Car
:
List<Car> cars = ArrayList<>();
// add cars here...
for (ListIterator<Car> carIterator = cars.listIterator(); carIterator.hasNext(); )
{
if (<some-condition>)
{
carIterator().remove()
}
else if (<some-other-condition>)
{
carIterator().add(aNewCar);
}
}
Вот выработанное решение, основанное на других предложениях:
#include <string>
#include <iostream>
#include <clocale>
#include <locale>
#include <vector>
int main() {
std::setlocale(LC_ALL, "");
const std::wstring ws = L"ħëłlö";
const std::locale locale("");
typedef std::codecvt<wchar_t, char, std::mbstate_t> converter_type;
const converter_type& converter = std::use_facet<converter_type>(locale);
std::vector<char> to(ws.length() * converter.max_length());
std::mbstate_t state;
const wchar_t* from_next;
char* to_next;
const converter_type::result result = converter.out(state, ws.data(), ws.data() + ws.length(), from_next, &to[0], &to[0] + to.size(), to_next);
if (result == converter_type::ok or result == converter_type::noconv) {
const std::string s(&to[0], to_next);
std::cout <<"std::string = "<<s<<std::endl;
}
}
Это обычно работает для Linux, но создаст проблемы в Windows.
Как заметил Кубби в одном из комментариев, std::wstring_convert
(C ++ 11) обеспечивает простое простое решение (вам нужно #include
<locale>
и <codecvt>
):
wstring string_to_convert;
//setup converter
using convert_type = std::codecvt_utf8<wchar_t>;
std::wstring_convert<convert_type, wchar_t> converter;
//use converter (.to_bytes: wstr->str, .from_bytes: str->wstr)
std::string converted_str = converter.to_bytes( string_to_convert );
Я использовал комбинацию wcstombs
и утомительное выделение / освобождение памяти, прежде чем я натолкнулся на это.
http://en.cppreference.com/w/cpp/locale / wstring_convert
update (2013.11.28)
Один лайнер может быть указан так (спасибо Guss за ваш комментарий):
std::wstring str = std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes("some string");
Функции Wrapper могут быть указаны следующим образом: (Спасибо ArmanSchwarz за ваш комментарий)
wstring s2ws(const std::string& str)
{
using convert_typeX = std::codecvt_utf8<wchar_t>;
std::wstring_convert<convert_typeX, wchar_t> converterX;
return converterX.from_bytes(str);
}
string ws2s(const std::wstring& wstr)
{
using convert_typeX = std::codecvt_utf8<wchar_t>;
std::wstring_convert<convert_typeX, wchar_t> converterX;
return converterX.to_bytes(wstr);
}
Примечание: есть некоторые разногласия относительно того, следует ли передавать string
/ wstring
в функции как ссылки или как литералы (из-за обновлений C ++ 11 и компилятора). Я оставлю это решение для человека, но его стоит знать.
Примечание. Я использую std::codecvt_utf8
в приведенном выше коде, но если вы не используете UTF-8, вы будете необходимо изменить это на соответствующую кодировку, которую вы используете:
std::wstring str = std::wstring_convert<std::codecvt_utf<wchar_t>>().from_bytes("some string");
– Guss
11 November 2013 в 14:59
std::string ws2s(std::wstring const&)
, чтобы получить больше голосов.
– quant
13 November 2013 в 08:05
u8""
(но менее переносимым). Примечание: вам не нужно кодировать исходный код i>, чтобы быть utf-8, чтобы использовать u8""
- ответственность компилятора заключается в том, чтобы преобразовать из кодировки исходного кода в utf-8, т. Е. , кодировка, используемая для строк в исполняемом файле, может отличаться от кодировки исходного кода (u8"" = source_bytes.decode(source_code_encoding).encode('utf-8')
; "" = source_bytes.decode(source_code_encoding).encode(exec_charset)
).
– jfs
2 May 2017 в 11:42
Я считаю, что официальный путь по-прежнему должен идти в сторону codecvt
граней (вам нужен какой-то перевод, ориентированный на языковой стандарт), как в
resultCode = use_facet<codecvt<char, wchar_t, ConversionState> >(locale).
in(stateVar, scratchbuffer, scratchbufferEnd, from, to, toLimit, curPtr);
или что-то в этом роде, я не есть рабочий код, лежащий вокруг. Но я не уверен, сколько людей в эти дни используют эту технику, и сколько попросят указать указатели на память, и пусть ICU или другая библиотека обрабатывают детали gory.
В случае, если кому-то интересен: мне нужен класс, который мог бы использоваться взаимозаменяемо везде, где ожидались string
или wstring
. Следующий класс convertible_string
, основанный на решении dk123 , может быть инициализирован либо с помощью string
, char const*
, wstring
, либо wchar_t const*
и может быть назначен или неявно преобразован в либо string
или wstring
(поэтому их можно передать в функции, которые принимают либо).
class convertible_string
{
public:
// default ctor
convertible_string()
{}
/* conversion ctors */
convertible_string(std::string const& value) : value_(value)
{}
convertible_string(char const* val_array) : value_(val_array)
{}
convertible_string(std::wstring const& wvalue) : value_(ws2s(wvalue))
{}
convertible_string(wchar_t const* wval_array) : value_(ws2s(std::wstring(wval_array)))
{}
/* assignment operators */
convertible_string& operator=(std::string const& value)
{
value_ = value;
return *this;
}
convertible_string& operator=(std::wstring const& wvalue)
{
value_ = ws2s(wvalue);
return *this;
}
/* implicit conversion operators */
operator std::string() const { return value_; }
operator std::wstring() const { return s2ws(value_); }
private:
std::string value_;
};
#include <boost/locale.hpp>
namespace lcv = boost::locale::conv;
inline std::wstring fromUTF8(const std::string& s)
{ return lcv::utf_to_utf<wchar_t>(s); }
inline std::string toUTF8(const std::wstring& ws)
{ return lcv::utf_to_utf<char>(ws); }
В моем случае я должен использовать многобайтовый символ (MBCS), и я хочу использовать std :: string и std :: wstring. И не может использовать c ++ 11. Поэтому я использую mbstowcs и wcstombs.
Я делаю одну и ту же функцию с использованием new, delete [], но это медленнее, чем это.
Это может помочь Как сделать: Конвертировать Между различными строковыми типами
EDIT
Однако в случае преобразования в строку wstring и источника строка не имеет алфавита и многобайтовой строки, она не работает. Поэтому я изменяю wcstombs на WideCharToMultiByte.
#include <string>
std::wstring get_wstr_from_sz(const char* psz)
{
//I think it's enough to my case
wchar_t buf[0x400];
wchar_t *pbuf = buf;
size_t len = strlen(psz) + 1;
if (len >= sizeof(buf) / sizeof(wchar_t))
{
pbuf = L"error";
}
else
{
size_t converted;
mbstowcs_s(&converted, buf, psz, _TRUNCATE);
}
return std::wstring(pbuf);
}
std::string get_string_from_wsz(const wchar_t* pwsz)
{
char buf[0x400];
char *pbuf = buf;
size_t len = wcslen(pwsz)*2 + 1;
if (len >= sizeof(buf))
{
pbuf = "error";
}
else
{
size_t converted;
wcstombs_s(&converted, buf, pwsz, _TRUNCATE);
}
return std::string(pbuf);
}
EDIT использовать «MultiByteToWideChar» вместо «wcstombs»
#include <Windows.h>
#include <boost/shared_ptr.hpp>
#include "string_util.h"
std::wstring get_wstring_from_sz(const char* psz)
{
int res;
wchar_t buf[0x400];
wchar_t *pbuf = buf;
boost::shared_ptr<wchar_t[]> shared_pbuf;
res = MultiByteToWideChar(CP_ACP, 0, psz, -1, buf, sizeof(buf)/sizeof(wchar_t));
if (0 == res && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
res = MultiByteToWideChar(CP_ACP, 0, psz, -1, NULL, 0);
shared_pbuf = boost::shared_ptr<wchar_t[]>(new wchar_t[res]);
pbuf = shared_pbuf.get();
res = MultiByteToWideChar(CP_ACP, 0, psz, -1, pbuf, res);
}
else if (0 == res)
{
pbuf = L"error";
}
return std::wstring(pbuf);
}
std::string get_string_from_wcs(const wchar_t* pcs)
{
int res;
char buf[0x400];
char* pbuf = buf;
boost::shared_ptr<char[]> shared_pbuf;
res = WideCharToMultiByte(CP_ACP, 0, pcs, -1, buf, sizeof(buf), NULL, NULL);
if (0 == res && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
{
res = WideCharToMultiByte(CP_ACP, 0, pcs, -1, NULL, 0, NULL, NULL);
shared_pbuf = boost::shared_ptr<char[]>(new char[res]);
pbuf = shared_pbuf.get();
res = WideCharToMultiByte(CP_ACP, 0, pcs, -1, pbuf, res, NULL, NULL);
}
else if (0 == res)
{
pbuf = "error";
}
return std::string(pbuf);
}
wcstombs()
.
– Vizor
9 November 2017 в 11:01
Я использую ниже, чтобы преобразовать wstring в строку.
std::string strTo;
char *szTo = new char[someParam.length() + 1];
szTo[someParam.size()] = '\0';
WideCharToMultiByte(CP_ACP, 0, someParam.c_str(), -1, szTo, (int)someParam.length(), NULL, NULL);
strTo = szTo;
delete szTo;
<string>
), а определение для WideCharToMultiByte()
- это какая-то оболочка вокруг std::wctomb()
?
– Toby Speight
5 April 2018 в 13:39
Вы можете просто использовать узкий метод ctype facet:
#include <clocale> #include <locale> #include <string> #include <vector> inline std::string narrow(std::wstring const& text) { std::locale const loc(""); wchar_t const* from = text.c_str(); std::size_t const len = text.size(); std::vector<char> buffer(len + 1); std::use_facet<std::ctype<wchar_t> >(loc).narrow(from, from + len, '_', &buffer[0]); return std::string(&buffer[0], &buffer[len]); }
Решение от: http://forums.devshed.com/c-programming-42/wstring-to-string-444006.html
std::wstring wide( L"Wide" );
std::string str( wide.begin(), wide.end() );
// Will print no problemo!
std::cout << str << std::endl;
] Остерегайтесь того, что здесь есть no преобразование набора символов. Это просто означает, что каждый итерированный wchar_t
присваивает char
- усекающее преобразование. Он использует std :: string c'tor :
template< class InputIt >
basic_string( InputIt first, InputIt last,
const Allocator& alloc = Allocator() );
Как указано в комментариях:
значения 0-127 идентичны в практически каждая кодировка, поэтому усекающие значения, которые все меньше 127, дают один и тот же текст.
-
значения 128-255 кодовой страницы Windows 1252 (по умолчанию Windows English) и значения 128-255 юникода в основном одинаковы, поэтому, если это кодовая страница, в которой вы используете большинство этих символов, должна быть усечена до правильных значений. (Я полностью ожидал, что и работаю, я знаю, что наш код на работе опирается на это для é, который я скоро исправлю)
И обратите внимание, что коды указывают в диапазоне
0x80 - 0x9F
в Win1252 будет работать не . Это включает в себя€
,œ
,ž
,Ÿ
, ...
// Embarcadero C++ Builder
// convertion string to wstring
string str1 = "hello";
String str2 = str1; // typedef UnicodeString String; -> str2 contains now u"hello";
// convertion wstring to string
String str2 = u"hello";
string str1 = UTF8string(str2).c_str(); // -> str1 contains now "hello"
Вместо того, чтобы включать язык и все эти причудливые вещи, если вы знаете FACT, ваша строка является конвертируемой, просто выполните это:
#include <iostream>
#include <string>
using namespace std;
int main()
{
wstring w(L"bla");
string result;
for(char x : w)
result += x;
cout << result << '\n';
}
Пример в реальном времени здесь
Это решение является вдохновенным решением dk123, но использует языковой зависимый кодекс decec. Результат - в строках, закодированных в локали вместо utf8 (если он не задан как locale):
std::string w2s(const std::wstring &var)
{
static std::locale loc("");
auto &facet = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(loc);
return std::wstring_convert<std::remove_reference<decltype(facet)>::type, wchar_t>(&facet).to_bytes(var);
}
std::wstring s2w(const std::string &var)
{
static std::locale loc("");
auto &facet = std::use_facet<std::codecvt<wchar_t, char, std::mbstate_t>>(loc);
return std::wstring_convert<std::remove_reference<decltype(facet)>::type, wchar_t>(&facet).from_bytes(var);
}
Я искал его, но я не могу его найти. Наконец, я обнаружил, что я могу получить правильный грань из std :: locale, используя функцию std :: use_facet () с правильным именем. Надеюсь, это поможет.
std::setlocale(LC_ALL, "");
? – smerlin 26 January 2011 в 15:44std::wcout.imbue(locale)
должно также выполнять эту работу, и оно имеет то преимущество, что оно не изменяет никакого глобального состояния. – smerlin 26 January 2011 в 16:22std::wstring_convert
из C ++ 11 покрывает много этого шума. – Cubbi 27 September 2011 в 20:34*** glibc detected *** test: malloc(): smallbin double linked list corrupted: 0x000000000180ea30 ***
на 64-разрядном Linux (gcc 4.7.3). Кто-нибудь еще испытывает это? – hogliux 10 November 2013 в 14:22