Главная страница
Навигация по странице:

  • Оператор Описание

  • Борис Пахомов Санкт Петербург бхв петербург 2013 удк 004. 4 Ббк 32. 973. 26018. 2 П


    Скачать 17.38 Mb.
    НазваниеБорис Пахомов Санкт Петербург бхв петербург 2013 удк 004. 4 Ббк 32. 973. 26018. 2 П
    АнкорMS Visual C.pdf
    Дата04.08.2018
    Размер17.38 Mb.
    Формат файлаpdf
    Имя файлаMS Visual C.pdf
    ТипДокументы
    #22453
    страница36 из 37
    1   ...   29   30   31   32   33   34   35   36   37
    String в ASCII
    -
    строку
    Текст программы показан в листинге 14.1, а результат — на рис. 14.1. Рис 14.1. Результат перевода na tive- строки в managed
    - строку
    Глава
    14. Преобразование между нерегулируемыми и
    регулируемыми указателями Листинг 14.1

    // 14.1_2011 Нерег в Рег.cpp : main project file.
    #include "stdafx.h"
    #include using namespace System; using namespace System::Runtime::InteropServices;
    #pragma unmanaged сигнал компилятору, что далее следуют функции, работающие с обычными (native) переменными, которые станут размещаться в неуправляемой куче памяти, за переполнением которой надо следить самому — вовремя освобождать от занимающих ее объектов
    */ void NativeTakesAString(const char* p)
    { printf("(native) received '%s'\n", p);
    }
    #pragma managed сигнал компилятору, что далее следуют функции, работающие со средой
    CLR, в которой переменные станут размещаться в управляемой куче (памяти, за переполнением которой не надо следить самому — среда CLR сама позаботится об ее освобождении от занимаемых объектов
    */ int main() //array ^args
    {
    String^ s = gcnew String("sample string");
    IntPtr ip = Marshal::StringToHGlobalAnsi(s); этот метод выделяет для s место в неуправляемой куче и указатель на это место передает в структуру IntPtr. Указатель имеет тип void, те. его еще надо настроить на конкретный тип данного const char* str = static_cast(ip.ToPointer());
    /*кастинг указателя настройка его на тип с c помощью оператора static_cast (expression). Теперь указатель str типа char будет настроен в неуправляемой куче на начало переменной s. Так как s – константа, то у указателя str взят квалификатор const, говорящий о том, что значение, на которое указывает указатель, изменять нельзя
    */
    Console::WriteLine("(managed) passing string..."); т. к. мы находимся в методе main(), то и вывод идет по WriteLine())*/
    NativeTakesAString( str ); вызов метода внутри метода

    474 Часть II. Приложения Windows Form
    Marshal::FreeHGlobal( ip );
    этот метод освобождает память, выделенную StringToHGlobalAnsi(s): т. к. это уже неуправляемая куча, то память надо освобождать самому */
    Console::ReadLine();
    } Пример 2. Перевод строки в строку String Текст программы показан в листинге 14.2, а результат — на рис. 14.2. Рис 14.2. Результат преобразования managed
    - строки в native
    - строку
    Листинг 14.2
    // 14.2_2011 Прим 2.cpp : main project file.
    #include "stdafx.h"
    #include
    #include using namespace System; using namespace System::Runtime::InteropServices;
    #pragma managed void ManagedStringFunc(char* s) здесь функция получает аргумент
    {
    String^ ms = Marshal::PtrToStringAnsi(static_cast(s)); метод PtrToStringAnsi() копирует строку s в пространство, преобразуя каждый символ ASCII в Юникод, и выдает указатель на месторасположение новой строки в переменную s, которая преобразуется в тип
    IntPtr. Затем этот тип преобразуется оператором static_cast в тип String ^ */
    Console::WriteLine("(managed): received '{0}'", ms);
    }
    #pragma unmanaged
    Глава
    14. Преобразование между нерегулируемыми и
    регулируемыми указателями
    void NativeProvidesAString() это функция, которая вызывает
    функцию
    { printf("(native) calling managed func...\n");
    ManagedStringFunc("test string");
    }
    #pragma managed int это функция, которая вызывает функцию
    {
    NativeProvidesAString();
    _getch();
    } Пример 3. Преобразование строки

    String в строку Тип wchar_t
    — это тип символа по таблице Юникода. Этот тип данного отличается от типа char тем, что символ кодируется двумя байтами, а не одним. Класс
    String тоже создает строку из Юникод-символов, однако по своему определению относится к типу. Преобразование, которое мы рассматриваем, фактически переводит Юникод-строку из состояния managed в состояние native
    . А в этом состоянии со строкой уже можно работать, применяя обычный указатель
    *
    Юникод-тексты можно вводить в файлы и читать из них соответственно функциями и Текст программы показан в листинге 14.3, а результат — на рис. 14.3. Рис 14.3. Результат преобразования
    Юникод
    - строки в native
    - строку
    Листинг 14.3
    // 14.3_2011 Прим 3.cpp : main project file.
    #include "stdafx.h"
    #include для printf()
    #include для _getch()
    #include для PtrToStringChars()

    476 Часть II. Приложения Windows Form
    using namespace System; using namespace System::Runtime::InteropServices;
    #pragma unmanaged void NativeTakesAString(const wchar_t* p)
    { printf("(native) recieved '%S'\n", p);
    }
    #pragma managed int main()
    {
    String^ s = gcnew String("test string"); pin_ptr str = PtrToStringChars(s);
    /* метод размещает s в управляемой куче и выдает указатель типа _const_Char_ptr на размещенный объект. Этот указатель с помощью оператора
    [cli::]pin_ptr var = &initializer; преобразуется в тип const wchar_t.
    Здесь cv_qualifier — квалификатор const или квалификатор volatile.
    Квалификатор volatile показывает, что поле может модифицироваться многочисленными средами, выполняющимися в данный момент, и все изменения данного поля будут присутствовать в этом поле.
    Указатель типа pin_ptr по умолчанию имеет квалификатор volatile, поэтому в операторе применен квалификатор const, чтобы объект в куче не изменял своего значения, а не только месторасположения это ссылочный тип данного элемент массива или любого другого объекта, которому вы назначаете указатель.
    Метод PtrToStringChars() как рази выдает такой указатель указатель в управляемой (managed) куче. type — тип initializer'a. В нашем случае это wchar_t var — имя pin_ptr указателя. В нашем случае это str.
    То есть str — это уже указатель строки String ^ в управляемой куче.
    */
    Console::WriteLine("(managed) passing string to native func...");
    вывод сообщения из функции
    NativeTakesAString( str );
    вызов функции, которая выдаст сообщение
    _getch();
    }
    Глава
    14. Преобразование между нерегулируемыми и
    регулируемыми указателями Здесь применен указатель pin_ptr
    (указатель от зашкаливания, как определяет его автор. Это внутренний указатель, который предотвращает объект (на который он указывает) от какого-либо перемещения в управляемой куче (памяти, с которой работает режим CLR): значение указателя не изменяется средой CLR. Такое условие необходимо при передаче адреса объекта функции, потому что этот адрес не должен меняться вовремя вызова функции. Пример 4. Преобразование строки в строку

    String Это преобразование — обратное приведенному в примере 3. Преобразование, которое мы рассматриваем, фактически переводит native
    Юникод-строку в состояние managed
    . А в этом состоянии со строкой уже можно работать, применяя managed- указатель
    ^
    . Текст программы показан в листинге 14.4, а результат — на рис. 14.4. Рис 14.4. Результат преобразования wchar_t в
    String Листинг 14.4

    // 14.4_2011 Прим 4.cpp : main project file.
    // 2008-Marshal wchar_t to Unicod.cpp : main project file.
    #include "stdafx.h"
    #include
    #include using namespace System; using namespace System::Runtime::InteropServices;
    #pragma managed void ManagedStringFunc(wchar_t* s)
    {
    String^ ms = Marshal::PtrToStringUni((IntPtr)s);
    /* копирует символы строки s в Юникоде в кучу, преобразовывая их в строку, и выдает указатель на месторасположения строки.

    478 Часть II. Приложения Windows Form
    Аргумент метода по его определению должен иметь тип IntPtr (внутренний указатель, поэтому s преобразуется к этому типу.
    */
    Console::WriteLine("(managed) recieved '{0}'", ms);
    }
    #pragma unmanaged void NativeProvidesAString()
    { printf("(unmanaged) calling managed func...\n");
    ManagedStringFunc(L"test string");
    }
    #pragma managed int main() {
    NativeProvidesAString();
    _getch();
    } Пример 5. Маршалинг native
    -
    структуры
    В данном примере показана работа с структурой в функции. Текст программы показан в листинге 14.5, а результат — на рис. 14.5. Рис 14.5.
    Маршалинг структуры
    Листинг 14.5
    // 14.5_2011 Прим 5.cpp : main project file.
    #include "stdafx.h"
    #include
    #include using namespace System; using namespace System::Runtime::InteropServices;
    Глава
    14. Преобразование между нерегулируемыми и
    регулируемыми указателями
    #pragma unmanaged структура struct Location
    { int x; int y;
    }; параметры функции — два экземпляра структуры double GetDistance(Location loc1, Location loc2)
    { printf("[unmanaged] loc1(%d,%d)", loc1.x, loc1.y); printf(" loc2(%d,%d)\n", loc2.x, loc2.y); double h = loc1.x — loc2.x; double v = loc1.y = loc2.y; квадратный корень из h2 + v2: double dist = sqrt( pow(h,2) + pow(v,2) ); return dist;
    } параметр функции — указатель на структуру void InitLocation(Location* lp)
    { printf("[unmanaged] Initializing location...\n"); lp->x = 50; lp->y = 50;
    }
    #pragma managed работа со структурой в функции int main()
    {
    Location loc1; loc1.x = 0; loc1.y = 0;
    Location loc2; loc2.x = 100; loc2.y = 100; вызов функции в функции double dist = GetDistance(loc1, loc2);
    Console::WriteLine("[managed] distance = {0}", dist);
    Location loc3; вызов функции в функции в ее параметре указатель, поэтому берется адрес экземпляра структуры

    480 Часть II. Приложения Windows Form
    InitLocation(&loc3);
    Console::WriteLine("[managed] x={0} y={1}", loc3.x, loc3.y);
    Console::ReadLine();
    } Пример 6. Работа с массивом элементов структуры в managed
    -
    функции
    Текст программы показан в листинге 14.6, а результат — на рис. 14.6. Рис 14.6. Результат работы с массивом элементов nati ve- структуры в managed
    - функции
    Листинг 14.6
    // 14.6_2011 Прим 6.cpp : main project file.
    #include "stdafx.h"
    #include using namespace System; using namespace System::Runtime::InteropServices;
    // unmanaged struct struct ListStruct
    Глава
    14. Преобразование между нерегулируемыми и
    регулируемыми указателями
    { int count; double* item;
    };
    #pragma unmanaged void UnmanagedTakesListStruct(ListStruct list)
    { printf_s("[unmanaged] count = %d\n", list.count); for (int i=0; i}
    #pragma managed int main()
    {
    ListStruct list; list.count = 10; list.item =new double[list.count];
    /* оператор new размещает объект в куче и возвращает указатель на этот объект.
    В данном случаев куче формируется одномерный массив из list.count элементов.
    */
    Console::WriteLine("[managed] count = {0}", list.count);
    создается указатель на объект, формирующий случайные числа
    Random^ r = gcnew Random(0);
    /* инициализация массива list.item[] случайными числами из интервала [0,1], умноженными на 100
    */ for (int i=0; i { list.item[i] = r->NextDouble() * 100.0;
    Console::WriteLine("array[{0}] = {1}", i, list.item[i]);
    }
    вызов функции в функции
    UnmanagedTakesListStruct(list);
    Console::ReadLine();
    }

    482 Часть II. Приложения Windows Пример 7. Доступ к символам в классе Это частный случай примера 3. Здесь интересна работа с указателем, показывающим на строку (строку "обычных" символов) в управляемой куче. Кавычки поставлены для того, чтобы указать на необычность ситуации каждый символ занимает (в отличие от обычной строки символов типа char
    ) два, а не один байт, т. к. находится в управляемой куче. Поэтому и признак конца — это необычный символа. Текст программы показан в листинге 14.7, а результат — на рис. 14.7. Рис 14.7. Доступ к символам
    System::String
    - строки
    Листинг 14.7
    // 14.7_2011 Прим 7.cpp : main project file.
    #include "stdafx.h"
    #include using namespace System; int main()
    {
    String ^ mystring = "abcdefg"; Описание метода показано в примере 3 */ interior_ptr ppchar = PtrToStringChars( mystring ); цикл по строке символов от нулевого (*ppchar) до признака конца строки
    (L'\0')*/ for ( ; *ppchar != L'\0'; ++ppchar )
    Console::Write(*ppchar);
    Console::Write(L'\n'); переход на новую, после выданной, строку
    Console::ReadLine();
    }
    Глава
    14. Преобразование между нерегулируемыми и
    регулируемыми указателями Пример 8. Преобразование
    char в массив Текст программы показан в листинге 14.8, а результат — на рис. 14.8. Рис 14.8. Результат преобразования строки обычных символов в массив
    System::Byte
    Листинг 14.8
    // 14.8_2011 Прим 8.cpp : main project file.
    #include "stdafx.h"
    #include //for strlen() using namespace System; using namespace System::Runtime::InteropServices; int main() { char buf[] = "Native String"; int len = strlen(buf); длина строки array< Byte >^ byteArray = gcnew array< Byte >(len + 2);
    копирование символов char c преобразованием указателя на них во внутренний указатель на них в управляемой куче.
    Преобразование идет в обычном С-стиле:*/
    Marshal::Copy((IntPtr)buf,byteArray, 0, len); вывод (для проверки преобразования) элементов массива с использованием методов класса array:*/ for ( int i = byteArray->GetLowerBound(0); i <= byteArray->GetUpperBound(0); i++ )
    {
    /*byteArray->GetValue(i) выдает указатель на объекта объектами являются элементы массива типа Byte. Поэтому идет преобразование типа.
    Но внутренний указатель в управляемой куче обладает свойствами обычного С++-указателя, поэтому можно применить операцию разыменования (*), чтобы получить обычный символ char dc = *(Byte^) byteArray->GetValue(i);

    484 Часть II. Приложения Windows Form
    преобразование (С) обычного символа в Юникод-символ, чтобы воспользоваться выводом из класса Console:*/
    Console::Write((Char)dc);
    }
    выдает стандартный символ окончания строки в стандартный
    выходной поток
    Console::WriteLine();
    Console::ReadLine();
    } Пример 9. Преобразование вили Метод
    PtrToStringChars()
    из Vcclr.h можно использовать для преобразования строки в строку типа wchar_t *
    или char *
    . Метод возвращает указатель на Юникод-строку, т. к. строки CLR — это строки Юникода. Затем, как показано в примере, вы можете конвертировать "широкую" строку в обычную. Текст программы показан в листинге 14.9, а результат — на рис. 14.9. Рис 14.9. Результат преобразования
    System::String
    - строки в wchar_t и char Листинг 14.9

    // 14.9_2011 Прим 9.cpp : main project file.
    #include "stdafx.h"
    #include < stdio.h >
    #include < conio.h >
    #include < stdlib.h >
    #include < vcclr.h > //for PtrToStringChars() using namespace System; int main()
    {
    String ^str = "Hello from our friends!";
    Глава
    14. Преобразование между нерегулируемыми и
    регулируемыми указателями
    преобразование строки в тип wchar_t в управляемой куче и формирование указателя на новую строку (указателя-фиксатора), чтобы строка не переместилась в куче, пока будет идти вызов функции printf():*/ pin_ptr wch = PtrToStringChars(str); printf_s("%S\n", wch);
    преобразование к типу char *: можно сразу перевести wchar_t * в char *, используя одну из функций-преобразователей WideCharToMultiByte() и wcstombs_s():*/ size_t convertedChars = 0; size_t sizeInBytes = ((str->Length + 1) * 2); errno_t err = 0;
    выделение памяти в неуправляемой куче под размер строки () ch будет на нее указывать char *ch = (char *)malloc(sizeInBytes); err = wcstombs_s(&convertedChars, //кол-во преобразуемых символов ch, sizeInBytes, адрес, куда они станут записываться wch, адрес, откуда они станут записываться sizeInBytes); количество переписываемых байтов if (err != 0) printf_s("wcstombs_s failed!\n"); printf_s("%s\n", ch); вывод переписанной строки
    _getch();
    } Пример 10. Преобразование в Фирма Microsoft ввела в С+ типы строки. На самом деле — это синонимы класса basic_string
    , введенные через typedef
    . Первый тип относится к классу, строки которого (как элементы класса) относятся к типу char
    , а второй тип — к классу, строки которого (как элементы класса) относятся к типу В табл. 14.2 приведены операторы для работы со строками указанных типов. Таблица Операторы для работы со строками типов и wstring

    Оператор
    Описание
    + Сцепляет две строки Проверяет, неравны ли две строки- операнда Проверяет, равны ли две строки- операнда

    486 Часть II. Приложения Windows Таблица 14.2
    (окончание)
    Оператор
    Описание
    < Проверяет, меньше ли строка слева от знака оператора строки справа от знака оператора Проверяет, меньше или равна строка слева от знака оператора строки справа от знака оператора Вставляет строку в выходной поток (аналог cout при С+ вводе/выводе)
    > Проверяет, больше ли строка слева от знака оператора строки справа от знака оператора Проверяет, больше или равна ли строка слева от знака оператора строки справа от знака оператора Извлекает строку из выходного потока (аналог cin при С+ вводе/выводе)
    swap Если выполнить оператор swap(m1, с этой функцией, тов будет содержимое m2, а в содержимое m1
    getline Извлекает строку из входного потока c_str Преобразует string
    - строку в С- строку
    Для работы со строками в программе надо выполнить операторы
    #include и using namespace Пример программы, использующей оператор
    !=
    , приведен в листинге 14.10, аре- зультат показан на рис. 14.10. Листинг 14.10
    // 14.10_2011 Прим 10.cpp : main project file.
    #include "stdafx.h"
    #include
    #include
    #include using namespace std ; void trueFalse(int x)
    { cout << (x? "True": "False") << endl;
    } int main()
    { string S1="ABC";
    Глава
    14. Преобразование между нерегулируемыми и
    регулируемыми указателями
    char CP1[]="ABC"; char CP2[]="DEF"; char CP3[]="abc"; cout << "S1 is " << S1 << endl; cout << "CP1 is " << CP1 << endl; cout << "CP2 is " << CP2 << endl; cout << "CP3 is " << CP3 << endl; cout << "S1!=CP1 returned "; trueFalse(S1!=CP1); // False cout << "S1!=CP2 returned "; trueFalse(S1!=CP2); // True cout << "S1!=CP3 returned "; trueFalse(S1!=CP3); // True cout << "CP1!=S1 returned "; trueFalse(CP1!=S1); // False cout << "CP2!=S1 returned "; trueFalse(CP2!=S1); // True cout << "CP3!=S1 returned "; trueFalse(CP3!=S1); // True
    _getch();
    } Строки
    String
    — это последовательности Юникод-символов. Программа, использующая маршалинг для преобразования строк типа
    String в строки типа string и wstring
    , приведена в листинге 14.11, а результат ее работы показан на рис. 14.11. Рис 14.10. Результат работы программы, указанной в листинге Рис 14.11. Результат работы со строками
    String
    , string и wstring

    488 Часть II. Приложения Windows Листинг 14.11
    // 14.11_2011 Прим 11.cpp : main project file.
    #include "stdafx.h"
    #include здесь операторы для string и wstring
    #include
    #include для С+ вывода using namespace System; using namespace std; здесь находятся данные о типах string и wstring using namespace Runtime::InteropServices;
    //----------------- функция копирует s в os типа string -------------------- void MarshalString ( String ^ s, string & os )
    {
    /*Маршал-метод копирует содержимое строки в неуправляемую память (кучу) и выдает указатель типа void для его последующего преобразования в необходимый тип
    (в данном случаев указатель на строку с символами char:*/ os = chars;
    освобождение памяти в неуправляемой куче, которую занимает строка
    Marshal::FreeHGlobal(IntPtr((void*)chars));
    }
    //----------------- функция копирует s в os типа wstring -------------- void MarshalString ( String ^ s, wstring & os )
    {
    /*Маршал-метод копирует содержимое строки в неуправляемую память (кучу) и выдает указатель типа void для его последующего преобразования в необходимый тип
    (в данном случаев теперь можно присвоить, т.к. переменные одного типа
    освобождение памяти в неуправляемой куче, которую занимает строка
    Marshal::FreeHGlobal(IntPtr((void*)chars));
    } int main()
    { string a = "test"; wstring b = L"test2"; широкая" строка (по 2 байта на символ)
    String ^ c = gcnew String("abcd");
    Глава
    14. Преобразование между нерегулируемыми и
    регулируемыми указателями
    cout << a << endl; вывод строки а
    MarshalString(c, a); перезапись св а c = "efgh";
    MarshalString(c, b); перезапись св вывода вывод b
    _getch();
    } Пример 11. Преобразование строки в
    1   ...   29   30   31   32   33   34   35   36   37


    написать администратору сайта