Я знаю, что в C++ есть конвертер. Но чтобы знать, как работает память, мне нужно знать, почему я не могу этого сделать:
#include <iostream>
#include <cstring>
int main() {
const char* text = "hello";
std::wstring* wtext = malloc(5);
strcpy(wtext, text);
std::wcout << wtext << std::endl;
free(wtext);
return 0;
}
«текст» — это указатель «привет»
«wtext» — указатель памяти, содержащий 5 свободных байт
функция «strcpy» копирует память из указателя «text» в указатель «wtext»
"std::wcout" все это распечатывает
«free» очищает старую память от указателя «wtext» \
Если вся эта теория верна, то она должна работать, но это не так.
Почему я не могу изменить размер чего-либо и поместить это в это?
поэтому компилятор C++ говорит, что я не могу использовать «malloc» для «wtext», потому что у него разные типы переменных. Однако профессор говорит, что в указателях может быть что угодно, потому что это указатели. Они могут указывать на цифры, текст и т. д. Я не понял, что произошло.
Для начала прочтите раздел руководства по C++, в котором объясняется, когда и как использовать new
. Но почему вы думаете, что вам нужно динамически выделять хранилище? И почему это должен быть std::wstring
, который сам способен управлять динамической памятью?
Что касается вашей проблемы преобразования строки с узкими символами в строку с широкими символами, см. std::mbstowcs.
В общем, похоже, что вы использовали действительно плохой ресурс для изучения C++ и смешиваете несвязанные и неработающие концепции C. Если вы серьезно настроены изучать C++, купите несколько хороших книг. А если вы хотите использовать широкие символы и строки, используйте их с самого начала и по всему коду. Большинство попыток смешать, скорее всего, окажутся безрезультатными.
Прежде чем продолжить, сначала изучите немного больше стандартного C++. Для строк в C++ используйте std::string и std::wstring. И никогда не следует использовать std::string*
. Посетите сайты Learncpp.com, cppreference.com и основные рекомендации C++. Кто учит вас C++?
Здесь есть несколько проблем. Что касается комментария вашего профессора об указателях, считайте указатели категорией. Указатель на float и указатель на int оба являются указателями. Принцип и характеристики, стоящие за ними, одинаковы. Однако это разные типы указателей, и они не являются взаимозаменяемыми. Точно так же, как кошка и бык — млекопитающие, и у них есть общие характеристики, но вы не станете использовать кошку, чтобы тянуть плуг.
Как уже упоминалось, malloc
здесь не нужен. Во-вторых, даже если вы использовали malloc
, это: std::wstring* wtext = malloc(5);
недопустимо для C++. Функция malloc
возвращает void *
, и вы не можете присвоить void *
std::wstring *
. Вам необходимо привести возвращаемое значение malloc
к правильному типу указателя.
Примечание: wchar_t
, std::wstring
, std::wcout
бесполезны в Linux и macOS. Они действительно полезны в Windows, но теперь я рекомендую везде использовать UTF-8 std::string
, а для Windows добавьте в исполняемый файл файл манифеста, чтобы включить кодовую страницу UTF-8 (возможно с 2019 года).
#include <iostream>
#include <string> // Include <string> for std::wstring
int main() {
const char* text = "hello";
std::wstring wtext = std::wstring(text, text + strlen(text)); // Convert const char* to std::wstring
std::wcout << wtext << std::endl;
return 0;
}
Вероятно, это работает нормально, если text
содержит только ASCII, но если он содержит что-то в кодировке UTF8, этот метод не будет работать.
Согласованный. Вам нужно фактическое преобразование данных, например std::wstring_convert()
, std::mbstowcs()
или другой эквивалентный API Unicode.
это ненужно медленно, поскольку вы дважды проходите по строке: один раз для подсчета символов, а второй раз для их копирования.
Никогда не следует выделять объекты C++ с помощью malloc
(и не освобождать их с помощью free
).malloc
— это наследие C. Он только выделяет необработанную память и не вызывает соответствующий конструктор.
В C++ вы должны (в принципе) использовать new
для динамического выделения объекта и получения указателя на него (и delete
для освобождения).
На практике бывают редкие случаи, когда вам действительно необходимо использовать необработанные указатели с ручными new
/delete
. Обычно лучше использовать интеллектуальный указатель.
Но в случае wstring
вообще нет смысла использовать какой-либо указатель. Просто используйте объект напрямую.
Также, если вы создадите text
массив char
, вы можете использовать std::begin
и std::end
для инициализации wstring
:
#include <string>
#include <iostream>
int main()
{
const char text[] = "hello";
std::wstring wtext(std::begin(text), std::end(text));
std::wcout << wtext << std::endl;
}
Выход:
hello
Примечание:
Прочитав ваш вопрос и пример кода, я предположил, что ваша исходная строка содержит только символы ascii.
Если это не так, вы не можете просто инициализировать wtext
из text
, как показано выше. Вместо этого вам нужно будет использовать какой-нибудь API для его преобразования, например std::wstring_convert , std::mbstowcs и т. д. По этим ссылкам на документацию также показаны некоторые примеры использования.
Просто обратите внимание, что создание std::wstring
из std::string
путем копирования символов как есть, как это происходит в этом коде, приведет к повреждению символов, отличных от ASCII. Вам нужно фактическое преобразование данных, например std::wstring_convert()
, std::mbstowcs()
или другой эквивалентный API Unicode.
@RemyLebeau хорошая мысль. Читая вопрос и код, я подумал, что ОП нужна тривиальная операция, подобная копированию. Добавил примечание.
хотя это не сработает с const char*
Если вам не нужно конвертировать строку и просто создать wstring с такими же, но широкими символами, то это одна строка кода:
std::wstring destination{std::from_range, "string"};
а для задания также можно использовать destination.assign_range("string");
malloc(5)
выделит пять байтов, а не место для пяти «элементов» любого типа. На самом деле ее нельзя использовать так, как вы этого хотите, поскольку это старая функция C, которая не знает элементов (на любом языке) или объектов C++.