﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-geforceX的编程小苑-文章分类-算法/数据结构</title><link>http://www.cppblog.com/geforcex/category/429.html</link><description /><language>zh-cn</language><lastBuildDate>Thu, 22 May 2008 16:26:51 GMT</lastBuildDate><pubDate>Thu, 22 May 2008 16:26:51 GMT</pubDate><ttl>60</ttl><item><title>DES算法简介</title><link>http://www.cppblog.com/geforcex/articles/7762.html</link><dc:creator>geforceX</dc:creator><author>geforceX</author><pubDate>Sun, 28 May 2006 02:50:00 GMT</pubDate><guid>http://www.cppblog.com/geforcex/articles/7762.html</guid><wfw:comment>http://www.cppblog.com/geforcex/comments/7762.html</wfw:comment><comments>http://www.cppblog.com/geforcex/articles/7762.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/geforcex/comments/commentRss/7762.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/geforcex/services/trackbacks/7762.html</trackback:ping><description><![CDATA[
		<img height="10" src="http://www.infosecurity.org.cn/article/images/2005061301/200561320243474877801.gif" width="10" border="0" />
		<font color="#003399">
				<b>1 简介</b>
		</font>
		<br />  DES是Data Encryption Standard（数据加密标准）的缩写。它是由IBM公司研制的一种加密算法，美国国家标准局于1977年公布把它作为非机要部门使用的数据加密标准，二十年来，它一直活跃在国际保密通信的舞台上，扮演了十分重要的角色[10]。<br />  DES是一个分组加密算法，他以64位为分组对数据加密。同时DES也是一个对称算法：加密和解密用的是同一个算法。它的密匙长度是56位（因为每个第8位都用作奇偶校验），密匙可以是任意的56位的数，而且可以任意时候改变。其中有极少量的数被认为是弱密匙，但是很容易避开他们。所以保密性依赖于密钥。<br /><b><font color="#003399"><img height="10" src="http://www.infosecurity.org.cn/article/images/2005061301/200561320243474877801.gif" width="10" border="0" /> 2 算法框架[11]</font></b>：<br />  DES对64(bit)位的明文分组M进行操作，M经过一个初始置换IP置换成m0，将m0明文分成左半部分和右半部分m0=(L0,R0)，各32位长。然后进行16轮完全相同的运算，这些运算被称为函数f，在运算过程中数据与密匙结合。经过16轮后，左，右半部分合在一起经过一个末置换，这样就完成了[12]。<br />  在每一轮中，密匙位移位，然后再从密匙的56位中选出48位。通过一个扩展置换将数据的右半部分扩展成48位，并通过一个异或操作替代成新的32位数据，在将其置换换一次。这四步运算构成了函数f。然后，通过另一个异或运算，函数f的输出与左半部分结合，其结果成为新的右半部分，原来的右半部分成为新的左半部分。将该操作重复16次，就实现了。具体图4所示。<br /><br />     <img src="http://www.cppblog.com/images/cppblog_com/geforcex/275/r_200561320243475877802.jpg" /><br /><br />                               图4　DES算法框图<br /><br /><b><font color="#003399"><img height="10" src="http://www.infosecurity.org.cn/article/images/2005061301/200561320243474877801.gif" width="10" border="0" /> 3 DES解密</font></b><br />  在经过所有的代替、置换、异或盒循环之后，你也许认为解密算法与加密算法完全不同。恰恰相反，经过精心选择的各种操作，获得了一个非常有用的性质：加密和解密使用相同的算法。<br />DES加密和解密唯一的不同是密匙的次序相反。如果各轮加密密匙分别是K1,K2,K3….K16那么解密密匙就是K16,K15,K14…K1。<br /><b><font color="#003399"><img height="10" src="http://www.infosecurity.org.cn/article/images/2005061301/200561320243474877801.gif" width="10" border="0" /> 4 DES的几种工作方式</font></b><br />  <font color="#cc3300">第一种电子密本方式（ECB）</font><br />   将明文分成n个64比特分组，如果明文长度不是64比特的倍数，则在明文末尾填充适当数目的规定符号。对明文组用给定的密钥分别进行加密，行密文C=(C0,C1,……,Cn-1)其中Ci=DES(K,xi),i=0,1,…..,n-1。<br />  <font color="#cc3300">第二种密文分组链接方式（CBC）</font><br />   在CBC方式下，每个明文组xi在加密前与先一组密文按位模二加后，再送到DES加密，CBC方式克服了ECB方式报内组重的缺点，但由于明文组加密前与一组密文有关，因此前一组密文的错误会传播到下一组。<br />  <font color="#cc3300">第三种密文反馈方式（CFB），可用于序列密码</font><br />   明文X＝(x0,x1,……,xn-1)，其中xi由t个比特组成0<t≤64。cfb实际上将des作为一个密钥流发生器，在t比特密文的反馈下，每次输出t比特乱数对t比特明文进行加密。由于cfb是密文反馈，它对密文错误较敏感，t比特密文中只要有一个比特错误，就会导致连续数个t 比特出错。<br="">   <font color="#cc3300">第四种输出反馈方式（OFB），可用于序列密码</font><br />   与CFB唯一不同的是OFB是直接取DES输出的t个比特，而不是取密文的t个比特，其余都与CFB相同。但它取的是DES的输出，所以它克服了CFB的密文错误传播的缺点 </t≤64。cfb实际上将des作为一个密钥流发生器，在t比特密文的反馈下，每次输出t比特乱数对t比特明文进行加密。由于cfb是密文反馈，它对密文错误较敏感，t比特密文中只要有一个比特错误，就会导致连续数个t><img src ="http://www.cppblog.com/geforcex/aggbug/7762.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/geforcex/" target="_blank">geforceX</a> 2006-05-28 10:50 <a href="http://www.cppblog.com/geforcex/articles/7762.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>scanf()函数释疑（下）</title><link>http://www.cppblog.com/geforcex/articles/2135.html</link><dc:creator>geforceX</dc:creator><author>geforceX</author><pubDate>Mon, 26 Dec 2005 09:13:00 GMT</pubDate><guid>http://www.cppblog.com/geforcex/articles/2135.html</guid><wfw:comment>http://www.cppblog.com/geforcex/comments/2135.html</wfw:comment><comments>http://www.cppblog.com/geforcex/articles/2135.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/geforcex/comments/commentRss/2135.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/geforcex/services/trackbacks/2135.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;在上篇我已经表达了两个观点，这里再重申一次：1。本文仅对scanf()函数控制串运用进行探讨，本文所有例程并不构成编程建议。2。凡事要亲力而为，不同平台不同编译器，可能会有不同结果。本文所有例程均在WIN-TC+windows Me下调试。
<P><FONT face=黑体 size=3>四、scanf()函数控制串运用出现的常见错误及对策技巧</FONT></P>
<P><FONT face=楷体_GB2312 size=4>问题一：&nbsp;&nbsp; 程序编译通过，但运行错误提示如下：<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scanf : floating point formats not linked<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Abnormal program termination</FONT> </P>
<P>出错示例程序：</P>
<P>#include &lt;stdio.h&gt;<BR>int main(void)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;int i,j ;<BR>&nbsp;&nbsp;&nbsp;&nbsp;float s[3][3];<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;/*这里*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;for(i=0;i&lt;3;i++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;for(j=0;j&lt;3;j++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;scanf("%f",&amp;s[i][j]);</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;for(i=0;i&lt;3;i++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;for(j=0;j&lt;3;j++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;printf("%f",s[i][j]);<BR>}</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;这实际上是个与本文主题无关的问题，也是与scanf()函数无关，是编译器的问题。</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;原因很明确：没有链接浮点库。早期系统内存资源紧张，多维浮点数组占用内存量大（一维浮点数组就没有此问题），因此TC在编译时尽量不加入无关的部分，在没发现需要浮点转换程序时，就不在可执行程序中安装这个部分。而有时TC又不能正确识别实际上确实需要做浮点转换，因此就会出现上面错误。</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;解决的方法：告诉TC需要做浮点数的输入转换。将以下语句加入上面程序中标有/*这里*/处。</P>
<P>方法一:&nbsp;&nbsp;float c;<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scanf("%f",&amp;c);</P>
<P>方法二:&nbsp;&nbsp;float c,*t<FONT color=#ff0000>;//此处手误，现已更</FONT><FONT color=#f70909>正&amp;t===》*t;</FONT></P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t=&amp;c;<BR>.....</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;也就是说，编译器只要有浮点转换的线索，TC就会把浮点转换连上,所以一般大一点的程序里的就会有浮点变量反而没有此问题。<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;但问题到此并没结束，我在上面有句“一维浮点数组就没有此问题”，那么我们来看看这样行不行：</P>
<P>#include &lt;stdio.h&gt;<BR>int main(void)<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;int i,j ;<BR>&nbsp;&nbsp;&nbsp;&nbsp;float s[3][3],*ptr;<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;ptr=&amp;s[0][0];<BR>&nbsp;&nbsp; <BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;for(i=0;i&lt;3;i++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;for(j=0;j&lt;3;j++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;scanf("%f",ptr+i*3+j);</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;for(i=0;i&lt;3;i++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;for(j=0;j&lt;3;j++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;printf("%7.2f\n",s[i][j]);<BR>}</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;这样我们就把多维浮点数组降为一维浮点数组来处理，调试一下，程序运行正常。这说明TC编译器仅在处理多维浮点数组（结构体）有此“未链接浮点库”的问题。</P>
<P><FONT face=楷体_GB2312 size=4>问题二：scanf()函数不能正确接受有空格的字符串？如: I love you!</FONT></P>
<P><BR>#include &lt;stdio.h&gt;<BR>int main()<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;char str[80];<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;scanf("%s",str);<BR>&nbsp;&nbsp;&nbsp;&nbsp;printf("%s",str);</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<BR>}</P>
<P>输入：I live you!<BR>输出：I</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scanf()函数接收输入数据时，遇以下情况结束一个数据的输入：（不是结束该scanf函数，scanf函数仅在每一个数据域均有数据，并按回车后结束）。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;① 遇空格、“回车”、“跳格”键。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;② 遇宽度结束。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;③ 遇非法输入。</P>
<P>所以，上述程序并不能达到预期目的，scanf()扫描到"I"后面的空格就认为对str的赋值结束，并忽略后面的"love you!".这里要注意是"love you!"还在<FONT color=#0909f7>键盘缓冲区</FONT><FONT color=#ff0000>（关于这个问题，网上我所见的说法都是如此，但是，我经过调试发现，其实这时缓冲区字符串首尾指针已经相等了，也就是说缓冲区清空了，scanf()函数应该只是扫描stdin流，这个残存信息是在stdin中)</FONT>。我们改动一下上面的程序来验证一下：</P>
<P>#include &lt;stdio.h&gt;<BR>int main()<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;char str[80];<BR>&nbsp;&nbsp;&nbsp;&nbsp;char str1[80];<BR>&nbsp;&nbsp;&nbsp;&nbsp;char str2[80];<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp;scanf("%s",str);/*此处输入:I love you!&nbsp;&nbsp;*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;printf("%s",str);<BR>&nbsp;&nbsp;&nbsp;&nbsp;sleep(5);/*这里等待5秒,告诉你程序运行到什么地方*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;scanf("%s",str1);/*这两句无需你再输入,是对键盘盘缓冲区再扫描&nbsp;&nbsp; */<BR>&nbsp;&nbsp;&nbsp;&nbsp;scanf("%s",str2);/*这两句无需你再输入,是对键盘盘缓冲区再扫描&nbsp;&nbsp;&nbsp;&nbsp;*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;printf("\n%s",str1);<BR>&nbsp;&nbsp;&nbsp;&nbsp;printf("\n%s",str2);<BR>&nbsp;&nbsp;&nbsp;&nbsp;return 0;<BR>}</P>
<P>输入：I love you!<BR>输出：I<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;love<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;you!</P>
<P>好了，原因知道了，那么scanf()函数能不能完成这个任务？回答是：能！别忘了scanf()函数还有一个 %[] 格式控制符（如果对%[]不了解的请查看本文的上篇）,请看下面的程序：</P>
<P>#include "stdio.h"<BR>int main()<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;char string[50];<BR>&nbsp;&nbsp;&nbsp;&nbsp;<BR>&nbsp;&nbsp;&nbsp;&nbsp; /*scanf("%s",string);不能接收空格符*/<BR>&nbsp;&nbsp;&nbsp;&nbsp; scanf("%[^\n]",string);<BR>&nbsp;&nbsp;&nbsp;&nbsp; printf("%s\n",string);<BR>&nbsp;&nbsp;&nbsp;&nbsp; return 0;<BR>}</P>
<P><FONT face=楷体_GB2312 size=4>问题三：键盘缓冲区残余信息问题</FONT></P>
<P><BR>#include &lt;stdio.h&gt;<BR>int main()<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;int a;<BR>&nbsp;&nbsp;&nbsp;&nbsp;char c;</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;do<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scanf("%d",&amp;a);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scanf("%c",&amp;c);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("a=%d&nbsp;&nbsp;&nbsp;&nbsp; c=%c\n",a,c);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*printf("c=%d\n",c);*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;}while(c!='N');<BR>}</P>
<P>&nbsp;&nbsp; scanf("%c",&amp;c);这句不能正常接收字符,什么原因呢？我们用printf("c=%d\n",c);将C用int表示出来，启用printf("c=%d\n",c);这一句，看看scanf()函数赋给C到底是什么，结果是 c=10 ,ASCII值为10是什么？换行即\n.对了，我们每击打一下"Enter"键，向键盘缓冲区发去一个“回车”(\r),一个“换行"(\n),在这里\r被scanf()函数处理掉了（姑且这么认为吧^_^），而\n被scanf()函数“错误”地赋给了c.</P>
<P>解决办法：可以在两个scanf()函数之后加个fflush(stdin);，还有加getch(); getchar();也可以，但是要视具体scanf()语句加那个，这里就不分析了，读者自己去摸索吧。但是加fflush(stdin);不管什么情况都可行。</P>
<P>函数名: fflush <BR>功&nbsp;&nbsp;能: 清除一个流 <BR>用&nbsp;&nbsp;法: int fflush(FILE *stream); </P>
<P>#include &lt;stdio.h&gt;<BR>int main()<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;int a;<BR>&nbsp;&nbsp;&nbsp;&nbsp;char c;</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;do<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scanf("%d",&amp;a);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fflush(stdin);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scanf("%c",&amp;c);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;fflush(stdin);<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;printf("a=%d&nbsp;&nbsp;&nbsp;&nbsp; c=%c\n",a,c);</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;}while(c!='N');<BR>}&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</P>
<P>这里再给一个用“空格符”来处理缓冲区残余信息的示例：</P>
<P>运行出错的程序：</P>
<P>#include &lt;stdio.h&gt;<BR>int main()<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;int i;<BR>&nbsp;&nbsp;&nbsp;&nbsp;char j;<BR>&nbsp;&nbsp;&nbsp;&nbsp;for(i = 0;i &lt; 10;i++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scanf("%c",&amp;j);/*这里%前没有空格*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}</P>
<P>使用了空格控制符后：</P>
<P>#include &lt;stdio.h&gt;<BR>int main()<BR>{<BR>&nbsp;&nbsp;&nbsp;&nbsp;int i;<BR>&nbsp;&nbsp;&nbsp;&nbsp;char j;<BR>&nbsp;&nbsp;&nbsp;&nbsp;for(i = 0;i &lt; 10;i++)<BR>&nbsp;&nbsp;&nbsp;&nbsp;{<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scanf(" %c",&amp;j);/*注意这里%前有个空格*/<BR>&nbsp;&nbsp;&nbsp;&nbsp;}<BR>}</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;可以运行看看两个程序有什么不同。</P>
<P><FONT face=楷体_GB2312 size=4>问题四&nbsp;&nbsp; 如何处理scanf()函数误输入造成程序死锁或出错？</FONT></P>
<P>#include &lt;stdio.h&gt;<BR>int main()<BR>{<BR>&nbsp;&nbsp;int a,b,c;&nbsp;&nbsp;/*计算a+b*/</P>
<P>&nbsp;&nbsp;scanf("%d,%d",&amp;a,&amp;b);<BR>&nbsp;&nbsp;c=a+b;<BR>&nbsp;&nbsp;printf("%d+%d=%d",a,b,c);<BR>}</P>
<P>如上程序，如果正确输入a,b的值，那么没什么问题，但是，你不能保证使用者每一次都能正确输入，一旦输入了错误的类型，你的程序不是死锁，就是得到一个错误的结果,呵呵，这可能所有人都遇到过的问题吧？</P>
<P>解决方法：scanf()函数执行成功时的返回值是成功读取的变量数,也就是说，你这个scanf()函数有几个变量，如果scanf()函数全部正常读取，它就返回几。但这里还要注意另一个问题，如果输入了非法数据，键盘缓冲区就可能还个有残余信息问题。</P>
<P>正确的例程：</P>
<P>#include &lt;stdio.h&gt;<BR>int main()<BR>{<BR>&nbsp;&nbsp;int a,b,c;&nbsp;&nbsp;/*计算a+b*/</P>
<P>&nbsp;&nbsp;while(scanf("%d,%d",&amp;a,&amp;b)!=2)fflush(stdin);<BR>&nbsp;&nbsp;c=a+b;<BR>&nbsp;&nbsp;printf("%d+%d=%d",a,b,c);<BR>}</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;就此结束此文吧,最后还得照例谦虚几句,本人水平有限(的的确确有限^_^,这到是真话),谬误难免还望达人指点一二,在下在此谢过了.<BR>(全文完)</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;knocker&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;2004.10.21</P><img src ="http://www.cppblog.com/geforcex/aggbug/2135.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/geforcex/" target="_blank">geforceX</a> 2005-12-26 17:13 <a href="http://www.cppblog.com/geforcex/articles/2135.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>scanf()函数释疑（上）</title><link>http://www.cppblog.com/geforcex/articles/2134.html</link><dc:creator>geforceX</dc:creator><author>geforceX</author><pubDate>Mon, 26 Dec 2005 09:11:00 GMT</pubDate><guid>http://www.cppblog.com/geforcex/articles/2134.html</guid><wfw:comment>http://www.cppblog.com/geforcex/comments/2134.html</wfw:comment><comments>http://www.cppblog.com/geforcex/articles/2134.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/geforcex/comments/commentRss/2134.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/geforcex/services/trackbacks/2134.html</trackback:ping><description><![CDATA[<P><FONT face=黑体 size=3>一、序言</FONT>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</P>
<P>&nbsp;&nbsp;&nbsp;&nbsp;scanf()函数是所有C语言学习者在学习C语言过程中所遇到的第二个函数（第一个函数是printf(),Brian W.Kerninghan &amp; Dennis M.Ritchie的“hello,world”程序基本上是所有的C语言学习者第一个范例），所以scanf()函数应当是C学习者能熟练运用的一个函数，但有很多初学者对此函数不能很好的运用，在实际编程中错误使用scanf()函数，导至程序产生某种错误不能正常运行，以至产生“scanf()函数有BUG”，“scanf()函数无用论”等等错误观点。<BR>&nbsp;&nbsp;&nbsp;&nbsp;本文结合笔者在编程实践中及论坛上网友所遇到的问题作一释疑，但笔者水平有限（菜鸟级），难免有谬误之处，还望达人指点一二。（Email:knocker.k@126.com)<BR>&nbsp;&nbsp;&nbsp;&nbsp;本文分上，下两篇讲述了C语言中的scanf()函数的用法，重点阐述使用scanf()函数过程中出现的常见错误及对策。当然，文中某些解决方法，均可以采用其他函数和方法来更好地解决，但本文仅限讨论scanf()函数本身。<BR>&nbsp;&nbsp;&nbsp;&nbsp;上篇，详细介绍了scanf()函数控制串的构成。下篇，用实际例程介绍scanf()函数控制串运用出现的常见错误及对策技巧。</P>
<P><FONT face=黑体 size=4>二、scanf()函数的控制串</FONT></P>
<P>函数名: scanf <BR>功&nbsp;&nbsp;能: 执行格式化输入 <BR>用&nbsp;&nbsp;法: int scanf(char *format[,argument,...]);</P>
<P>scanf()函数是通用终端格式化输入函数，它从标准输入设备(键盘) 读取输入的信息。可以读入任何固有类型的数据并自动把数值变换成适当的机内格式。</P>
<P>其调用格式为:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scanf("&lt;格式化字符串&gt;"，&lt;地址表&gt;);</P>
<P>scanf()函数返回成功赋值的数据项数，出错时则返回EOF。</P>
<P>其控制串由三类字符构成：</P>
<P>1。格式化说明符；<BR>2。空白符；<BR>3。非空白符；</P>
<P><BR>（A）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;格式化说明符</P>
<P><BR>格式字符&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 说明</P>
<P>%a&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 读入一个浮点值(仅C99有效) <BR>%A&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 同上<BR>%c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 读入一个字符<BR>%d&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 读入十进制整数<BR>%i&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 读入十进制，八进制，十六进制整数<BR>%o&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 读入八进制整数<BR>%x&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 读入十六进制整数<BR>%X&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 同上<BR>%c&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 读入一个字符<BR>%s&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 读入一个字符串<BR>%f&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 读入一个浮点数<BR>%F&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 同上<BR>%e&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 同上<BR>%E&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 同上<BR>%g&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 同上<BR>%G&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 同上<BR>%p&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 读入一个指针<BR>%u&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 读入一个无符号十进制整数<BR>%n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 至此已读入值的等价字符数<BR>%[]&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;扫描字符集合<BR>%%&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 读%符号<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<BR>附加格式说明字符表</P>
<P>修饰符&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 说明</P>
<P>L/l 长度修饰符&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 输入"长"数据<BR>h 长度修饰符&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 输入"短"数据<BR>W 整型常数&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 指定输入数据所占宽度<BR>* 星号&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 空读一个数据 <BR>hh,ll同上h,l但仅对C99有效。</P>
<P><BR>（B）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 空白字符 </P>
<P>空白字符会使scanf()函数在读操作中略去输入中的一个或多个空白字符，空白符可以是space,tab,newline等等，直到第一个非空白符出现为止。</P>
<P>（C）&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;非空白字符 </P>
<P>一个非空白字符会使scanf()函数在读入时剔除掉与这个非空白字符相同的字符。 </P>
<P><BR>注：scanf()控制串知识就介绍到这里（应该比较齐全了^_^)，如有遗漏下次补上。下面将结合实际例程，一一阐述.</P>
<P><FONT face=黑体 size=4>三、scanf()函数的控制串的使用</FONT></P>
<P>例1.</P>
<P>#include "stdio.h" <BR>int main(void) <BR>{ <BR>&nbsp;&nbsp;int a,b,c; <BR>&nbsp;&nbsp;<BR>&nbsp;&nbsp;scanf("%d%d%d",&amp;a,&amp;b,&amp;c);&nbsp;&nbsp;<BR>&nbsp;&nbsp;printf("%d,%d,%d\n",a,b,c);&nbsp;&nbsp;<BR><BR>&nbsp;&nbsp;return 0;<BR>}&nbsp;&nbsp; </P>
<P>运行时按如下方式输入三个值：</P>
<P>3□4□5　↙（输入a,b,c的值）</P>
<P>3，4，5 （printf输出的a，b，c的值）</P>
<P>&nbsp;&nbsp; （1） &amp;a、&amp;b、&amp;c中的&amp;是地址运算符，分别获得这三个变量的内存地址。<BR>&nbsp;&nbsp; （2） "%d%d%d"是按十进值格式输入三个数值。输入时，在两个数据之间可以用一个或多个空格、tab键、回车键分隔。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;以下是合法输入方式： <BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;① 3□□4□□□□5↙<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;② 3↙<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4□5↙<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;③ 3（tab键）4↙<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5↙</P>
<P><BR>例2.</P>
<P>#include "stdio.h" <BR>int main(void) <BR>{ <BR>&nbsp;&nbsp;int a,b,c; </P>
<P>&nbsp;&nbsp;scanf("%d,%d,%d",&amp;a,&amp;b,&amp;c);<BR>&nbsp;&nbsp;printf("%d,%d,%d\n",a,b,c);&nbsp;&nbsp;</P>
<P>&nbsp;&nbsp;return 0;<BR>}&nbsp;&nbsp; </P>
<P>运行时按如下方式输入三个值：</P>
<P>3,4,5　↙（输入a,b,c的值）</P>
<P>或者</P>
<P>3,□4,□5　↙（输入a,b,c的值）</P>
<P>3,□□□4,□5　↙（输入a,b,c的值）<BR>......<BR>都是合法的，但是","一定要跟在数字后面，如：<BR>3□，4,□5　↙就非法了，程序出错。（解决方法与原因后面讲）</P>
<P>再如：</P>
<P>1、sacnf()中的变量必须使用地址。</P>
<P>　　&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int a, b;<BR>scanf("%d%d",a,b); //错误<BR>scanf("%d%d",&amp;a,&amp;b); </P>
<P>2、scanf()的格式控制串可以使用其它非空白字符，但在输入时必须输入这些字符。</P>
<P>例：<BR>scanf("%d,%d",&amp;a,&amp;b); <BR>输入： 3，4 ↙（逗号与"%d,%d"中的逗号对应） <BR>scanf("a=%d,b=%d",&amp;a,&amp;b); <BR>输入： a=3，b=4 ↙（"a=","b=",逗号与"%d,%d"中的"a=","b="及逗号对应）</P>
<P><BR>3、在用"%c"输入时，空格和“转义字符”均作为有效字符。</P>
<P>例：<BR>scanf("%c%c%c",&amp;c1,&amp;c2,&amp;c3); <BR>输入：a□b□c↙ <BR>结果：a→c1，□→c2，b→c3 (其余被丢弃) </P>
<P><BR>scanf()函数接收输入数据时，遇以下情况结束一个数据的输入：（不是结束该scanf函数，scanf函数仅在每一个数据域均有数据，并按回车后结束）。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;① 遇空格、“回车”、“跳格”键。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;② 遇宽度结束。<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;③ 遇非法输入。</P>
<P><BR>&nbsp;&nbsp;&nbsp;&nbsp;上篇就写到这里吧，第三小节的例程"抄"自网上的一个教程（原因有二：一，可以少打不少字。二，□↙我不知道怎么打。^_^)，并删去其中的错误之处.这里也顺便提醒本文读者一句：凡事要亲力而为，即使是经典的书籍也不免有疏漏之处，所以，用编译器说话是最可靠的，是对是错请编译器告诉你。</P><img src ="http://www.cppblog.com/geforcex/aggbug/2134.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/geforcex/" target="_blank">geforceX</a> 2005-12-26 17:11 <a href="http://www.cppblog.com/geforcex/articles/2134.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>数组和指针总结</title><link>http://www.cppblog.com/geforcex/articles/1861.html</link><dc:creator>geforceX</dc:creator><author>geforceX</author><pubDate>Sun, 18 Dec 2005 13:08:00 GMT</pubDate><guid>http://www.cppblog.com/geforcex/articles/1861.html</guid><wfw:comment>http://www.cppblog.com/geforcex/comments/1861.html</wfw:comment><comments>http://www.cppblog.com/geforcex/articles/1861.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/geforcex/comments/commentRss/1861.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/geforcex/services/trackbacks/1861.html</trackback:ping><description><![CDATA[<P><FONT size=3>初学者往</FONT>往知道数组和指针之间有联系，但是具体的联系和限制却又搞不清楚，想当年我也如此，这里就将这方面的知识做个总结吧。</P>
<H2>1.定义</H2>
<H2><FONT size=3>定义数组时必须指定数组的类型和大小，<BR>定义指针时只需要指定类型。</FONT></H2>
<H2>2.存储空间的分配</H2>
<P><BR>对于数组，因为系统会按照你指定的大小为数组分配存储空间，这也是为什么数组必须指定大小的原因，如：char array[5] ; //系统会自动为其预留sizeof(char)*5个字节的连续内存（注意是连续的）。所以我们可以对array[0]...array[4]这五个变量随便访问（读和写）都不会有问题。<BR>对于指针，系统只会为所定义的指针变量分配空间，指针所指向的地点并未分配。举个例子： char *p ; 这里会为变量p分配空间，大小为4字节（32位机），但是*p（就是p指向的地方）却是随机的地方，这个地方系统也不为其分配空间。所以在这种情况下，你访问和给p赋值（p=...)都是允许的，但是访问*p或者给*p赋值都是错误的。我们要想使用*p必须先使其指向有效区域，这可以通过动态申请内存或者赋值（将知道的有效地点赋给它）来实现。<BR>提醒一下：对于指针，在使用时，不光所指向的区域能读写，指针变量本身也能读写，但是数组不同，数组名的不能写的（允许读）。为什么？因为指针变量p有存储空间，而数组名array是没有的。</P>
<H2>3.多级指针</H2>
<P><BR>一级指针，char *p ; //p为指向char类型的指针变量。</P>
<P>有了指针变量我们就可以定义任何类型的指针，可以随心所欲的用指针来访问任何类型的变量。但是有人发现了问题，使用这种定义，我们无法用指针来操纵指针类型，于是二级指针的定义被拿出来了。</P>
<P>二级指针就是指向指针的指针，用来操纵一指针变量。<BR>例：char **pp ; <BR>定义的pp为指向一个 指向一char变量的指针 的指针。<BR>我们可以将 pp指向到前面定义的p : pp = &amp;p ;<BR>现在很容易看清他们之间个关系：<BR>*pp就是访问pp指向的位置，访问的值当然就是p,<BR>**pp就是*(*pp)拉，当然等于*p.</P>
<P>注意 定义pp的时候，系统只为pp分配了空间，并未为*pp分配空间，后来能访问*pp是因为我们使用pp=&amp;p将pp指向了&amp;p这个已经分配好了的空间。</P>
<P>同理，为了控制二级指针于是有了三级指针，...</P>
<H2>4.多维数组</H2>
<P>char array[5];//定义了array为含有5个char元素的数组。<BR>二维数组的定义我就不多说了，相信大家知道得已经很详细了。我这里就说一说他们的名称吧。提醒一下：他提出的愿意是我们希望得到array类型的数组。<BR>char arrayMulti[3][5] ;<BR>前面说过数组名不是变量，那么它是怎么使用的呢？<BR>其实数组名只是在编译时刻编译器用来定位变量位置的一个标签。比如 array[3],那么编译器就认为是“标签+3”，你如果写 array[6]，那么编译器就认为是“标签+6”，这就是C不会给出数组越界错误的原因。那么arrayMulti是什么呢？细读二维数组的定义：我们定义的是一个数组的数组。我们写了这个定义，就意味着我们已经有了 char [5] 这种类型的数组，而现在我们要定义一个现有数组类型的数组arrayMulti 。并且在以后的程序中他会永远记得它的元素的类型是char [5]，所以你在访问他的元素arrayMulti[1]时，他知道这是一个char[5]的数组。同样二维数组也不检查越界，所以你写arrayMulti[2][5]不会有问题。<BR>提示：编译器不检查数组的越界，但会检查数组元素的类型，所以：<BR>对于array ,你给array[0]一个int型的值是不行的，因为他的元素是char类型；<BR>对于arrayMulti,你他的元素一个char[6]的值也是不行的（详细例子见“蜕化”）。</P>
<H2>5.数组名的蜕化</H2>
<P><BR>数组在作为函数参数时，数组名将蜕化为指针。C语言的书上是这么说的，我这里要说得是：这句话是不完全正确的！我们知道指针是占用内存的，但是这个蜕化而成的家伙是不占有内存的，仍然只是个标签。书上为什么这么说呢？书上的意思是说这家伙已经蜕化得不知道自己有几个元素了。举个例子：<BR>void fun(char array[5]);<BR>在编译时编译器会当成是:void fun(char *array);你在这个函数中使用sizeof(a)得到的值是4，而在定义char array[5]的函数中sizeof(array) = 5,说明确实已经蜕化为指针了。所以你写：<BR>char *pa = array ; //正确，指针到指针</P>
<P>数组名退化为指针，在这里强调一下：数组的元素类型仍然存在！这里要注意的是多维数组的情况。<BR>以2维数组为例：<BR>void fun2(char arrayMulti[3][5]);<BR>那么在函数fun2中，arrayMulti蜕化成的是char (*)[5],即：指向char[5]类型的指针，因为前面分析过arrayMulti的元素的类型是char[5]，所以在程序中：<BR>char **pm = arrayMulti ; //错误：从char (*)[5]到 char **的赋值<BR>char (*pm5)[5] ;<BR>pm5 = arrayMulti ; //正确。 </P>
<P><FONT size=5><STRONG>6.对元素的访问</STRONG><BR></FONT>数组名是一个标签，是一个记录地址的标签，在对元素的访问上所起的作用和指针一样，所以：<BR>int a[5];<BR>int *b;<BR>b=a;<BR>那么：<BR>a[1],b[1],*(a+1),*(b+1)都是允许的。<BR>更悬一点：因为其在这儿所起的作用仅仅是个标签而已（编译的时候就是让两者相加），所以：<BR>1[a],1[b],也是允许的。</P>
<P><FONT size=5><STRONG>7.取地址</STRONG></FONT><BR>对指针变量使用&amp;运算后得到的是指针变量的地址，那么数组名呢？<BR>他仅仅是个标签啊，根本就没地方存放。<BR>所以C语言中的规定是取数组地址的结果是：仍然是其本身。<BR>既 &amp;array 的值和 array一样。<BR>注意：值是一样，类型是不一样的。</P>
<P>------------------------</P>
<P>虽然数组名的确没有存储空间，但把&amp;a规定为跟a的地址值一样并不是这个原因。<BR>数组名是一个右值，本来不符合&amp;的语法的，但是，数组却是一个对象，对一个<BR>数组对象取地址是合理的，C标准委员会经过衡量，认为维护一个对象的完整性<BR>更重要，因此允许&amp;a，只不过，&amp;a的意义，并非对一个数组名取地址，而是对<BR>一个数组对象取地址。</P><img src ="http://www.cppblog.com/geforcex/aggbug/1861.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/geforcex/" target="_blank">geforceX</a> 2005-12-18 21:08 <a href="http://www.cppblog.com/geforcex/articles/1861.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>scanf()函数的用法和实践</title><link>http://www.cppblog.com/geforcex/articles/1327.html</link><dc:creator>geforceX</dc:creator><author>geforceX</author><pubDate>Fri, 25 Nov 2005 14:19:00 GMT</pubDate><guid>http://www.cppblog.com/geforcex/articles/1327.html</guid><wfw:comment>http://www.cppblog.com/geforcex/comments/1327.html</wfw:comment><comments>http://www.cppblog.com/geforcex/articles/1327.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/geforcex/comments/commentRss/1327.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/geforcex/services/trackbacks/1327.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;摘要：本文阐述了基于ANSI，Win 95，Win NT上的 C/C++语言中scanf()函数的用法，以及在实际使用中常见错误及对策。关键词：scanf()&nbsp;一、&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 序言在CSDN论坛的C/C++版块，我时...&nbsp;&nbsp;<a href='http://www.cppblog.com/geforcex/articles/1327.html'>阅读全文</a><img src ="http://www.cppblog.com/geforcex/aggbug/1327.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/geforcex/" target="_blank">geforceX</a> 2005-11-25 22:19 <a href="http://www.cppblog.com/geforcex/articles/1327.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>二叉树常用算法</title><link>http://www.cppblog.com/geforcex/articles/1325.html</link><dc:creator>geforceX</dc:creator><author>geforceX</author><pubDate>Fri, 25 Nov 2005 12:20:00 GMT</pubDate><guid>http://www.cppblog.com/geforcex/articles/1325.html</guid><wfw:comment>http://www.cppblog.com/geforcex/comments/1325.html</wfw:comment><comments>http://www.cppblog.com/geforcex/articles/1325.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/geforcex/comments/commentRss/1325.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/geforcex/services/trackbacks/1325.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;#include&nbsp;"stdio.h"#include&nbsp;"stdlib.h"typedef&nbsp;struct&nbsp;BiTNode{char&nbsp;data;struct&nbsp;BiTNode&nbsp;*lchild,*rchild;}BiTNode,*BiTree;BiTree&nbsp;CreateBiTree(){char&nbsp;ch...&nbsp;&nbsp;<a href='http://www.cppblog.com/geforcex/articles/1325.html'>阅读全文</a><img src ="http://www.cppblog.com/geforcex/aggbug/1325.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/geforcex/" target="_blank">geforceX</a> 2005-11-25 20:20 <a href="http://www.cppblog.com/geforcex/articles/1325.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>