Как преобразовать строку в wstring?

Я знаю, что в 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», потому что у него разные типы переменных. Однако профессор говорит, что в указателях может быть что угодно, потому что это указатели. Они могут указывать на цифры, текст и т. д. Я не понял, что произошло.

malloc(5) выделит пять байтов, а не место для пяти «элементов» любого типа. На самом деле ее нельзя использовать так, как вы этого хотите, поскольку это старая функция C, которая не знает элементов (на любом языке) или объектов C++.
Some programmer dude 30.06.2024 17:46

Для начала прочтите раздел руководства по C++, в котором объясняется, когда и как использовать new. Но почему вы думаете, что вам нужно динамически выделять хранилище? И почему это должен быть std::wstring, который сам способен управлять динамической памятью?

Ulrich Eckhardt 30.06.2024 17:47

Что касается вашей проблемы преобразования строки с узкими символами в строку с широкими символами, см. std::mbstowcs.

Some programmer dude 30.06.2024 17:48

В общем, похоже, что вы использовали действительно плохой ресурс для изучения C++ и смешиваете несвязанные и неработающие концепции C. Если вы серьезно настроены изучать C++, купите несколько хороших книг. А если вы хотите использовать широкие символы и строки, используйте их с самого начала и по всему коду. Большинство попыток смешать, скорее всего, окажутся безрезультатными.

Some programmer dude 30.06.2024 17:50

Прежде чем продолжить, сначала изучите немного больше стандартного C++. Для строк в C++ используйте std::string и std::wstring. И никогда не следует использовать std::string*. Посетите сайты Learncpp.com, cppreference.com и основные рекомендации C++. Кто учит вас C++?

Pepijn Kramer 30.06.2024 18:20

Здесь есть несколько проблем. Что касается комментария вашего профессора об указателях, считайте указатели категорией. Указатель на float и указатель на int оба являются указателями. Принцип и характеристики, стоящие за ними, одинаковы. Однако это разные типы указателей, и они не являются взаимозаменяемыми. Точно так же, как кошка и бык — млекопитающие, и у них есть общие характеристики, но вы не станете использовать кошку, чтобы тянуть плуг.

Avi Berger 30.06.2024 18:51

Как уже упоминалось, malloc здесь не нужен. Во-вторых, даже если вы использовали malloc, это: std::wstring* wtext = malloc(5); недопустимо для C++. Функция malloc возвращает void *, и вы не можете присвоить void *std::wstring *. Вам необходимо привести возвращаемое значение malloc к правильному типу указателя.

PaulMcKenzie 30.06.2024 19:08

Примечание: wchar_t, std::wstring, std::wcout бесполезны в Linux и macOS. Они действительно полезны в Windows, но теперь я рекомендую везде использовать UTF-8 std::string, а для Windows добавьте в исполняемый файл файл манифеста, чтобы включить кодовую страницу UTF-8 (возможно с 2019 года).

prapin 30.06.2024 20:40
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
8
144
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

#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, этот метод не будет работать.

Ted Lyngmo 30.06.2024 18:40

Согласованный. Вам нужно фактическое преобразование данных, например std::wstring_convert(), std::mbstowcs() или другой эквивалентный API Unicode.

Remy Lebeau 30.06.2024 18:58

это ненужно медленно, поскольку вы дважды проходите по строке: один раз для подсчета символов, а второй раз для их копирования.

Gene 30.06.2024 21:08
Ответ принят как подходящий

Никогда не следует выделять объекты 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.

Remy Lebeau 30.06.2024 18:56

@RemyLebeau хорошая мысль. Читая вопрос и код, я подумал, что ОП нужна тривиальная операция, подобная копированию. Добавил примечание.

wohlstad 30.06.2024 19:01

хотя это не сработает с const char*

Gene 30.06.2024 21:10

Если вам не нужно конвертировать строку и просто создать wstring с такими же, но широкими символами, то это одна строка кода:

std::wstring destination{std::from_range, "string"};

а для задания также можно использовать destination.assign_range("string");

Другие вопросы по теме