??xml version="1.0" encoding="utf-8" standalone="yes"?>香蕉久久永久视频,亚洲AV无码久久寂寞少妇,久久精品国产99国产精品澳门http://www.shnenglu.com/golq/archive/2009/07/09/89692.html英勇的近卫军英勇的近卫军Thu, 09 Jul 2009 14:33:00 GMThttp://www.shnenglu.com/golq/archive/2009/07/09/89692.htmlhttp://www.shnenglu.com/golq/comments/89692.htmlhttp://www.shnenglu.com/golq/archive/2009/07/09/89692.html#Feedback0http://www.shnenglu.com/golq/comments/commentRss/89692.htmlhttp://www.shnenglu.com/golq/services/trackbacks/89692.html C++/CLI中函数的工作方式与ISO/ANSI C++完全相同Q但׃在C++/CLI中用跟踪句柄和跟t引用替代了本地指针和引用,因此也带来一些变化,主要包括

  • CLRE序中函数的形参与返回值可以是数值类型、跟t句柄、跟t引用和内部指针?/div>
  • 如果某个形参是CLR数组Q程序不需要另外的参数指定其大,因ؓ数组大小在属性Length中?/div>
  • 在C++/CLIE序中,不能像C++一栯行地址的算术运,而应使用数组索引。(内部指针不是可以术操作吗?Q?/div>
  • 可以方便的返回CLR堆上的句柄,因ؓCLR有垃圑֛收机制自动清理无用的内存?/div>
  • C++/CLI函数接收可变长度参数的机制与本地C++不同?/div>
  • C++/CLI中main()函数讉K命o行实参的机制与本地C++不同?/div>

下面最?条进行说明?/p>

一、接收可变长度参数的函数

C++/CLI允许Ş参列表指定ؓ数组Q数l声明前面加省略P从而实现实参的长度可变?/p>

int sum(...array<int>^ args)
{
	// Code for sum
}

上面的sum()函数可以接收L数量的整C为实参,在函数内部,通过讉K数组args的元素就可以实现对实参的处理Q实参个数由args的属性Length得到。下面是一个完整的例子Q描qC该机制的工作q程?/p>

- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::开?=>> [Ex5_15.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Ex5_15.cpp : main project file.
#include "stdafx.h"
using namespace System;

double sum(...array<double>^ args)
{
	double sum = 0.0;
	for each(double arg in args)
		sum += arg;
	return sum;
}

int main(array<System::String ^> ^args)
{
	Console::WriteLine( sum(2.0, 4.0, 6.0, 8.0, 10.0, 12.0) );
	Console::WriteLine( sum(1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9) );
        return 0;
}
- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::l束==>> [Ex5_15.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

输出?/p>

42
49.5

二、main()的实?/h1>

从前面的例子可以看出QCLRE序中main()函数仅有一个Ş参,它ؓString^cd的数l,q就处理命令行实参化ؓ讉K该数l的元素。下面的例子展示了这个用法?/p>

此外q应注意Q?font color="#ffff00">与本地C++中main()不同Q命令行参数中不包括E序名称本n?/font>

- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::开?=>> [Ex5_16.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Ex5_16.cpp : main project file.
#include "stdafx.h"
using namespace System;

int main(array<System::String ^> ^args)
{
	Console::WriteLine(L"There were {0} command line arguments.", args->Length);
	Console::WriteLine(L"Command line arguments received are:");
	int i=1;
	for each(String^ str in args)
		Console::WriteLine(L"Argument {0}: {1}", i++, str);
    
	return 0;
}
- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::l束==>> [Ex5_16.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
输出?/pre>
D:\My Documents\My Projects\Ex5_16\Debug>ex5_16 tring multiple "arguments values
" 4.5 0.0
There were 5 command line arguments.
Command line arguments received are:
Argument 1: tring
Argument 2: multiple
Argument 3: arguments values
Argument 4: 4.5
Argument 5: 0.0


]]>C++/CLI学习入门(?:跟踪句柄、跟t引用及内部指针http://www.shnenglu.com/golq/archive/2009/07/09/89682.html英勇的近卫军英勇的近卫军Thu, 09 Jul 2009 13:47:00 GMThttp://www.shnenglu.com/golq/archive/2009/07/09/89682.htmlhttp://www.shnenglu.com/golq/comments/89682.htmlhttp://www.shnenglu.com/golq/archive/2009/07/09/89682.html#Feedback0http://www.shnenglu.com/golq/comments/commentRss/89682.htmlhttp://www.shnenglu.com/golq/services/trackbacks/89682.html与本地C++自己l护堆不同,C++/CLI中动态分配的内存是由CLR来维护的。当不需要堆ӞCLR自动其删除回收Q同时CLRq能自动地压~内存堆以避免生不必要的内存碎片。这U机制能够避?strong>内存泄露?strong>内存片Q被UCؓ垃圾回收Q而由CLR理的这U堆被称为CLR堆。它由操作符gcnew创徏?/p>

׃垃圾回收机制会改变堆中对象的地址Q因此不能在CLR堆中使用普通C++指针Q因为如果指针指向的对象地址发生了变化,则指针将不再有效。ؓ了能够安全地讉K堆对象,CLR提供了跟t句柄(cM于C++指针Q和跟踪引用Q类gC++Q引用?/p>

一、跟t句?/h1>

跟踪句柄cM于本地C++指针Q但能够被CLR垃圾回收器自动更C反映被跟t对象的新地址。同时不允许对跟t句柄进行地址的算术运,也不能够q行强制cd转换?/p>

凡是在CLR堆上创徏的对象必被跟踪句柄引用Q这些对象包括:(1)用gcnew操作W显C创建在堆上的对象;(2)所有的引用数据cdQ数值类型默认分配在堆栈上)?strong>注意Q所有分配在堆上的对象都不能在全局范围内被创徏?/font>

关于跟踪句柄的相关用方法参见?a href="http://www.shnenglu.com/golq/archive/2009/06/29/88733.html">C++/CLI学习入门(?:数组?/p>

二、跟t引?/h1>

跟踪引用cM于本地C++引用Q表C某对象的别名。可以给堆栈上的值对象、CLR堆上的跟t句柄创t引用。跟t引用本wL在堆栈上创徏的。如果垃圑֛收移动了被引用的对象Q则跟踪引用被自动更新?/p>

跟踪引用?来定义,下面的例子创Z一个对堆栈上值对象的跟踪引用Q?/p>

int value = 10;
int% trackValue = value;

stackValue为value变量的引用,可以用stackValue来访问valueQ?/p>

trackValue *= 5;
Console::WriteLine(value);	// Result is 50

三、内部指?/h1>

C++/CLIq提供一U用关键字interior_ptr定义的内部指针,它允许进行地址的算术操作。必要时Q该指针内存储的地址会由CLR垃圾回收自动更新。注意,内部指针L函数的局部自动变量?/p>

下面的代码定义了一个内部指针,它含有某数组中第一个元素的地址Q?/p>

array<double>^ data = {1.5, 3.5, 6.7, 4.2, 2.1};
interior_ptr<double> pstart = %data[0];

必须linterio_ptr指定内部指针指向的对象类型。此外还应该l指针进行初始化Q如果不提供初始|pȝ其默认初始化ؓnullptr?/p>

内部指针在指定类型时应注意:可以包含堆栈上值类型对象的地址Q也可以包含指向CLR堆上某对象句柄的地址Q还可以是本地类对象或本地指针,?strong>不能是CLR堆上整个对象的地址。也是_可以使用内部指针存储作ؓCLR堆上对象l成部分的数值类对象Q如CLR数组元素Q的地址Q也可以存储System::String对象跟踪句柄的地址Q但不能存储String对象本n的地址?/p>

interior_ptr<String^> pstr1;	// OK -- pointer to a handle
interior_ptr<String>  pstr2;	// ERROR -- pointer to a String object

与本地C++指针一P内部指针可以q行术计算。可以通过递增或递减来改变其包含的地址Q从而引用后面或前面的数据项Q还可在内部指针上加上或减去某个整数Q可以比较内部指针。下面的例子展示了内部指针的用法Q?/p>

- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::开?=>> [Ex4_19.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Ex4_19.cpp : main project file.
#include "stdafx.h"
using namespace System;

int main(array<System::String ^> ^args)
{
	array<double>^ data = {1.5, 3.5, 6.7, 4.2, 2.1};
	interior_ptr<double> pstart = &data[0];
	interior_ptr<double> pend = &data[data->Length - 1];
	double sum = 0;

	while(pstart<=pend)
		sum += *pstart++;

	Console::WriteLine(L"Total of data array elements = {0}\n", sum);

	array<String^>^ strings = { L"Land ahoy!",
		L"Splice the mainbrace!",
		L"Shiver me timbers!",
		L"Never throw into the wind!"
	};

	for(interior_ptr<String^> pstrings = &strings[0]; pstrings-&strings[0] < strings->Length; ++pstrings)
		Console::WriteLine(*pstrings);

    return 0;
}
- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::l束==>> [Ex4_19.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

输出?/p>

Total of data array elements = 18

Land ahoy!
Splice the mainbrace!
Shiver me timbers!
Never throw into the wind!


]]>C++/CLI学习入门(?:字符?/title><link>http://www.shnenglu.com/golq/archive/2009/07/07/89505.html</link><dc:creator>英勇的近卫军</dc:creator><author>英勇的近卫军</author><pubDate>Tue, 07 Jul 2009 15:39:00 GMT</pubDate><guid>http://www.shnenglu.com/golq/archive/2009/07/07/89505.html</guid><wfw:comment>http://www.shnenglu.com/golq/comments/89505.html</wfw:comment><comments>http://www.shnenglu.com/golq/archive/2009/07/07/89505.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/golq/comments/commentRss/89505.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/golq/services/trackbacks/89505.html</trackback:ping><description><![CDATA[<p style="text-indent: 24pt">C++/CLI字符ԌUnicode字符l成的字W串Q是指在System命名I间中定义的Stringc,即由System:Charcd的字W序列组成的字符丌Ӏ它包含大量强大的功能,使得字符串的处理非常Ҏ。创Z个String对象的方法如下例所C:</p><pre>System::String^ saying = L"<span style="color: #8b0000">Many hands make light work.</span>";</pre> <p style="text-indent: 24pt">跟踪句柄saying用于讉KStringcd象。该对象的字Wؓ宽字W,因ؓ采用了前~ “L”,如果省略“L”,该字W串?位的字符l成Q编译器确保将其{换成宽字W?/p> <p style="text-indent: 24pt">讉K字符串内字符可以像访问数l元素一P使用索引来访问,首字W的索引?。这U方法只能用于读取字W串内字W,但不能用于修改字W串的内宏V?/p><pre>Console::WriteLine("<span style="color: #8b0000">The third character in the string is {0}</span>", saying[2]);</pre> <p style="text-indent: 24pt">利用Length属性,可以获取字符串内字符的数量(长度Q?/p><pre>Console::WriteLine("<span style="color: #8b0000">The saying has {0} charactors.</span>", saying->Length);</pre> <h1>一、连接字W串</h1> <p style="text-indent: 24pt">利用 ?”可以连接字W串QŞ成新的字W串。执行下面的例子之后Qname3包含字W串 “Beth and Betty”?/p><pre>String^ name1 = L"<span style="color: #8b0000">Beth</span>"; String^ name2 = L"<span style="color: #8b0000">Betty</span>"; String^ name3 = name1+L"<span style="color: #8b0000"> and </span>"+name2;</pre> <p style="text-indent: 24pt">?”还可以用来q接字符串与数倹{bool值等非字W串变量Q在q接之前Q这些变量将自动的{换成字符丌Ӏ?/p><pre>String^ str = L"<span style="color: #8b0000">Value: </span>"; String^ str1 = str + 2.5; <span style="color: #008000">// str1 is "Value: 2.5"</span> String^ str2 = str + 25; <span style="color: #008000">// str2 is "Value: 25"</span> String^ str3 = str + <span style="color: #0000ff">true</span>; <span style="color: #008000">// str3 is "Value: True"</span></pre> <p style="text-indent: 24pt">?”还可以用来q接字符串与字符Q但要注意,<strong>l果字符串的形式取决于字W的cd?/strong>q是因ؓcharcd的字W被视ؓ数|wchar_t与String对象的字W具有相同的cdQCharcdQ?/p><pre><span style="color: #0000ff">char</span> ch = 'Z'; wchar_t wch = 'Z'; String^ str4 = str + ch; <span style="color: #008000">// str4 is "Value: 90"</span> String^ str5 = str + wch; <span style="color: #008000">// str5 is "Value: Z"</span></pre> <p style="text-indent: 24pt">Stringcd定义了Join()函数Q用于将数组中的多个字符串连接成一个字W串Q数l元素之间用分隔W隔开Q如</p><pre>array<String^>^ names = {"<span style="color: #8b0000">Jill</span>", "<span style="color: #8b0000">Ted</span>", "<span style="color: #8b0000">Mary</span>", "<span style="color: #8b0000">Eve</span>", "<span style="color: #8b0000">Bill</span>"}; String^ seperator = "<span style="color: #8b0000"> and </span>"; String^ joined = String::Join(seperator, names); <span style="color: #008000">// joined is "Jill and Ted and Mary and Eve and Bill"</span></pre> <p style="text-indent: 24pt"><strong>特别注意QString对象是固定不变的Q一旦创建完毕后׃能再被修改了。这意味着所有的字符串操作都是在创徏新的字符丌Ӏ?/strong></p> <p style="text-indent: 24pt">下面的例子将整数数组内的元素按列整齐地输出?/p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:332fa510-2da2-4c81-9825-3ceed863ae66" class="wlWriterEditableSmartContent">- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::开?=>> [Ex4_17.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - </div><pre><span style="color: #008000">// Ex4_17.cpp : main project file.</span> #include "<span style="color: #8b0000">stdafx.h</span>" <span style="color: #0000ff">using</span> <span style="color: #0000ff">namespace</span> System; <span style="color: #0000ff">int</span> main(array<System::String ^> ^args) { array<<span style="color: #0000ff">int</span>>^ values = { 2, 456, 23, -46, 34211, 456, 5609, 112098, 234, -76504, 341, 6788, -909121, 99, 10 }; String^ formatStr1 = "<span style="color: #8b0000">{0, </span>"; String^ formatStr2 = "<span style="color: #8b0000">}</span>"; String^ number; <span style="color: #0000ff">int</span> maxLength = 0; <span style="color: #0000ff">for</span> each(<span style="color: #0000ff">int</span> value in values) { number = "<span style="color: #8b0000"></span>"+value; <span style="color: #0000ff">if</span>(maxLength<number->Length) maxLength = number->Length; } String^ format = formatStr1+(maxLength+1)+formatStr2; <span style="color: #0000ff">int</span> numberPerLine = 3; <span style="color: #0000ff">for</span>(<span style="color: #0000ff">int</span> i=0; i<values->Length; i++) { Console::Write(format, values[i]); <span style="color: #0000ff">if</span>((i+1)%numberPerLine == 0) Console::WriteLine(); } }</pre> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:39eaa58f-a5cc-4e1c-8310-d9c2137a5022" class="wlWriterEditableSmartContent">- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::l束==>> [Ex4_17.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - </div> <p style="text-indent: 24pt">输出?/p><pre> 2 456 23 -46 34211 456 5609 112098 234 -76504 341 6788 -909121 99 10</pre> <h1>二、修改字W串</h1> <p style="text-indent: 24pt">Trim()函数用于删除字符串头部和N的空根{不带参数调用该函数删除字W串头、尾部的全部I格q返回一新字W串?/p><pre>String^ str = {"<span style="color: #8b0000"> Handsome is as handsome does... </span>"}; String^ newStr = str->Trim();</pre> <p style="text-indent: 24pt">也可传递给Trim()函数字符数组作ؓ参数Q字W串?strong>从头部和N开?/strong>删除数组中的字符。如果字W出现在字符串中_则不会被删除?/p><pre>String^ toBeTrimed = L"<span style="color: #8b0000">wool wool sheep sheep wool wool wool</span>"; array<wchar_t>^ notWanted = {L'w', L'o', L'l', L' ' }; Console::WriteLine(toBeTrimed->Trim(notWanted));</pre> <p style="text-indent: 24pt">上面的语句将输出<br>sheep sheep</p> <p style="text-indent: 24pt">如果在上面的语句中没有加前缀”L“,则字WؓcharcdQ对应于System::SBytecd。不q编译器自动地其转换成wchar_tcdQ即System::CharcdQ?/p> <p style="text-indent: 24pt">Trim()函数也支持直接输入要删除的字W列表,下面的语句将产生同样的输?/p><pre>Console::WriteLine(toBeTrimed->Trim(L'w', L'o', L'l', L' '));</pre> <p style="text-indent: 24pt">如果仅仅惌删除头部或者尾部中的一端,可以使用TrimStart或者TrimEnd函数?/p> <p style="text-indent: 24pt">如果要在字符串的一端填充空格或其它字符Q这一般用于以固定宽度靠左或靠叛_齐输出文本)Q可使用PadLeft()和PadRight()函数。如果字W串长度大于指定的长度参敎ͼ则返回字W串为长度等于原来字W串的新字符丌Ӏ?/p><pre>String^ value = L"<span style="color: #8b0000">3.142</span>"; String^ leftPadded = value->PadLeft(10); <span style="color: #008000">// Result is " 3.142"</span> String^ rightPadded = value->PadRight(10); <span style="color: #008000">// Result is "3.142 "</span> String^ leftPadded2 = value->PadLeft(10, L'*'); <span style="color: #008000">// Result is "*****3.142"</span> String^ rightPadded2= value->PadRight(10,L'#'); <span style="color: #008000">// Result is "3.142#####"</span></pre> <p style="text-indent: 24pt">如果需要将字符串{换成大写或小写,可用ToUpper()或ToLower函数?/p><pre>String^ proverb = L"<span style="color: #8b0000">Many hands make light work.</span>" String^ upper = proverb->ToUpper(); <span style="color: #008000">// Result is "MANY HANDS MAKE LIGHT WORK."</span></pre> <p style="text-indent: 24pt">如果需要在字符串中间插入一个字W串Q可使用Insert()函数Q第一个参数指定v始位|的索引Q第二个参数指定要插入的字符丌Ӏ?/p><pre>String^ proverb = L"<span style="color: #8b0000">Many hands light work.</span>"; String^ newProverb = proverb->Insert(5, "<span style="color: #8b0000">deck </span>");</pre> <p style="text-indent: 24pt">l果?/p><pre>Many deck hands make light work.</pre> <p style="text-indent: 24pt">如果要用另一个字W替换字W串中指定的字符Q或者用另一个子串替换字W串中给定的子串Q可使用Replace()函数?/p><pre>String^ proverb = L"<span style="color: #8b0000">Many hands make light work.</span>" Console::WriteLine(proverb->Replace(L' ', L'*'); Console::WriteLine(proverb->Replace(L"<span style="color: #8b0000">Many hands</span>", L"<span style="color: #8b0000">Press switch</span>");</pre> <p style="text-indent: 24pt">输出?/p><pre>Many*hands*make*light*work. Pressing switch make light work.</pre> <h1>三、搜索字W串</h1> <p style="text-indent: 24pt">如果需要测试字W串是否以给定的子串开始或l束Q可使用StartWith()或EndWith()函数。要L的子串句柄作为参C递给函数Q返回bool倹{?/p><pre>String^ snetence = L"<span style="color: #8b0000">Hide, the cow's outside.</span>"; <span style="color: #0000ff">if</span>(sentence->StartWith(L"<span style="color: #8b0000">Hide</span>")) Console::WriteLine("<span style="color: #8b0000">The sentence starts with 'Hide'.</span>");</pre> <p style="text-indent: 24pt">IndexOf()函数用于q回l定字符或子串在字符串中扑ֈ的第一个实例烦引,如果未找刎ͼ则返?1?/p><pre>String^ sentence = L"<span style="color: #8b0000">Hide, the cow's outside.</span>"; <span style="color: #0000ff">int</span> ePosition = sentence->IndexOf(L'e'); <span style="color: #008000">// Return 3</span> <span style="color: #0000ff">int</span> thePosition = sentence->IndexOf(L"<span style="color: #8b0000">the</span>"); <span style="color: #008000">// Retuen 6</span></pre> <p style="text-indent: 24pt">也可以指定IndexOf搜烦的v始烦引,q一般用于遍历整个字W串扑և所有的实例Q如下面的例子:</p><pre><span style="color: #0000ff">int</span> index = 0; <span style="color: #0000ff">int</span> count = 0; <span style="color: #0000ff">while</span>((index=words->IndexOf(word, index))>=0) { index += word->Length; count++; } Console::WriteLine(L"<span style="color: #8b0000">'{0}' was found {1} times in: {2}</span>", word, count, words);</pre> <p style="text-indent: 24pt">LastIndexOf()函数cM于IndexOf()函数Q不q它用于从字W串N或指定烦引位|开始,倒着向头部搜索。注意:如果从尾部开始的索引值是words->Lenght-1?/p> <p style="text-indent: 24pt">如果要搜索一个字W串数组中Q意元素出现在字符串中的位|,可以使用IndexOfAny()函数。同P它也有倒序搜烦的版本?下面的例子说明了IndexOfAny()的用法。下面的例子用于搜烦字符串中的标点符?/p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:9d340c6c-5d14-43db-bb93-9712e07b5d52" class="wlWriterEditableSmartContent">- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::开?=>> [Ex4_18.CPP] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - </div><pre><span style="color: #008000">// Ex4_18.cpp : main project file.</span> #include "<span style="color: #8b0000">stdafx.h</span>" <span style="color: #0000ff">using</span> <span style="color: #0000ff">namespace</span> System; <span style="color: #0000ff">int</span> main(array<System::String ^> ^args) { array<wchar_t>^ punctuation = {L'"<span style="color: #8b0000">', L'\'', L'.', L',', L':',L'!', L'?'};</span> String^ sentence = L"<span style="color: #8b0000">\"It's chilly in here\", the boy 's mother said coldly.</span>"; array<wchar_t>^ indicators = gcnew array<wchar_t>(sentence->Length){L' '}; <span style="color: #0000ff">int</span> index = 0; <span style="color: #0000ff">int</span> count = 0; <span style="color: #0000ff">while</span>((index=sentence->IndexOfAny(punctuation, index))>=0) { indicators[index] = L'^'; ++index; ++count; } Console::WriteLine(L"<span style="color: #8b0000">There are {0} punctuation charactors in the string:</span>", count); Console::WriteLine(L"<span style="color: #8b0000">\n{0}\n{1}</span>", sentence, gcnew String(indicators)); <span style="color: #0000ff">return</span> 0; } </pre> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:c049a6cc-7ef0-44ea-823d-93e4485dc7e2" class="wlWriterEditableSmartContent">- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::l束==>> [Ex4_18.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - </div><pre> <u><em>输出?/em></u></pre><pre>There are 6 punctuation charactors in the <span style="color: #0000ff">string</span>: "<span style="color: #8b0000">It's chilly in here</span>", the boy 's mother said coldly. ^ ^ ^^ ^ ^</pre><img src ="http://www.shnenglu.com/golq/aggbug/89505.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/golq/" target="_blank">英勇的近卫军</a> 2009-07-07 23:39 <a href="http://www.shnenglu.com/golq/archive/2009/07/07/89505.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++/CLI学习入门(?:数组http://www.shnenglu.com/golq/archive/2009/06/29/88733.html英勇的近卫军英勇的近卫军Sun, 28 Jun 2009 17:34:00 GMThttp://www.shnenglu.com/golq/archive/2009/06/29/88733.htmlhttp://www.shnenglu.com/golq/comments/88733.htmlhttp://www.shnenglu.com/golq/archive/2009/06/29/88733.html#Feedback0http://www.shnenglu.com/golq/comments/commentRss/88733.htmlhttp://www.shnenglu.com/golq/services/trackbacks/88733.html要学习数l,必须先了解跟t句柄?/p>

一、跟t句?/h1>

跟踪句柄cM于本地C++指针Q但也有很大区别。跟t句柄确实存储着某个对象的地址Q但当CLR压羃堆过E中改变了该对象的地址Q则垃圾回收器自动更新句柄所包含的地址。我们不能像本地指针那样用跟t句柄来执行地址的算术运,也不允许对跟t句柄进行强制类型{换?

在CLR堆中创徏的对象必被跟踪句柄引用。所有属于引用类型的对象都存储在堆中Q因此ؓ引用q些对象所创徏的变量都必须是跟t句柄。例如,Stringcd是引用类型,因此引用String对象的变量必L跟踪句柄。值类型默认分配在堆栈上,但也可以用gcnew操作W将其存储在堆上。此外必L意,在堆上分配的变量——其中包括所有CLR引用cd——都不能在全局作用域内声明?

通过在类型名U后加”^”符P用于声明一个该cd的句柄。下面的例子声明了一个Stringcd的跟t句柄proverb?

String^ proverb;

在声明时句柄Ӟpȝ自动为其分配一个空|该句柄不引用M对象。也可显C地某个句柄置为空?

proverb = nullptr;

注意不能?来表C空倹{如果用0来初始化某个句柄Q则0自动{换ؓ被引用类型的对象Q而句柄则指向该对象。可以在声明句柄时显C的其初始化:

String^ saying = L"I used to think I was indecisive but now I??¡^¡؈m not so sure."; 

该语句首先在堆上创徏一个包含等号右边字W串的String对象Q然后将该对象的地址存入saying中。注意字W串字面值的cd为const wchar_t*而非String。类String提供了这LҎ使得const wchar_t*cd的字W串可以用来创徏Stringcd的对象?

下面q条语句创徏了值类型的句柄Q?/p>

int^ value = 99; 

      该语句在堆上创徏一个Int32型的值类型变量,然后该变量的地址存入句柄value中。由于value是一U指针,因此不能直接参与术q算Q可使用*q算W对地址求|cM于本地C++指针那样Q?

int result = 2*(*value)+15;

      ׃*value表示value所指向地址存储的数|因此result的gؓ2*99+15=213。注意,当value作ؓq算式左值时Q不需?卛_对value指向的变量赋倹{?

int^ result = 0;
result = 2*(*value)+15;

      首先创徏了一个指向数?的句柄result。(该语句会触发一条编译器警告Q提CZ能利?来将句柄初始化ؓI倹{)

      W?条语?号右边ؓ数|而左边ؓ句柄Q编译器自动将叛_D予句柄所指向的对象,卛_其{换ؓ如下语句

*result = 2*(*value)+15;

       注意Q要采用上面的语句,result句柄必须实际定义q。如果仅仅声明了resultQ则会生运行时错误

int^ result;
*result = 2*(*value)+15;

       q是因ؓW二句要对地址result求|x味着result指向的对象已l存在,但实际ƈ非如此,因ؓ声明该对象时pȝ默认赋予其空?nullptr)。在q种情况下,采用下面的方法就可以正常工作?

int^ result;
result = 2*(*value)+15; 

二、数l?/h1>

(一)数组句柄

       CLR数组是分配在可回收垃圑֠上的。必ȝarray<typename>指出要创建的数组Q同其它CLR堆上的对象一P需要用句柄来访问它Q例子如下:

array<int>^ data;

      数组句柄data可用于存储对元素cd为int的一l数l的引用。下面的例子声明了一个句柄,q新Z个CLR数组来对此句柄初始化?/p>

array<int>^ data = gcnew array<int>(100); 

       和本地C++数组一PCLR数组中元素的索引g是从0开始的Q可以通过[ ]讉K数组元素。数l元素都是CLR对象Q在上面的例子中数组元素为Int32型对象,它们在算术表辑ּ中就像普通的整数cd一栗?

       Length属性是数组的一个重要属性,记录着数组元素的数量。保存了64位的数组长度?

for(int i=0; i<data->Length; i++)
	data[i] = 2*(i+1);

可以用for each循环遍历数组元素?/p>

array<int>^ value = {3, 5, 6, 8, 6};
for each(int item in value)
{
	item = 2*item + 1;
	Console::WriteLine("{0, 5}", item);
}

该@环输?字符宽度的字D,以右寚w的方式输出当前元素的计算l果Q输出如下:

    7   11   13   17   13 

       数组句柄可以被重新赋|只要保持数组元素cd和维敎ͼ{Q不变即可,在前面例子中的数l句柄data指向一个intcd的一l数l,可以重新l它赋|使其指向另外的intcd1l数l:

data = gcnew array<int>(45);

       数组可以在创建时通过元素列表初始化,下例在CLR堆上创徏了一个doublecd的数l,q将引用赋值给了数l句柄:

array<double>^ sample = {3.4, 2.3, 6.8, 1.2, 5.5, 4.9, 7.4, 1.6};

       如果在声明数l句柄时不进行初始化Q那么在l句柄赋值时不能采用上面的方法直接用元素列表用作叛_|而必采用显C创建的方式。即不能

array<double>^ sample;
sample = {3.4, 2.3, 6.8, 1.2, 5.5, 4.9, 7.4, 1.6}

       而必采用如下方?

array<double>^ sample;
sample = gcnew array<double>{3.4, 2.3, 6.8, 1.2, 5.5, 4.9, 7.4, 1.6}

       对于字符串数l,注意每一个元素也是引用类型,q是因ؓ每一个元素String也是在CLR堆上创徏的,因此也要用String^来访问它?

array<String^>^ names = {"Jack", "John", "Joe", "Jessica", "Jim", "Joanna"};

       可以用Arrayc静态函数Clear()Ҏl中的连l数l元素清零?

Array::Clear(samples, 0, samples->Length);

       Clear()函数的第一个参数是被清零的数组Q第二个参数是要清除地第一个元素的索引Q第三个参数清除地元素数量。因此上q语句将samples数组的所有元素都|ؓ0。如果Clear()清除的是某个跟踪句柄Q则句柄所对应的元素都被应用Clear()函数。如果元素ؓbool型,则被|ؓfalse?

(?数组排序

Arrayc还定义了一个Sort()静态函敎ͼ可用于对数组q行排序。如果以数组句柄作ؓ参数Q则Ҏ个数l排序。如果要Ҏl部分排序,则还需要增加元素v始烦引及数量Q如下例

array<int>^ samples = {27, 3, 54, 11, 18, 2, 16};
Array::Sort(samples, 2, 3);

排序后数l元素变为{27, 3, 11, 18, 54, 2, 16}

Sort函数q有很多其它版本Q下面的例子展示了如何排序两个相关的数组Q即W一个数l中的元素是W二个数l对应元素的键。对W一个数l排序后Q可对第二个数组q行相应的调_使得键与值相互对应?/p>

Sort()函数?个数l排序时Q用W一个数l参数来定两个数组的顺序,以此保持2个数l元素对应关pM变?/p>

- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::开?=>> [Ex4_13.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Ex4_13.cpp : main project file.
#include "stdafx.h"
using namespace System;

int main(array<System::String ^> ^args)
{
	array<String^>^ names = { "Jill", "Ted", "Mary", "Eve", "Bill", "Al" };
	array<int>^ weights = {103, 168, 128, 115, 180, 176};

	Array::Sort(names, weights);
	for each( String^ name in names )
		Console::Write(L"{0, 10}", name);
	Console::WriteLine();
	
	for each(int weight in weights)
		Console::Write(L"{0, 10}", weight);
	Console::WriteLine();
	
	return 0;
}
- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::l束==>> [Ex4_13.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
输出为: 
Al Bill Eve Jill Mary Ted 
176 180 115 103 128 168 

(?数组搜烦

Arrayc还提供了函数BinarySearch()以用对分法搜烦法Q对一l数l或l定范围内搜索特定元素的索引位置。用该函数要求数组必须是顺序排列的Q因此在搜烦之前必须Ҏl进行排序?/p>

array<int>^ value = { 23, 45, 68, 94, 123, 150, 203, 299 };
int toBeFound = 127;
int position = Array::BinarySearch(value, toBeFound);
if(position<0)
        Console::WriteLine(L"{0} was not found.", toBeFound);
else
        Console::WriteLine(L"{0} was found at index position {1}", toBeFound, position);

Array::BinarySearch()的第一个参数是被搜索数l的句柄Q第二个参数是要查找的内容,q回gؓintcd的数倹{如果返回值小?则说明未扑ֈ。如果要指定搜烦范围Q则需要传?个参敎ͼ其中W?参数为搜索v始烦引,W?参数为搜索的元素数量Q第4个是要搜索的内容。下面的代码从第4个元素开始,一直搜索到l束位置?/p>

array<int>^ value = { 23, 45, 68, 94, 123, 150, 203, 299 };
int toBeFound = 127;
int position = Array::BinarySearch(value, 3, 6, toBeFound);    
- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::开?=>> [Ex4_14.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Ex4_14.cpp : main project file.
#include "stdafx.h"
using namespace System;

int main(array<System::String ^> ^args)
{
	array<String^>^ names = { "Jill", "Ted", "Mary", "Eve", "Bill", "Al", "Ned", "Zoe", "Dan", "Jean" };
	array<int>^ weights = {103, 168, 128, 115, 180, 176, 209, 98, 190, 130};
	array<String^>^ toBeFound = {"Bill", "Eve", "Al", "Fred"};
	
	int result = 0;
	Array::Sort(names, weights);

	for each( String^ name in toBeFound )
	{
		result = Array::BinarySearch(names, name);
		if(result<0)
			Console::WriteLine(L"{0} was not found.", name);
		else
			Console::WriteLine(L"{0} weights {1} lbs.", name, weights[result]);
	}

	return 0;
}
- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::开?=>> [Ex4_14.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

        当搜索不到目标时QArray::BinarySearch()函数输出的ƈ非Q意负敎ͼ而是W一个大于该目标的元素烦引值的按位补码。利用该ҎQ可以不打ؕ序在数l中插入新倹{如Q我们希望插入”Fred”到names数组?/p>

array<String^>^ names = { "Jill", "Ted", "Mary", "Eve", "Bill", "Al", "Ned", "Zoe", "Dan", "Jean" }
Array::Sort(names);
String^ name = L"Fred";
int position = Array::BinarySearch(names, name);
if(position<0)
position = ~position;

此时Qposition保存的是大于Fred的第一个元素的位置Q该数值可用于插入新倹{?/p>

array<String^>^ newNames = gcnew array<String^>(names->Length+1);
for(int i=0;i<position;i++)
	newNames[i] = names[i];
newNames[position] = name;

if(position<name->Length)
	for(int i=position; i<names->Length; i++)
		newNames[i+1] = names[i];
names = nullptr;

注意Q最后一句用于删除names数组?

(?多维数组

C++/CLI中可以创建多l数l,最大维?2l。与ISO/ANSI C++不同的是QC++/CLI中的多维数组q数组的数l,而是真正的多l数l,创徏整数多维数组Ҏ如下Q?/p>

array<int 2>^ value = gcnew array<int, 2>(4, 5);

上面的代码创Z一个二l数l,四行五列Q共20个元素。访问的Ҏ是利用多个用逗号分隔的烦引值来讉K每一个元素,而不能用一个烦引D问一?/p>

int nrows = 4;
int ncols = 5;
array<int, 2>^ value = gcnew array<int, 2>(nrows, ncols);
for(int i=0; i<nrows; i++)
    for(int j=0; j<ncols; j++)
        value[i, j] = (i+1)*(j+1);

上面的代码利用@环给二维数组value赋倹{这里访问二l数l元素的W号与本地C++不同Q后者实际上是数l的数组Q而C++/CLI是真正的二维数组Q不能用一个烦引值来讉K二维数组Q那h没有意义的。数l的l数被称为等U,上面value数组的等Uؓ2。而本地C++数组的等U始lؓ1。当Ӟ在C++/CLI中也可以定义数组的数l,Ҏ见下?/p>

- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::开?=>> [Ex4_15.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Ex4_15.cpp : main project file.
#include "stdafx.h"
using namespace System;

int main(array<System::String ^> ^args)
{
	const int SIZE = 12;
	array<int, 2>^ products = gcnew array<int, 2>(SIZE, SIZE);
	
	for(int i=0; i<SIZE; i++)
		for(int j=0; j<SIZE; j++)
			products[i, j] = (i+1)*(j+1);
	Console::WriteLine(L"Here is the {0} times table:", SIZE);

	// Write horizontal divider line
	for(int i=0; i<=SIZE; i++)
		Console::Write(L"_____");
	Console::WriteLine();

	// Write top line of table
	Console::Write(L"    |");
	for(int i=1; i<=SIZE; i++)
		Console::Write("{0, 3} |", i);
	Console::WriteLine();

	// Write horizontal divider line with verticals
	for(int i=0; i<=SIZE; i++)
		Console::Write("____|", i);
	Console::WriteLine();

	// Write remaining lines
	for(int i=0; i<SIZE; i++)
	{
		Console::Write(L"{0, 3} |", i+1);
		for(int j=0; j<SIZE; j++)
			Console::Write("{0, 3} |", products[i, j]);
		Console::WriteLine();
	}

	// Write horizontal divider line
	for(int i=0; i<=SIZE; i++)
		Console::Write("_____", i);
	Console::WriteLine();
	return 0;
}
- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::l束==>> [Ex4_15.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

上面的例子创Z一?2x12的乘法表Q输出如下:

Here is the 12 times table:
_________________________________________________________________
    |  1 |  2 |  3 |  4 |  5 |  6 |  7 |  8 |  9 | 10 | 11 | 12 |
____|____|____|____|____|____|____|____|____|____|____|____|____|
  1 |  1 |  2 |  3 |  4 |  5 |  6 |  7 |  8 |  9 | 10 | 11 | 12 |
  2 |  2 |  4 |  6 |  8 | 10 | 12 | 14 | 16 | 18 | 20 | 22 | 24 |
  3 |  3 |  6 |  9 | 12 | 15 | 18 | 21 | 24 | 27 | 30 | 33 | 36 |
  4 |  4 |  8 | 12 | 16 | 20 | 24 | 28 | 32 | 36 | 40 | 44 | 48 |
  5 |  5 | 10 | 15 | 20 | 25 | 30 | 35 | 40 | 45 | 50 | 55 | 60 |
  6 |  6 | 12 | 18 | 24 | 30 | 36 | 42 | 48 | 54 | 60 | 66 | 72 |
  7 |  7 | 14 | 21 | 28 | 35 | 42 | 49 | 56 | 63 | 70 | 77 | 84 |
  8 |  8 | 16 | 24 | 32 | 40 | 48 | 56 | 64 | 72 | 80 | 88 | 96 |
  9 |  9 | 18 | 27 | 36 | 45 | 54 | 63 | 72 | 81 | 90 | 99 |108 |
 10 | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | 90 |100 |110 |120 |
 11 | 11 | 22 | 33 | 44 | 55 | 66 | 77 | 88 | 99 |110 |121 |132 |
 12 | 12 | 24 | 36 | 48 | 60 | 72 | 84 | 96 |108 |120 |132 |144 |
_________________________________________________________________

其中创徏二维数组的代码如下:

const int SIZE = 12;
array<int, 2>^ products = gcnew array<int, 2>(SIZE, SIZE);

W一行定义了一个整型常量SIZEQ用于指定每一l数l的元素数量Q第二行代码定义了一个等U?的数l,?2x12大小Q该数组用于存储12x12的乘法表乘积。然后在嵌套循环中给数组赋|大部分代码用于格式化输出以其更加美观,q里׃再说明?/p>

(?数组的数l?/h2>

如果数组的元素是引用数组的跟t句柄,那么可以创建数l的数组。同Ӟ每一l数l的长度可以不同Q即所谓的“锯齿Ş数组”。例如,用ABCDE来表C学生的成W{Q根据等U分l存储班内学生的姓名Q则可以创徏一个包?个元素的数组Q每个元素ؓ一个姓名数l(卛_W串数组Q?/p>

array<array<String ^>^>^ grades = gcnew array<array<String^>^>(5)

利用上面创徏的数l,然后可以创徏5个姓名数l了

grades[0] = gcnew array<String^>{"Louise", "Jack"};
grades[1] = gcnew array<String^>{"Bill", "Mary", "Ben", "Joan"};
grades[2] = gcnew array<String^>{"Jill", "Will", "Phil"};
grades[3] = gcnew array<String^>{"Ned", "Fred", "Ted", "Jed", "Ed"};
grades[4] = gcnew array<String^>{"Dan", "Ann"};

grades[n]讉Kgrades数组的第n个元素,而各元素为指向String^cd数组的句柄,因此上面的语句用于创ZString对象句柄的数l,q将创徏数组的地址赋值给了grades数组元素。同Ӟq些字符串数l的长度是不同的?/p>

上面的语句也可以用一个初始化语句来实?/p>

array<array<String^>^>^ grades = gcnew array<array<String^>^>
{
    gcnew array<String^>{"Louise", "Jack"},
    gcnew array<String^>{"Bill", "Maray", "Ben", "Joan"},
    gcnew array<String^>{"Jill", "Will", "Phil"},
    gcnew array<String^>{"Ned", "Fred", "Ted", "Jed", "Ed"},
    gcnew array<String^>{"Dan", "Ann"},
};

注意Q元素的初值必d在花括号里?/p>

- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::开?=>> [Ex4_16.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Ex4_16.cpp : main project file.
#include "stdafx.h"
using namespace System;

int main(array<System::String ^> ^args)
{
	array<array<String^>^>^ grades = gcnew array<array<String^>^>
		{
			gcnew array<String^>{"Louise", "Jack"},
			gcnew array<String^>{"Bill", "Maray", "Ben", "Joan"},
			gcnew array<String^>{"Jill", "Will", "Phil"},
			gcnew array<String^>{"Ned", "Fred", "Ted", "Jed", "Ed"},
			gcnew array<String^>{"Dan", "Ann"}
		};
	
	wchar_t gradeLetter = 'A';
	for each(array<String^>^ grade in grades)
	{
		Console::WriteLine(L"Students with Grade {0}:", gradeLetter++);
		for each(String^ student in grade)
			Console::Write("{0, 12}", student);
		Console::WriteLine();
	}
	return 0;
}
- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::l束==>> [Ex4_16.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

输出?/p>

Students with Grade A:
      Louise        Jack
Students with Grade B:
        Bill       Maray         Ben        Joan
Students with Grade C:
        Jill        Will        Phil
Students with Grade D:
         Ned        Fred         Ted         Jed          Ed
Students with Grade E:
         Dan         Ann


]]>C++/CLI学习入门(?:控制与@?/title><link>http://www.shnenglu.com/golq/archive/2009/06/27/88645.html</link><dc:creator>英勇的近卫军</dc:creator><author>英勇的近卫军</author><pubDate>Sat, 27 Jun 2009 08:46:00 GMT</pubDate><guid>http://www.shnenglu.com/golq/archive/2009/06/27/88645.html</guid><wfw:comment>http://www.shnenglu.com/golq/comments/88645.html</wfw:comment><comments>http://www.shnenglu.com/golq/archive/2009/06/27/88645.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/golq/comments/commentRss/88645.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/golq/services/trackbacks/88645.html</trackback:ping><description><![CDATA[<h1>一、基本控制结?/h1> <p style="text-indent: 24pt">ISO/ANSI C++中的控制与@环全部适用于C++/CLI。下例展CZC++/CLI控制台程序中的控制@环:</p> <h2><em><u>例子Q基本@环控?/u></em></h2> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:51a1b54f-086a-48f2-b1f6-4ee9a7947e98" class="wlWriterEditableSmartContent">- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::开?=>> [Ex3_15.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - </div><pre><span style="color: #008000">// Ex3_15.cpp : main project file.</span> #include "<span style="color: #8b0000">stdafx.h</span>" <span style="color: #0000ff">using</span> <span style="color: #0000ff">namespace</span> System; <span style="color: #0000ff">int</span> main(array<System::String ^> ^args) { wchar_t letter; Console::Write(L"<span style="color: #8b0000">Enter a letter:</span>"); letter = Console::Read(); <span style="color: #0000ff">if</span>(letter>='A') <span style="color: #0000ff">if</span>(letter<='Z') { Console::WriteLine(L"<span style="color: #8b0000">You entered a captial letter.</span>"); <span style="color: #0000ff">return</span> 0; } <span style="color: #0000ff">if</span>(letter>='a') <span style="color: #0000ff">if</span>(letter<='z') { Console::WriteLine(L"<span style="color: #8b0000">You entered a small letter.</span>"); <span style="color: #0000ff">return</span> 0; } Console::WriteLine(L"<span style="color: #8b0000">You did not enter a letter.</span>"); <span style="color: #0000ff">return</span> 0; }</pre> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:4fbddd37-75c5-4813-8c7b-a1940ab131d0" class="wlWriterEditableSmartContent">- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::l束==>> [Ex3_15.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - </div> <p style="text-indent: 24pt"> letter被声明ؓwchar_tcdQ映ؓC++/CLI中的System::CharcdQ它h一些特D的功能Q其中包括将字符代码转换为大写和写的函敎ͼChar::ToUpperQ)和Char::ToLower()Q被转换的函C为参数被传递给?</p><pre>wchar_t uppercaseLetter = Char::ToUpper(letter);</pre> <p style="text-indent: 24pt"> 此外q包括检字母是否大写或写的函?IsUpper()和IsLower()Q因此上例可改ؓ</p><pre>wchar_t letter; wchar_t upper; Console::Write(L"<span style="color: #8b0000">Enter a letter:</span>"); letter = Console::Read(); upper = Char::ToUpper(letter); <span style="color: #0000ff">if</span>(upper>='A' && upper<='Z') Console::WriteLine(L"<span style="color: #8b0000">You entered a {0} letter.</span>", Char::IsUpper(letter) ? "<span style="color: #8b0000">Capital</span>":"<span style="color: #8b0000">Small</span>"); <span style="color: #0000ff">else</span> Console::WriteLine(L"<span style="color: #8b0000">You entered a small letter.</span>");</pre> <p style="text-indent: 24pt"> Console::ReadKey()函数用于试按键Qƈ结果存储在ConsoleKeyInfocd象里。该cL3个可讉K属性用于帮助确定被按下的键是哪个或哪些键。属性Key识别被按下的键是哪个Q属性KeyChar是被按键的Unicode字符码,属性Modifiers表示Shift,Alt,Ctrl键的按位l合Q它是定义在System命名I间中的枚DcdConsoleModifiers的常量,包括Shift\Alt\Control?/p> <p style="text-indent: 24pt">应该注意的是Q在C++/CLI中枚丑ָ量在用作数g前必被昄的强制{换ؓ值类型(整数cdQ?/p> <h4></h4> <h2><em><u>例子Q用Console::ReadKey()函数</u></em></h2> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:67119a9f-0a48-4345-afc8-d63e2d656e32" class="wlWriterEditableSmartContent">- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::开?=>> [Ex3_16.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - </div><pre><span style="color: #008000">// Ex3_16.cpp : main project file.</span> #include "<span style="color: #8b0000">stdafx.h</span>" <span style="color: #0000ff">using</span> <span style="color: #0000ff">namespace</span> System; <span style="color: #0000ff">int</span> main(array<System::String ^> ^args) { ConsoleKeyInfo keyPress; Console::WriteLine(L"<span style="color: #8b0000">Press a key combination - press Escape to quit.</span>"); <span style="color: #0000ff">do</span>{ keyPress = Console::ReadKey(<span style="color: #0000ff">true</span>); Console::Write(L"<span style="color: #8b0000">You pressed</span>"); <span style="color: #0000ff">if</span>(safe_cast<<span style="color: #0000ff">int</span>>(keyPress.Modifiers)>0) Console::Write(L"<span style="color: #8b0000"> {0}</span>", keyPress.Modifiers); Console::WriteLine(L"<span style="color: #8b0000"> {0} which is the {1} character</span>", keyPress.Key, keyPress.KeyChar); }<span style="color: #0000ff">while</span>(keyPress.Key != ConsoleKey::Escape); <span style="color: #0000ff">return</span> 0; } </pre> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:7eb3432e-0ed1-45b8-a5b1-4f5130a6057e" class="wlWriterEditableSmartContent">- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::l束==>> [Ex3_16.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - </div> <p style="text-indent: 24pt"> 该程序的输入CZ如下Q?</p><pre>Press a key combination - press Escape to quit. You pressed Enter which is the character You pressed Spacebar which is the character You pressed Spacebar which is the character</pre> <p style="text-indent: 24pt"> 从输Z可以看出Q当不只一个键被按下时Q用一条语句就可以得到所有的键。这是因为Modifiers枚Dcd是用FlagsAttribute属性定义的Q该属性表明这U枚丄型是一l唯一的位标志。这使得该枚丄型的变量可以pq与在一L标志位组成,而Write()或WriteLine()函数可以识别q输出各标志位?</p> <h1>二、for each循环</h1> <p style="text-indent: 24pt"> 以例子开?/p> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:956e7ca7-a8a2-4ce9-b203-000336508821" class="wlWriterEditableSmartContent">- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::开?=>> [Ex3_17.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - </div><pre><span style="color: #008000">// Ex3_17.cpp : main project file.</span> #include "<span style="color: #8b0000">stdafx.h</span>" <span style="color: #0000ff">using</span> <span style="color: #0000ff">namespace</span> System; <span style="color: #0000ff">int</span> main(array<System::String ^> ^args) { <span style="color: #0000ff">int</span> volwels = 0; <span style="color: #0000ff">int</span> consonants = 0; String^ proverb = L"<span style="color: #8b0000">A nod is as good as a wink to a blind horse.</span>"; <span style="color: #0000ff">for</span> each(wchar_t ch in proverb) { <span style="color: #0000ff">if</span>(Char::IsLetter(ch)) { ch = Char::ToLower(ch); <span style="color: #0000ff">switch</span>(ch) { <span style="color: #0000ff">case</span> 'a': <span style="color: #0000ff">case</span> 'e': <span style="color: #0000ff">case</span> 'i': <span style="color: #0000ff">case</span> 'o': <span style="color: #0000ff">case</span> 'u': ++volwels; <span style="color: #0000ff">break</span>; <span style="color: #0000ff">default</span>: ++consonants; <span style="color: #0000ff">break</span>; } } } Console::WriteLine(proverb); Console::WriteLine(L"<span style="color: #8b0000">The proverb contains {0} volwels and {1} consonants.</span>", volwels, consonants); <span style="color: #0000ff">return</span> 0; } </pre> <div style="padding-bottom: 0px; margin: 0px; padding-left: 0px; padding-right: 0px; display: inline; float: none; padding-top: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:e6e492bc-0694-4a70-bf03-24eb0ef87923" class="wlWriterEditableSmartContent">- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::l束==>> [Ex3_17.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - </div> <p style="text-indent: 24pt"> 输出为:</p><pre>A nod is as good as a wink to a blind horse. The proverb contains 14 volwels <span style="color: #0000ff">and</span> 18 consanants. </pre> <p style="text-indent: 24pt"> 注意Q由于proverb字符串中的字W都是Unicode字符Q因此用wchar_tQ映ؓCharcdQ类型的变量来存储这些字W。变量ch为@环内的局部变量?/p><img src ="http://www.shnenglu.com/golq/aggbug/88645.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/golq/" target="_blank">英勇的近卫军</a> 2009-06-27 16:46 <a href="http://www.shnenglu.com/golq/archive/2009/06/27/88645.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++/CLI学习入门(一)Q基http://www.shnenglu.com/golq/archive/2009/06/27/88644.html英勇的近卫军英勇的近卫军Sat, 27 Jun 2009 08:27:00 GMThttp://www.shnenglu.com/golq/archive/2009/06/27/88644.htmlhttp://www.shnenglu.com/golq/comments/88644.htmlhttp://www.shnenglu.com/golq/archive/2009/06/27/88644.html#Feedback1http://www.shnenglu.com/golq/comments/commentRss/88644.htmlhttp://www.shnenglu.com/golq/services/trackbacks/88644.html从今日开始,前期学习《Visual C++ 2005入门l典》(Ivor Horton?清华大学出版Cև版)的相关笔记整理到随笔中,希望能和C++/CLI爱好者分享学习过E中的心得。文中主要内容和例子摘自原书相关章节Q如有R权,La或来信告知?/font>

相比于ISO/ANSI C++而言QC++/CLIq行了大量的扩充Qƈ且提供了大量的附加功能。主要包?

  • 在C++/CLIE序中,所有ISO/ANSI基本数据cd都可以用,但在一些特D的上下文环境中Q它们具有一些额外属性;
  • 在控制台E序中,C++/CLI寚w盘和命o行输出提供了自己的机Ӟ
  • C++/CLI中引入了safe_castq算W,保强制cd转换操作能够生成可检验的代码Q?/div>
  • C++/CLI提供了另外一U基于类的枚丑֊能,其灵zL超q了ISO/ANSI C++中的enum声明?/div>

一、基本数据类?/h1>

C++/CLI中包括了所有ISO/ASNI C++中的基本数据cdQ算术运也和本地C++完全一栗除此之外,C++/CLI中还定义?U整数类型,如表1所C:

?:C++/CLI新增基本数据cd

cd

字节

值域

long long

8

?9223372036854775808?223372036854775807

Unsigned long long

8

  ??8446744073709551615

指定long long数据cdӞ需要在整数数值后面加LL或小写字母llQ如

longlong big = 123456789LL;

指定unsinged long longcdӞ需要在整数数值后面加ULL或小写字母ullQ如

unsigned long long huge = 123456789LL;

在C++/CLI中,每一个ISO/ANSI C++基本cd名称都映到System命名I间中定义的值类cd。在C++/CLIE序中,ISO/ANSI C++基本cd名称都是CLI中对应值类cd的简略Ş式。表2l出了基本类型、占用内存以及对应的值类cd?/p>

?Q基本类型与CLI值类?/p>

基本cd

字节

CLI值类cd

bool
char
singed char
unsigned char
short
unsigned short
int
unsigned int
long
unsigned long
long long
unsigned long long
float
double
long double
wchar_t

1
1
1
1
2
2
4
4
4
4
8
8
4
8
8
2

System::Boolean
System::SByte
System::SByte
System::Byte
System::Int16
System::UInt16
System::Int32
System::UInt32
System::Int32
System::UInt32
System::Int64
System::UInt64
System::Single
System::Double
System::Double
System::Char

默认情况下,charcd被视为singed charQ因此其兌的值类cd为System::SByte。如果编译选项/JQ则char 默认为unsigned charQ此时关联ؓSystem::Byte。System为根命名I间名,C++/CLI的值类cd在这个空间中定义。此外SystemI间中还定义了许多其他类型,如表C字W串的Stringcd、精存储的十进制小数类型Decimal{等?

在C++/CLI中,兌的值类cd为基本类型添加了重要的附加功能。编译器在需要时Q将安排原g兌cd之间的自动{换,其中从原D{换ؓ兌cd成ؓ装箱(boxing)Q反之称为拆?unboxing)。根据上下文环境Q这些变量将表现为简单的值或者对象?

׃ISO/ANSI C++基本cd的名U是C++/CLIE序中值类cd名称的别名,所以原则上C++/CLI代码中可用Q何一U名U?/p>

int count = 10; 
double value = 2.5;

与下面的代码是等L

System::Int32 count = 10; 
System::Double value = 2.5;

上面2U代码是完全合法的,但应量使用基本cd名称Q如int和doubleQ而不是System::Int32和System::Double。这是因Z面描q的q种映射关系仅适用于Visual C++ 2005及以上版本的~译器,其他版本~译器未必实现这U映关pR?/p>

基本类型{换ؓ值类cd是C++/CLI的一个重要特征。在ISO/ANSI C++中基本类型与cȝ型完全不同,而在C++/CLI中,所有数据都以类cd的Ş式存储,包括值类型(存储在堆栈上Q和引用cdQ存储在堆上Q?U?/p>

例子QFruit CLR控制台项?/u>

在Visual Studio 2005中创建CLR Console Application目Q输入名UEx2_12Q将生成如下文g

// Ex2_12.cpp : main project file. 
#include "stdafx.h" 
using namespace System; 
int main(array<System::String ^> ^args) 
{ 
    Console::WriteLine(L"Hello World"); 
    return 0; 
}

main函数后的参数为命令行参数。然后按如下方式改写代码

- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::开?=>> [Ex_12.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Ex2_12.cpp : main project file. 
#include "stdafx.h" 
using namespace System; 
int main(array<System::String ^> ^args) 
{ 
    int apples, oranges; 
    int fruit; 

    apples = 5; 
    oranges = 6; 
    fruit = apples + oranges; 
    Console::WriteLine(L"\nOranges are not the only fruit ..."); 
    Console::Write(L"- and we have "); 
    Console::Write(fruit); 
    Console::Write(L" fruit in all.\n"); 

    return 0; 
}
- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::l束==>> [Ex_12.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

~译后执行得到如下输出:

Oranges are not the only fruit?- 
- and we have 11 fuit in all. 

与ISO/ANSI C++版本比较Q变量的cdint成为C++/CLIcdSystem::Int32。如果用System::Int32替换代码中的intQ然后重新编译运行,l果没有变化?/p>

WriteLine()函数为C++/CLI函数Q定义在System命名I间的ConsolecM。Console表示标准输入输出。Write()函数cȝ另一个输出函敎ͼ不会自动换行。下面专门讨论C++/CLI的控制台输入输出?    

二、控制台输出

C++/CLI中特有控制台格式化输出功能,例如可用下面的代码来输出字符串与变量混合文本?/p>

Console::WriteLine(L"There are {0} fruit.", fruit);

Console::WriteLine()的第一个参数是L”There are {0} fruit.”,其中{0}为格式化占位W,表示在此处插入第二个参数的|如果有更多需要插入的参数Q则该参数对应的占位W编Ll增加:{1}、{2}、{3}…。在W一个字W串参数中,~号的顺序可以颠倒,?

Console::WriteLine(L"There are {1} packages weighting {0} pounds", packageWeight, packageCount);

格式化占位符q可以控制显C的格式Q如{1:F2}表示W?个参数显C成?位小数的点敎ͼ冒号后的为格式规?/p>

Console::WriteLine(L"There are {0} packages weighting {1:F2} pounds ", packageCount, packageWeight);

输出?/p>

There are 25 packages weighting 7.50 pounds.       

一般说来,可以~写格式为{n,w:Axx}的格式规范,其中n为烦引|用于选择逗号后的W几个参敎ͼ A为单个字母,表示如何对变量格式化Qxx?个或2个数字,指定参数的精度;w为有W号整数Q表C可选的字段宽度范围Q如果w?Q则字段叛_齐,如果w?Q则左对齐。如果数值的位置数小于w指定的位|数Q则多出来的用空格填充,如果数值的位置数大于w指定的位|数Q则忽略w的限定:

Console::WriteLine(L"Packages: {0,3} Weight: {1,5nºF2} pounds ", packageCount, packageWeight);

输出为(下划U表C空格填充位Q:

Packages: _25 Weight: __7.50 pounds

可选的格式说明W如?所C?/p>

?Q格式说明符

格式说明W?/strong>

说明

C或c

把g币量输出

D或d

把整C为十q制D出。如果指定的_ֺ大于位数Q则在数值的坐标填充0

E或e

按照U学技术法输出点?/p>

F或f

把QҎ作ؓu####.##的定Ҏ输出

G或g

以最紧凑的Ş式输出,取决于是否指定了_ֺ|如果没有则适用默认_ֺ

N或n

把g为定点十q制D出,必要时以3位一l用逗号分隔

X或x

把整C为十六进制D出。根据X或xQ以大写或小写输出?/td>

例子Q计地毯h|演示CLR控制台程序的格式化输?/em>

- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::开?=>> [Ex_13.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Ex2_13.cpp : main project file.
#include "stdafx.h"
using namespace System;
int main(array<System::String ^> ^args)
{
	double carpetPriceSqYd = 27.95;
	double roomWidth = 13.5;			// in feet
	double roomLength = 24.75;			// in feet
	const int feetPerYard = 3;
	double roomWidthYard = roomWidth/feetPerYard;
	double roomLengthYard = roomLength/feetPerYard;
	double carpetPrice = roomWidthYard*roomLengthYard*carpetPriceSqYd;

	Console::WriteLine(L"Room is {0:F2} yards by {1:F2} yards",
		roomWidthYard, roomLengthYard);
	Console::WriteLine(L"Room area is {0:F2} square yards", 
		roomWidthYard*roomLengthYard);
	Console::WriteLine(L"Carpet price is ${0:F2}", carpetPrice);
	return 0;
}
- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::l束==>> [Ex_13.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

三、控制台输入

.Net Framework的控制台键盘输入功能有限Q可以适用Console::ReadLine()函数把整行输入作为字W串dQ或者用Console::Read()d单个字符Q还可以适用Console::ReadKey()d按键。ReadLine()的例子如下:

ReadLine()用于整行文本存入字W串中,按下Enter键时Q文本结束。变量line为String^型,表示String数据cd的引用,line为Console::ReadLine()函数d字符串的引用?/p>

String^ line = Console::ReadLine();

Read()用于逐字W的d输入数据Qƈ其转换成对应的数字倹{ReadKey的例子如下:

char ch = Console::Read();

ReadKey()用于d按键|q返回ConsoleKeyInfo对象Q该为对象定义在System命名I间中的值类型。参数true表示按键不在命o行上昄出来Qfalse则表C显C按键回显。按键对应的字符可用ConsoleKeyInfo对象的KeyChar得到?/p>

ConsoleKeyInfo keyPressed = Console::ReadKey(true);
Console::WriteLine(L"The key press corresponds to the character: {0}", keyPress.KeyChar);

管C++/CLI控制台程序中不能格式化输入,但输入一般都通过H口lg得到Q因此这仅仅是一个小~陷?/p>

四、强制类型{换safe_cast

在CLR环境中safe_cast用于昄的强制类型{换。safe_cast用于一U类型{换ؓ另一U类型,在不成功时能够抛出异常,因此在C++/CLI中用safe_cast是比较好的选择。其用法和static_cast一P

double value1 = 10.5; 
double value2 = 15.5; 
int whole_number = safe_cast<int>(value1) + safe_cast<int>(value2);

五、枚?/h1>

C++/CLI的枚举与ISO/ANSI C++有较大的区别。下例ؓC++/CLI中的一个枚丄型:该语句定义了一个枚丄型SuitQ该cd的变量只能被赋值枚丑֮义中的|且必ȝ枚Dcd名称限定枚D常数?/p>

enum class Suit {Clubs, Diamonds, Hearts, Spades};
Suit suit = Suit::Diamonds;

注意class关键字跟在enum之后。说明该枚Dcd为C++/CLIQ该关键字还表明在定义中规定的常? Clubs\Diamonds\Hearts\Spades都是cd象而非ISO/ANSI C++中的基本cdQ整型)倹{实际上Q默认情况下q些都是Int32cd的对象?/p>

׃C++/CLI枚D定义中的变量都是cd象,因此不能在函数内部定义?/p>

(一Q指定枚丑ָ量的cd

枚D中常量的cd可以是下表中M基本cdQ?/p>

short

int

long

long long

signed char

char

unsigned short

unsigned int

unsigned long

unsigned long long

unsigned char

bool

要指定一个枚丑ָ量的cdQ可以在枚Dcd名称之后写入帔Rcd名称Q要用冒号隔开Q,下例枚Dcd中的帔R为CharcdQ对应的基本cd为char。其中第一个常量默认情况下对应于代码?Q后面的依次递增?/p>

enum class Face:char { Ace,Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Jack,Queen,King};

(?指定枚D帔R的?/h2>

可以赋予枚Dcd定义中的一个或全部常数对应的|下例使得Ace获得1QTwo获得2Q其余依此类推,直到King=13?

enum class Face:char { Ace=1,Two,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Jack,Queen,King};

如果惌Ace获得最大|则可以如下定义:

enum class Face:Char { Ace=14,Two=2,Three,Four,Five,Six,Seven,Eight,Nine,Ten,Jack,Queen,King};

例子Q用枚丄?/u>

- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::开?=>> [Ex_14.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Ex2_14.cpp : main project file.
#include "stdafx.h"
using namespace System;

enum class Suit {Clubs, Diamonds, Hearts, Spades};

int main(array<System::String ^> ^args)
{
	Suit suit = Suit::Clubs;
	int value = safe_cast<int>(suit);

	Console::WriteLine(L"Suit is {0} and the value is {1}", suit, value);
	suit = Suit::Diamonds;
	value = safe_cast<int>(suit);
	Console::WriteLine(L"Suit is {0} and the value is {1}", suit, value);
	suit = Suit::Hearts;
	value = safe_cast<int>(suit);
	Console::WriteLine(L"Suit is {0} and the value is {1}", suit, value);
	suit = Suit::Spades;
	value = safe_cast<int>(suit);
	Console::WriteLine(L"Suit is {0} and the value is {1}", suit, value);
    return 0;
}
- - - - - - - - - - - - - - - - <<== 华丽的分割线 ::l束==>> [Ex_14.cpp] - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

该例子的输出?/p>

Suit is Clubs and the value is 0 
Suit is Diamonds and the value is 1 
Suit is Hearts and the value is 2 
Suit is Spades and the value is 3 

例子说明

  • Suit为枚丄型,不能在函数main()内部定义Q因此只能定义ؓ全局作用域内?
  • 必须用类型名USuit限定枚D帔RQ如Suit::ClubsQ否则编译器无法识别?
  • 变量suit的gؓcd象,要获取其值必LC的其转换成intcd?


]]>
2021ٸþþþþþþþ| 99þwww˳ɾƷ| ҹþþþ| Ʒþþþþһ| Ʒ99þþƷ| һAëƬѹۿþþƷ| avԾþþþa鶹| Ʒ99þþþþլ| ˳ɵӰվþ| ˾Ʒһþ| þۺϹapp| ޹˾þۺһ| þþþþŮ| Ʒݾþþþø99 | þ99Ʒ鶹լլ| պһƵþ| Vþþ| ޾Ʒھþ| һĻþ| þþƷ}Ů| þۺձ츾| þþþӰԺŮ| ޹þþþƷ| ޾Ʒһþ| Ʒ99þþƷ| þþƷվ| þѵľƷV| þþþþԻAV| ŷɫۺϾþþþþ| 99ȳ˾ƷȾþ669| 69Ʒþþþվ| ҹƷþþþþþ| 99þþƷѿ| 97þó˾Ʒվ| þٸ۲AVר| ŷ޹Ʒþ| þþƷƷʢۿ| 97㽶þҹɫƷ| 99þۺϹƷ| þɫۺҹž| þ99ֻƵƷ6|