闵棋 發表於 2015-7-30 22:00:00

深入理解C语言

<p>  语言只是一种工具,任何语言之间都是相通的,一通则百通,关键是要理解语言背后的思想,理解其思想,任何语言,拿来用就行了。语言没有好坏之分,任何语言既然存在自然有它存在的价值。</p>
<p>  在一个到处是OOP的年代,为何面向过程的C语言依然可以如此活跃?这主要得益于C语言本身的语言特性。C语言小巧灵活,而且还有一个直接与硬件打交道的指针的存在,所以它是嵌入式开发唯有的高级语言;正因为他的小巧灵活,我们可以用它来开发一系列的小工具,Unix/Linux就是由这些小工具组成的操作系统;同时用C语言可以开发高性能的应用程序。</p>
<p>1、数据类型。C是一门面向过程的语言,但它依旧可以实现大多数面向对象所能完成的工作。比如面向对象的三大特性:封装、继承、多态。</p>
<p>  <strong>封装:</strong>C中有一种复杂的数据结构叫做struct。struct是C里面的结构体。</p>
<p>  假如我们要对person进行封装,person可能包括姓名、性别、年龄、身高、体重等信息。我们就可以对它封装如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> Person{
    </span><span style="color: rgba(0, 0, 255, 1)">char</span> name[<span style="color: rgba(128, 0, 128, 1)">20</span>];<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">姓名</span>
    <span style="color: rgba(0, 0, 255, 1)">char</span> gender;    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">性别   </span>
    <span style="color: rgba(0, 0, 255, 1)">int</span> age;         <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">年龄</span>
    <span style="color: rgba(0, 0, 255, 1)">int</span> height;      <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">身高</span>
    <span style="color: rgba(0, 0, 255, 1)">int</span> weight;       <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">体重</span>
};</pre>
</div>
<p>  当我们要像OOP那样新建一个对象时,我们就可以:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">struct</span> Person p;</pre>
</div>
<p>  我们就可以直接对p进行赋值:</p>
<div class="cnblogs_code">
<pre>p.name = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">whc</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
p.gender </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">b</span><span style="color: rgba(128, 0, 0, 1)">'</span>;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">'b' = boy; 'g' = girl</span>
p.age = <span style="color: rgba(128, 0, 128, 1)">25</span><span style="color: rgba(0, 0, 0, 1)">;
p.height </span>= <span style="color: rgba(128, 0, 128, 1)">175</span><span style="color: rgba(0, 0, 0, 1)">;
p.weight </span>= <span style="color: rgba(128, 0, 128, 1)">65</span>;</pre>
</div>
<p>  <strong>继承:</strong>同样利用struct,我们来创建一个学生结构,同时继承结构体Person,如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> Student{
    </span><span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> Person p;
    </span><span style="color: rgba(0, 0, 255, 1)">char</span> number[<span style="color: rgba(128, 0, 128, 1)">20</span>]; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">学号</span>
    <span style="color: rgba(0, 0, 255, 1)">int</span> score;            <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">成绩</span>
};</pre>
</div>
<p>    对Student进行创建对象,并赋值:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> Student s;
s.p.name </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">whc</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
s.p.gender </span>= <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">b</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
s.p.age </span>= <span style="color: rgba(128, 0, 128, 1)">25</span><span style="color: rgba(0, 0, 0, 1)">;
s.p.height </span>= <span style="color: rgba(128, 0, 128, 1)">175</span><span style="color: rgba(0, 0, 0, 1)">;
s.p.weight </span>= <span style="color: rgba(128, 0, 128, 1)">65</span><span style="color: rgba(0, 0, 0, 1)">;
s.number </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">20150618</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
s.score </span>= <span style="color: rgba(128, 0, 128, 1)">90</span>;</pre>
</div>
<p>  <strong>多态:</strong>C中对于多态的实现可以借助函数指针来实现。为了简单起见,我们假设Person这个结构体中,只有一个函数指针。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> Person{
    </span><span style="color: rgba(0, 0, 255, 1)">void</span> (*print)(<span style="color: rgba(0, 0, 255, 1)">void</span> *<span style="color: rgba(0, 0, 0, 1)">p);
};

</span><span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> Student{
    </span><span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> Person p;
};</span></pre>
</div>
<p>  而Person和Student这两个结构体的print函数实现如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">void</span> printPerson(<span style="color: rgba(0, 0, 255, 1)">void</span> *<span style="color: rgba(0, 0, 0, 1)">person){
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(NULL ==<span style="color: rgba(0, 0, 0, 1)"> person)
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> ;
    </span><span style="color: rgba(0, 0, 255, 1)">struct</span> Person *p = (<span style="color: rgba(0, 0, 255, 1)">struct</span> Person *<span style="color: rgba(0, 0, 0, 1)">)person;
    printf(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">run in the person!!\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
}
</span><span style="color: rgba(0, 0, 255, 1)">void</span> printStudent(<span style="color: rgba(0, 0, 255, 1)">void</span> *<span style="color: rgba(0, 0, 0, 1)">person){
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(NULL ==<span style="color: rgba(0, 0, 0, 1)"> person)
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> ;
    </span><span style="color: rgba(0, 0, 255, 1)">struct</span> Person *p = (<span style="color: rgba(0, 0, 255, 1)">struct</span> Person *<span style="color: rgba(0, 0, 0, 1)">)person;
    printf(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">run in the student!!\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">);
}</span></pre>
</div>
<p>  我们写一个函数来调用他们:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">void</span> print(<span style="color: rgba(0, 0, 255, 1)">void</span> *<span style="color: rgba(0, 0, 0, 1)">person){
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(NULL ==<span style="color: rgba(0, 0, 0, 1)"> person)
      </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> ;
    </span><span style="color: rgba(0, 0, 255, 1)">struct</span> Person *p = (<span style="color: rgba(0, 0, 255, 1)">struct</span> Person *<span style="color: rgba(0, 0, 0, 1)">)person;
    p</span>-&gt;<span style="color: rgba(0, 0, 0, 1)">print(person);
}
</span><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> main(){
    </span><span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> Person person;
    </span><span style="color: rgba(0, 0, 255, 1)">struct</span><span style="color: rgba(0, 0, 0, 1)"> Student student;
    person.print </span>=<span style="color: rgba(0, 0, 0, 1)"> printPerson;
    student.p.print </span>=<span style="color: rgba(0, 0, 0, 1)"> printStudent;

    print(</span>&amp;person);    <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">实参为Person的对象</span>
    print(&amp;student);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">实参为Student的对象</span>

    <span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
}</span></pre>
</div>
<p>  他们的输出为:</p>
<p>  <img src="http://images0.cnblogs.com/blog2015/685406/201507/301949188459272.png"></p>
<p>  <strong>其实这个也不难理解,无论是Person还是Student,他们在内存中只有一个变量,就是那个函数指针,而void*表示任何类型的指针,当我们将它强制转换成struct Person*类型时,p-&gt;print指向的自然就是传入实参的print地址。</strong></p>
<p>2、 指针和内存管理</p>
<p>  无论问哪一个C工程狮:C语言中最容易出错的地方在哪?我们基本上会得到同一个答案,那就是指针和内存溢出。那么指针是什么,指针其实就是一个地址,这个地址可以是一个变量的地址,也可以是一个函数的地址,不管是什么,反正都是内存中的一个地址。</p>
<p>  例如有一个变量a,我们定义一个指针来保存变量a的地址:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">int</span> a = <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">int</span> *p = &amp;a;</pre>
</div>
<p>  如果是一个函数呢?我们定义一个函数,然后用一个函数指针来保存这个函数地址:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">int</span> min(<span style="color: rgba(0, 0, 255, 1)">int</span> a,<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> b){
</span><span style="color: rgba(0, 0, 255, 1)">return</span> a&lt;b?<span style="color: rgba(0, 0, 0, 1)">a:b;
}

</span><span style="color: rgba(0, 0, 255, 1)">int</span> (*f)(<span style="color: rgba(0, 0, 255, 1)">int</span>,<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)">);
f </span>= min;</pre>
</div>
<p>  可能我们有时候会想,难道我们只能先定义一个变量或者函数,然后把它的地址给指针么?不能直接使用指针,或者直接给指针赋一个常量么?首先,我们不知道内存中哪些是可用的地址,哪些是不可用的,每当我们定义一个指针时,这个指针指向的是一个未定义的内存,这个就是传说中的野指针。如果我们给这个指针所指向的内存赋值,就有可能覆盖了一些很重要的数据,所以每当我们定义一个指针时,最好给它赋一个初始地址或者NULL;如果我们给一个指针赋常量,同样的道理。</p>
<p>  指针的类型要与变量的类型一致(如果我们不是故意要他们不一致),所谓类型,只是变量的一直表现形式,其实在内存中,他们不过是0101的二进制,当我们用32bits的原码表示时,它就是unsigned;当我们用32bits补码表示时,就是signed;当用浮点表示时就是float;当用更复杂的自定义表示时就是struct;用union可以很好的理解这些。</p>
<p>  现在我们来讲一下内存,这里我们只讨论用户内存区域:</p>
<p>  一般分为5个区域:</p>
<p>  (1)程序代码区:存放代码指令的地方</p>
<p>  (2)全局(静态)变量区:包括初始化、未初始化的全局变量和静态变量</p>
<p>  (3)字符常量区:存放一些字符串常量,在C语言里面,这个很容易与栈中定义的字符数组搞混,当我们定义如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> main(){
</span><span style="color: rgba(0, 0, 255, 1)">char</span> *str0 = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Hello World!</span><span style="color: rgba(128, 0, 0, 1)">"</span>;   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">字符常量区</span>
<span style="color: rgba(0, 0, 255, 1)">char</span>   str1[] = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Hello World!</span><span style="color: rgba(128, 0, 0, 1)">"</span>;   <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">栈区</span>
                        
<span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;            
}</span></pre>
</div>
<p>  str0所指向的字符串就是在字符常量区,但是str0本身的这个指针变量是在栈区的,这个变量存放的是字符常量区中"Hello World!"的首地址。</p>
<p>  str1是字符数组,所以str1中所存放的字符串是在栈区,这里利用的不过是字符数组初始化的一种形式,其实它可以写成如下形式:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">char</span> str1[] = {<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">H</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">e</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">l</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">l</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">o</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span> <span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">W</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">o</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">r</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">l</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">d</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">!</span><span style="color: rgba(128, 0, 0, 1)">'</span>,<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">\0</span><span style="color: rgba(128, 0, 0, 1)">'</span>};</pre>
</div>
<p>  (4)栈区:局部变量,形参,函数返回地址等,由系统来管理,在内存里面是由高地址往低地址生长,所以栈空间大小是有限的,当在栈中定义一个很大的数组或者使用很深的递归调用时,就有可能栈溢出。</p>
<p>  (5)堆区:由malloc、calloc、realloc函数分配的空间,由我们自己来管理,每次用完之后,必须用free释放内存,否则,就会产生内存泄漏,每次释放内存后,虽然不再占用着这块内存中,但是对应的指针依然指向这块区域,这个指针就是野指针,所以释放内存后,建议给指针赋NULL。如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> main(){
</span><span style="color: rgba(0, 0, 255, 1)">int</span> *p = (<span style="color: rgba(0, 0, 255, 1)">int</span>*)<span style="color: rgba(0, 0, 255, 1)">malloc</span>(<span style="color: rgba(128, 0, 128, 1)">100</span>*<span style="color: rgba(0, 0, 255, 1)">sizeof</span>(<span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)">));
</span><span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)">
    执行语句
</span><span style="color: rgba(0, 128, 0, 1)">*/</span>
<span style="color: rgba(0, 0, 255, 1)">free</span>(p);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">这时p依然指向那块内存,成了野指针</span>
p = NULL;<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">对p赋值NULL</span>
<span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
}</span></pre>
</div>
<p>3、C语言的I/O输入输出</p>
<p>  C语言本身并不带有输入输出的特性,所以它的所有I/O操作都是通过系统调用来实现。幸运的是C标准库,已经给我们封装好了一系列的I/O操作的函数。</p>
<p class="reader-word-layer reader-word-s1-3">  putchar&nbsp;():把变量中的一个字符常量输出到显示器屏幕上;&nbsp;</p>
<p class="reader-word-layer reader-word-s1-3">  getchar&nbsp;();从键盘上输入一个字符常量,此常量就是该函数的值;&nbsp;</p>
<p class="reader-word-layer reader-word-s1-3">  printf&nbsp;();把键盘中的各类数据,加以格式控制输出到显示器屏幕上;&nbsp;</p>
<p class="reader-word-layer reader-word-s1-3">  scanf&nbsp;&nbsp;&nbsp;();从键盘上输入各类数据,并存放到程序变量中;&nbsp;</p>
<p class="reader-word-layer reader-word-s1-3">  puts&nbsp;&nbsp;&nbsp;&nbsp;():把数组变量中的一个字符串常量输出到显示器屏幕上</p>
<p class="reader-word-layer reader-word-s1-3">  gets&nbsp;&nbsp;&nbsp;&nbsp;():从键盘上输入一个字符串常量并放到程序的数组中</p>
<p class="reader-word-layer reader-word-s1-3">  一些为对文件的操作,由于一切皆可看作是文件,标准输入,输出也可以当作文件来操作,文件描述符:标准输入(0)、标准输出(1)、标准错误(2)</p>
<p class="reader-word-layer reader-word-s1-3">  fputs();输出到文件</p>
<p class="reader-word-layer reader-word-s1-3">  fgets();从文件输入</p>
<p>  fscanf();格式化文件输入</p>
<p>  fprintf();格式化文件输出</p>
<p>  另外两个很重要的函数,当然还有他们的派生函数也是类似的</p>
<p class="reader-word-layer reader-word-s1-3">  sscanf();&nbsp;从一个字符串中提取各类数据。</p>
<p class="reader-word-layer reader-word-s1-3">  sprintf();&nbsp;把格式化的数据写入某个字符串</p>
<p>  这里不对每个函数进行详解,主要对<strong>格式化函数</strong>进行分析:</p>
<p>  (1)当我们要<strong>把一个字符串转换成一个整数</strong>或者<strong>把一个整数转换成一个字符串</strong>时,我们一般会想到atoi()或者itoa()(非标准函数),但是我们可以通过流来实现:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">int</span><span style="color: rgba(0, 0, 0, 1)"> main(){
    </span><span style="color: rgba(0, 0, 255, 1)">int</span> num = <span style="color: rgba(128, 0, 128, 1)">10</span><span style="color: rgba(0, 0, 0, 1)">;
    </span><span style="color: rgba(0, 0, 255, 1)">char</span> str[<span style="color: rgba(128, 0, 128, 1)">10</span>] = {<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">};
    sprintf(str,</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">%d</span><span style="color: rgba(128, 0, 0, 1)">"</span>,num); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">把int转换成char[]</span>
    num = <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
    sscanf(str,</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">%d</span><span style="color: rgba(128, 0, 0, 1)">"</span>,&amp;num);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">把字符串转换成int</span>
    printf(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">num:%d str:%s\n</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,num,str);

    </span><span style="color: rgba(0, 0, 255, 1)">return</span> <span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">;
}</span></pre>
</div>
<p>  输出结果如下:</p>
<p>  <img src="http://images0.cnblogs.com/blog2015/685406/201507/302155410794792.png"></p>
<p>  把字符串转与其它类型之间的转换:比如float,16进制,unsigned等都可以用流实现。</p>
<p>  (2)格式化函数中的<span style="color: rgba(255, 102, 0, 1)"><strong>正则表达式</strong></span></p>
<p>  所有的格式化函数都可以定制自己的扫描集&nbsp;%、%、%[^abc]、%[^a-z],其中[]内是匹配的字符,^表示求反集。</p>
<p>  当我们要从标准输入输入一个可能带空格的字符串时,直接用scanf("%s",str);当读到空格时就返回,此时就可以使用正则表达式:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">char</span> str[<span style="color: rgba(128, 0, 128, 1)">100</span>] = {<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">};
scanf(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">%[^\n]</span><span style="color: rgba(128, 0, 0, 1)">"</span>,str);<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">直到遇到回车才写入</span></pre>
</div>
<p>  从标准输入中只要读小写字母a-z,遇到其它字符则返回:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">char</span> str[<span style="color: rgba(128, 0, 128, 1)">100</span>] = {<span style="color: rgba(128, 0, 128, 1)">0</span><span style="color: rgba(0, 0, 0, 1)">};
scanf(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">%</span><span style="color: rgba(128, 0, 0, 1)">"</span>,str);</pre>
</div>
<p>  其他格式化函数的用法相同,不一一举例。</p>
<p>4、总结</p>
<p>  从大一开始学习C语言也有四五年了,个人认为:C语言中最大的成功在于它的指针,但是也是最容易出错的,想要理解C,必须要掌握指针。虽然说,语言只是一门工具,但是这是基础。或许,你可以说,现在是JAVA的天下了,满大街都是招聘JAVA工程师;或者你可以说C太底层,现在都是OOP的时代了,谁还会用面向过程的......你们不要忘了操作系统是用什么写的?是C;C实现的nginx的并发量是C++实现的apache的几十倍。无论是什么编程语言,好好学,深入学就行,不要因为它今天流行就抛弃昨天所学的。</p>
<p>  <span style="color: rgba(255, 0, 0, 1)"><strong>版权所有,欢迎转载,转载请注明出处。</strong></span></p>

</div>
<div id="MySignature" role="contentinfo">
    每一个不曾起舞的日子里都是对以往生命的辜负!!<br><br>
来源:https://www.cnblogs.com/whc-uestc/p/4677414.html
頁: [1]
查看完整版本: 深入理解C语言