欧美色欧美亚洲高清在线观看,国产特黄特色a级在线视频,国产一区视频一区欧美,亚洲成a 人在线观看中文

  1. <ul id="fwlom"></ul>

    <object id="fwlom"></object>

    <span id="fwlom"></span><dfn id="fwlom"></dfn>

      <object id="fwlom"></object>

      為C程序員準(zhǔn)備的0x10個最佳問題

      時間:2019-05-12 18:42:15下載本文作者:會員上傳
      簡介:寫寫幫文庫小編為你整理了多篇相關(guān)的《為C程序員準(zhǔn)備的0x10個最佳問題》,但愿對你工作學(xué)習(xí)有幫助,當(dāng)然你在寫寫幫文庫還可以找到更多《為C程序員準(zhǔn)備的0x10個最佳問題》。

      第一篇:為C程序員準(zhǔn)備的0x10個最佳問題

      為C程序員準(zhǔn)備的0x10個最佳問題

      (1)

      整個測試遵循以下的約定:

      u

      假定在所有的程序中必須的頭文件都已經(jīng)被正確包含。

      考慮如下的數(shù)據(jù)類型:

      u

      char 為1個字節(jié)

      u

      int為4個字節(jié)

      u

      long int為4個字節(jié)

      u

      float 為4個字節(jié)

      u

      double 為個8字節(jié)

      u

      long double 為 8個字節(jié)

      u

      指針為4個字節(jié)

      1.Consider the following program:

      #include

      staticjmp_bufbuf;

      main()

      {

      volatile int b;

      b =3;

      if(setjmp(buf)!=0)

      {

      printf(“%d ”, b);

      exit(0);

      }

      b=5;

      longjmp(buf , 1);

      }

      The output for this program is:

      (a)3(b)5(c)0(d)None of the above

      2.Consider the following program:

      main()

      {

      struct node

      {

      int a;

      int b;

      int c;

      };

      struct node s= { 3, 5,6 };

      struct node *pt = &s;

      printf(“%d” , *(int*)pt);

      }

      The output for this program is:(a)3(b)5(c)6(d)7

      3.Consider the following code segment:

      int foo(int x , int n)

      {

      intval;

      val =1;

      if(n>0)

      {

      if(n%2 == 1)val = val *x;

      val = val * foo(x*x , n/2);

      }

      returnval;}

      What function of x and n is compute by this code segment?

      (a)x^n(b)x*n(c)n^x(d)None of the above

      4.Consider the following program:

      main()

      {

      int a[5] = {1,2,3,4,5};

      int *ptr =(int*)(&a+1);

      printf(“%d %d” , *(a+1), *(ptr-1));

      }

      The output for this program is:

      (a)2 2(b)2 1(c)2 5(d)None of the above

      5.Consider the following program:

      void foo(int [][3]);

      main()

      {

      int a [3][3]= { { 1,2,3} , { 4,5,6},{7,8,9}};

      foo(a);

      printf(“%d” , a[2][1]);

      }

      void foo(int b[][3])

      {

      ++ b;

      b[1][1] =9;

      }

      The output for this program is:(a)8(b)9(c)7(d)None of the above

      6.Consider the following program:

      main()

      {

      int a, b,c, d;

      a=3;

      b=5;

      c=a,b;

      d=(a,b);

      printf(“c=%d” ,c);

      printf(“d=%d” ,d);

      }

      The output for this program is:

      (a)c=3 d=3(b)c=5 d=3(c)c=3 d=5(d)c=5 d=5

      7.Consider the following program:

      main()

      {

      int a[][3] = { 1,2,3 ,4,5,6};

      int(*ptr)[3] =a;

      printf(“%d %d ” ,(*ptr)[1],(*ptr)[2]);

      ++ptr;

      printf(“%d %d” ,(*ptr)[1],(*ptr)[2]);

      }

      The output for this program is:

      (a)2 3 5 6(b)2 3 4 5(c)4 5 0 0(d)None of the above

      8.Consider following function

      int *f1(void)

      {

      int x =10;

      return(&x);

      }

      int *f2(void){

      int*ptr;

      *ptr =10;

      returnptr;

      }

      int *f3(void)

      {

      int *ptr;

      ptr=(int*)malloc(sizeof(int));

      returnptr;

      }

      Which of the above three functions are likely to cause problem with pointers

      (a)Only f3(b)Only f1 and f3(c)Only f1 and f2(d)f1 , f2 ,f3

      9.Consider the following program:

      main()

      {

      int i=3;

      int j;

      j = sizeof(++i+ ++i);

      printf(“i=%d j=%d”, i ,j);

      }

      The output for this program is:

      (a)i=4 j=2(b)i=3 j=2(c)i=3 j=4(d)i=3 j=6

      10.Consider the following program: void f1(int *, int);

      void f2(int *, int);

      void(*p[2])(int *, int);

      main()

      {

      int a;

      int b;

      p[0] = f1;

      p[1] = f2;

      a=3;

      b=5;

      p[0](&a , b);

      printf(“%dt %dt” , a ,b);

      p[1](&a , b);

      printf(“%dt %dt” , a ,b);

      }

      void f1(int* p , int q)

      {

      inttmp;

      tmp =*p;

      *p = q;

      q= tmp;

      }

      void f2(int* p , int q)

      {

      inttmp;

      tmp =*p;

      *p = q;

      q= tmp;

      }

      The output for this program is:

      (a)5 5 5 5(b)3 5 3 5(c)5 3 5 3(d)3 3 3 3

      11.Consider the following program:

      void e(int);

      main()

      {

      int a;

      a=3;

      e(a);

      }

      void e(int n)

      {

      if(n>0)

      {

      e(--n);

      printf(“%d” , n);

      e(--n);

      }

      }

      The output for this program is:

      (a)0 1 2 0(b)0 1 2 1(c)1 2 0 1(d)0 2 1 1

      12.Consider following declaration

      typedefint(*test)(float * , float*)

      testtmp;

      type of tmp is

      (a)Pointer to function of having two arguments that is pointer to float(b)int(c)Pointer to function having two argument that is pointer to float and return int(d)None of the above

      13.Consider the following program:

      main()

      {

      char *p;

      char buf[10] ={ 1,2,3,4,5,6,9,8};

      p =(buf+1)[5];

      printf(“%d” , p);

      }

      The output for this program is:

      (a)5(b)6(c)9(d)None of the above

      14.Consider the following program:

      Void f(char**);

      main()

      {

      char * argv[] = { “ab” ,“cd” , “ef” ,“gh”, “ij” ,“kl” };

      f(argv);

      }

      void f(char **p)

      {

      char* t;

      t=(p+= sizeof(int))[-1];

      printf(“%s” , t);

      }

      The output for this program is:

      (a)ab(b)cd(c)ef(d)gh

      15.Consider the following program:

      #include

      int ripple(int ,...);

      main()

      {

      intnum;

      num = ripple(3, 5,7);

      printf(“ %d” , num);

      }

      int ripple(int n,...)

      {

      int i , j;

      int k;

      va_list p;

      k= 0;

      j = 1;

      va_start(p , n);

      for(;j

      {

      i = va_arg(p , int);

      for(;i;

      i &=i-1)

      ++k;

      }

      return k;

      }

      The output for this program is:

      (a)7(b)6(c)5(d)3

      16.Consider the following program:

      int counter(int i)

      {

      staticint count =0;

      count = count +i;

      return(count);

      }

      main()

      {

      int i , j;

      for(i=0;i <=5;i++)

      j = counter(i);}

      The value of j at the end of the execution of the this program is:

      (a)10(b)15(c)6(d)7

      (2)

      Answer With Detailed Explanation

      _____________________________________________________________

      Answer 1.The answer is(b)

      volatile variable isn't affected by the optimization.Its value after the longjump is the last value variable assumed.b last value is 5 hence 5 is printed.setjmp : Sets up for nonlocal goto /* setjmp.h*/

      Stores context information such as register values so that the lomgjmp function can return control to the statement following the one calling setjmp.Returns 0 when it is initially called.Lonjjmp: longjmp Performs nonlocal goto /* setjmp.h*/

      Transfers control to the statement where the call to setjmp(which initialized buf)was made.Execution continues at this point as if longjmp cannot return the value 0.A nonvolatile automatic variable might be changed by a call to longjmp.When you use setjmp and longjmp, the only automatic variables guaranteed to remain valid are those declared volatile.Note: Test program without volatile qualifier(result may very)

      Answer 2.The answer is(a)

      The members of structures have address in increasing order of their declaration.If a pointer to a structure is cast to the type of a pointer to its first member, the result refers to the first member.Answer 3.The answer is(a)

      Non recursive version of the program

      int what(int x , int n)

      {

      intval;

      int product;

      product =1;

      val =x;

      while(n>0)

      { if(n%2 == 1)

      product = product*val;

      n = n/2;

      val = val* val;

      }

      }

      /* Code raise a number(x)to a large power(n)using binary doubling strategy */ Algorithm description

      (while n>0)

      {

      if next most significant binary digit of n(power)is one

      then multiply accumulated product by current val ,reduce n(power)sequence by a factor of two using integer division.get next val by multiply current value of itself

      }

      Answer 4.The answer is(c)

      type of a is array of int type of &a is pointer to array of int Taking a pointer to the element one beyond the end of an array is sure to work.Answer 5.The answer is(b)

      Answer 6.The answer is(c)

      The comma separates the elements of a function argument list.The comma is also used as an operator in comma expressions.Mixing the two uses of comma is legal, but you must use parentheses to distinguish them.the left operand E1 is evaluated as a void expression, then E2 is evaluated to give the result and type of the comma expression.By recursion, the expression

      E1, E2,..., En

      results in the left-to-right evaluation of each Ei, with the value and type of En giving the result of the whole expression.c=a,b;/ *yields c=a* /

      d=(a,b);/* d =b */

      Answer 7.The answer is(a)

      /* ptr is pointer to array of 3 int */

      Answer 8.The answer is(c)

      f1 and f2 return address of local variable ,when function exit local variable disappeared

      Answer 9.The answer is(c)

      sizeof operator gives the number of bytes required to store an object of the type of its operand.The operands is either an expression, which is not evaluated((++i + ++ i)is not evaluated so i remain 3 and j is sizeofint that is 2)or a parenthesized type name.Answer 10.The answer is(a)

      void(*p[2])(int *, int);

      define array of pointer to function accept two argument that is pointer to int and return int.p[0] = f1;p[1] = f2 contain address of function.function name without parenthesis represent address of function Value and address of variable is passed to function only argument that is effected is a(address is passed).Because of call by value f1, f2 can noteffect b

      Answer 11.The answer is(a)

      Answer 12.The answer is(c)

      C provide a facility called typedef for creating new data type names, for example declaration

      typedef char string

      Makes the name string a synonym for int.The type string can be used in declaration, cast, etc, exactly the same way that the type int can be.Notice that the type being declared in a typedef appears in the position of a variable name not after the word typedef.Answer 13.The answer is(c)

      If the type of an expression is “array of T” for some type T, then the value of the expression is a pointer to the first object in the array, and the type of the expression is altered to “pointer to T” So(buf+1)[5] is equvalent to *(buf +6)or buf[6]

      Answer 14.The answer is(d)

      p+=sizeof(int)point to argv[2]

      (p+=sizeof(int))[-1] points to argv[1]

      Answer 15.The answer is(c)

      When we call ripple value of the first argument passed to ripple is collected in the n that is 3.va_start initialize p to point to first unnamed argument that is 5(first argument).Each call of va_arg return an argument and step p to the next argument.va_arg uses a type name to determine what type to return and how big a step to take Consider inner loop

      (;i;i&=i-1)k++ /* count number of 1 bit in i *

      in five number of 1 bits is(101)2 in seven number of 1 bits is(111)3 hence k return 5

      example

      let i= 9 = 1001

      i-1 = 1000

      (i-1)+1 = i

      1000

      +1 001

      The right most 1 bit of i has corresponding 0 bit in i-1 this way i & i-1, in a two complement number system will delete the right most 1 bit I(repeat until I become 0 gives number of 1 bits)

      Answer 16.The answer is(b)

      Static variable count remain in existence rather than coming and going each time function is called so first call counter(0)count =0 second call counter(1)count = 0+1;third call counter(2)count = 1+2;/* count = count +i */ fourth call counter(3)count = 3+3;fifth call counter(4)count = 6+4;sixth call counter(5)count = 10+5;

      本篇文章來源于站長資訊網(wǎng)http://

      第二篇:程序員C方向技能描述技能描述

      軟件程序員C方向技能描述

      初級

      軟件程序員初級資格主要培養(yǎng)學(xué)生的基本編程能力,應(yīng)具備以下技能:

      1、熟練掌握C程序設(shè)計(jì)的基礎(chǔ)知識、基本概念;掌握過程化程序設(shè)計(jì)的思想和編程技巧;理解算法的概念以及算法的表示方法,能使用C語言進(jìn)行簡單的程序設(shè)計(jì)。

      2、熟練掌握C++語言的基本語法規(guī)則,掌握常用數(shù)據(jù)類型、函數(shù)、類、對象等基礎(chǔ)知識;掌握面向?qū)ο蟪绦蛟O(shè)計(jì)的思想和編程技巧;能夠使用C++語言進(jìn)行簡單程序設(shè)計(jì)。

      3、掌握面向?qū)ο蟪绦蛟O(shè)計(jì)的基本方法,能進(jìn)行簡單的VC界面設(shè)計(jì)。

      4、掌握基本的數(shù)據(jù)庫知識,熟悉常見數(shù)據(jù)庫在編程語言中的使用。

      5、具有規(guī)范化、標(biāo)準(zhǔn)化的編程習(xí)慣和方法,符合軟件工程要求。

      中級

      中級程序員資格主要培養(yǎng)學(xué)生的基本編程能力、數(shù)據(jù)庫應(yīng)用能力,具備初級的軟件工程思想,應(yīng)具備以下技能。

      1、掌握過程化程序設(shè)計(jì)的思想和編程技巧;理解算法的概念以及算法的表示方法;能夠使用C語言按照需求進(jìn)行編碼實(shí)現(xiàn)。

      2、能夠深刻理解和領(lǐng)會面向?qū)ο蟪绦蛟O(shè)計(jì)的特點(diǎn)和風(fēng)格,掌握其方法和要領(lǐng)。

      3、掌握面向?qū)ο蟪绦蛟O(shè)計(jì)的基本方法,熟練使用VC進(jìn)行界面設(shè)計(jì)。

      4、掌握一定的數(shù)據(jù)庫理論知識,熟悉一種或兩種數(shù)據(jù)庫產(chǎn)品的使用,能夠進(jìn)行基本的數(shù)據(jù)庫設(shè)計(jì)與分析能力,熟悉編程語言與數(shù)據(jù)庫的連接和操作。

      5、具備基本的軟件工程思想,熟悉軟件生命周期和常用開發(fā)模型。

      6、具有規(guī)范化、標(biāo)準(zhǔn)化的編程習(xí)慣和方法,符合軟件工程要求。

      高級

      高級程序員資格主要培養(yǎng)學(xué)生的數(shù)據(jù)庫編程能力,具備系統(tǒng)的軟件工程理論知識,應(yīng)具備以下能力:

      1、熟練掌握過程化程序設(shè)計(jì)的思想和編程技巧;熟悉數(shù)據(jù)結(jié)構(gòu),能夠使用C語言能進(jìn)行較復(fù)雜的算法編程。

      2、深刻理解和領(lǐng)會面向?qū)ο蟪绦蛟O(shè)計(jì)的特點(diǎn)和風(fēng)格,具有較高的使用C++語言解決實(shí)際問題的能力。

      3、能正確運(yùn)用面向?qū)ο蟮乃季S方法分析問題和解決問題,能夠應(yīng)用MFC來解決實(shí)際復(fù)雜的問題,具有創(chuàng)新意識。

      4、掌握一定的數(shù)據(jù)庫理論知識,熟悉一種或兩種數(shù)據(jù)庫產(chǎn)品的使用,能夠進(jìn)行基本的數(shù)據(jù)庫設(shè)計(jì)。

      6、具備系統(tǒng)的軟件工程理論知識,有一定的軟件工程實(shí)踐經(jīng)驗(yàn),有較強(qiáng)的溝通能力和協(xié)調(diào)能力,能夠應(yīng)付軟件開發(fā)中出現(xiàn)的大多數(shù)問題。

      第三篇:C程序員精通Perl

      C程序員精通Perl

      本書幫助有C和C++背景的程序員學(xué)習(xí)和使用Perl語言。

      全書共17章,探討了Perl語言的所有知識要點(diǎn)。既包括C程序員所熟悉的變量、數(shù)據(jù)結(jié)構(gòu)、控制語句和子程序,又包括C中所沒有的報告編寫、文本表格操縱、CGI編程以及簡單數(shù)據(jù)庫接口,還講述了如何充分利用CPAN庫中廣泛的Perl模塊庫。

      本書可作為C和C++程序員學(xué)習(xí)Perl編程的參考書。對于Perl語言的初學(xué)者,本書可以幫助他們了解C和Perl之間可比較、可結(jié)合特性。

      第四篇:程序員實(shí)驗(yàn)室 - C 基礎(chǔ)教程

      C++ 基礎(chǔ)教程Beta 版

      原作:Juan Soulié 翻譯:Jing Xu(aqua)英文原版

      本教程根據(jù)Juan Soulie的英文版C++教程翻譯并改編。本版為最新校對版,尚未定稿。如有不明或錯誤之處,請參考英文原版,并敬請?jiān)诒菊玖粞灾刚?。版?quán)歸作者所有,歡迎鏈接,請勿轉(zhuǎn)載。

      本教程對C++語言進(jìn)行了深入淺出的介紹,從基礎(chǔ)知識到ANSI-C++標(biāo)準(zhǔn)的最新功能,內(nèi)容涵蓋了從數(shù)組,類等基本概念到多態(tài)、模板等高級概念。教程本著實(shí)用的原則,每一小節(jié)都結(jié)合了可以工作的程序?qū)嵗?,以便讀者從第一課開始就可以上手實(shí)習(xí)。

      本翻譯版本對許多C++概念中的關(guān)鍵詞保留了中英文對照,以便讀者增強(qiáng)理解,并方便日后閱讀英文原版教材 目錄

      1.簡介

      怎樣使用本教程 2.C++基礎(chǔ) Basics of C++ 1.C++程序結(jié)構(gòu)

      Structure of a program 2.變量和數(shù)據(jù)類型

      Variables and Data types 3.常量 Constants 4.操作符/運(yùn)算符 Operators 5.控制臺交互

      Communication through console 3.控制結(jié)構(gòu)和函數(shù)

      Control structures and Functions 1.控制結(jié)構(gòu)

      Control Structures 2.函數(shù)I Functions I 3.函數(shù)II Functions II 4.高級數(shù)據(jù)類型 Advanced Data 1.數(shù)組 Arrays 2.字符序列

      Character Sequences 3.指針 Pointers 4.動態(tài)內(nèi)存分配 Dynamic memory 5.數(shù)據(jù)結(jié)構(gòu) Data Structures 6.自定義數(shù)據(jù)類型

      User defined data types 5.面向?qū)ο缶幊?/p>

      Object-oriented Programming 1.類,構(gòu)造函數(shù)和析構(gòu)函數(shù),類的指針

      Classes.Constructors and Destructors.Pointers to classes.2.操作符重載,this,靜態(tài)成員

      Overloading Operators.this.Static members 3.類之間的關(guān)系

      Relationships between classes: friend.Inheritance 4.虛擬成員,抽象,多態(tài)

      Virtual Members.Abstraction.Polymorphism 6.C++高級

      Advanced concepts 1.模板 Templates 2.名空間 Namespaces 3.出錯處理

      Exception handling 4.類型轉(zhuǎn)換高級

      Advacned Class Type-casting 5.預(yù)處理指令

      Preprocessor Directives 7.C++ 標(biāo)準(zhǔn)函數(shù)庫 C++ Standard Library 1.文件的輸入輸出

      Input/Output with files C++基礎(chǔ)教程簡介 怎樣使用本教程 讀者范圍

      本教程面向所有希望學(xué)習(xí)C++語言的讀者。如果讀者有其他編程語言背景或計(jì)算機(jī)相關(guān)基本知識可以幫助更好的理解教程內(nèi)容,但這并非必須條件。

      對于C語言熟悉的讀者可將前三章(1.1 到 3.4)當(dāng)作復(fù)習(xí),因?yàn)檫@部分內(nèi)容主要介紹C++中的C部分。不過某些C++的語法與C還是有些差別,所以建議還是快速的讀一下這部分。第四章講述面向?qū)ο缶幊獭?/p>

      第五章主要介紹ANSI-C++標(biāo)準(zhǔn)中的新增的功能。

      本教程結(jié)構(gòu)

      教程共分6章,每章分若干小節(jié)。你可以直接從主目錄進(jìn)入任意小節(jié),并循每頁底部的鏈接向后瀏覽。

      很多小節(jié)含有一頁例題介紹該章節(jié)主要知識點(diǎn)的使用。建議在進(jìn)入下一章學(xué)習(xí)之前最好先閱讀這些例題,理解每行代碼。

      學(xué)習(xí)和練習(xí)一種編程語言的最好辦法是自己修改書中例題程序,設(shè)法在程序中增加新的功能。不要不敢修改這些例題程序,這正是學(xué)習(xí)的方法。

      兼容性備注

      ANSI-C++標(biāo)準(zhǔn)近幾年來被接受為國際標(biāo)準(zhǔn)。盡管C++語言從二十世紀(jì)80年代即存在,ANSI-C++在1997年才被發(fā)表,2003年又被修訂過。因此很多編譯器不支持ANSI-C++中的部分新功能,特別是那些在此標(biāo)準(zhǔn)發(fā)表前即被發(fā)布的編譯器。

      在本教程中,那些ANSI-C++中新增的而老一代C++編譯器大多不支持概念將備用如下標(biāo)志標(biāo)出:

      ANSI C++新增的概念

      同樣對于C和C++在實(shí)現(xiàn)上有明顯不同的概念,將備用如下標(biāo)志標(biāo)出: C 與 C++不同的地方 編譯器

      本教程中所有例題程序均為console程序(控制臺程序)。此類程序以文本形式與用戶交換信息,顯示結(jié)果。

      所有C++編譯器均支持console程序的編譯。要了解更多關(guān)于如何編譯的說明,請查詢你的編譯器用戶使用手冊。C++編譯器和開發(fā)環(huán)境推薦

      很多讀者詢問編譯器和開發(fā)環(huán)境的問題。除了常用的商用收費(fèi)的MS Visual Studio, VC++,Borland C++等工具外,還有很多免費(fèi)的工具也是很好用的。這里推薦兩種免費(fèi)的C++開發(fā)軟件:

      1、Eclipse的CDT開發(fā)工具,官方網(wǎng)站在http://004km.cn/cdt/

      2、開源工具Dev-C++和wxDev-C++ 第一章 C++ 基礎(chǔ)知識(Basics of C++)1.C++程序結(jié)構(gòu)

      Structure of a program 2.變量和數(shù)據(jù)類型

      Variables and Data types 3.常量 Constants 4.操作符/運(yùn)算符 Operators 5.控制臺交互

      Communication through console

      1.1 C++程序結(jié)構(gòu)(Structure of a program)

      下面我們從一個最簡單的程序入手看一個C++程序的組成結(jié)構(gòu)。// my first program in C++ #include using namespace std;

      int main(){ cout << “Hello World!”;return 0;} Hello World!上面左側(cè)顯示了我們的第一個程序的源代碼,代碼文件名稱為hellowworld.cpp。右邊顯示了程序被編譯執(zhí)行后的輸出結(jié)果。編輯和編譯一個程序的方法取決于你用的是什么編譯器,根據(jù)它是否有圖形化的界面及版本的不同,編譯方法也有可能不同,具體請參照你所使用的編譯器的使用說明。

      以上程序是多數(shù)初學(xué)者學(xué)會寫的第一個程序,它的運(yùn)行結(jié)果是在屏幕上打出”Hello World!”這句話。雖然它可能是C++可寫出的最簡單的程序之一,但其中已經(jīng)包含了每一個C++程序的基本組成結(jié)構(gòu)。下面我們就逐個分析其組成結(jié)構(gòu)的每一部分: // my first program in C++ 這是注釋行。所有以兩個斜線符號(//)開始的程序行都被認(rèn)為是注釋行,這些注釋行是程序員寫在程序源代碼內(nèi),用來對程序作簡單解釋或描述的,對程序本身的運(yùn)行不會產(chǎn)生影響。在本例中,這行注釋對本程序是什么做了一個簡要的描述。# include < iostream.h > 以#標(biāo)志開始的句子是預(yù)處理器的指示語句。它們不是可執(zhí)行代碼,只是對編譯器作出指示。在本例中這個句子# include < iostream.h > 告訴編譯器的預(yù)處理器將輸入輸出流的標(biāo)準(zhǔn)頭文件(iostream.h)包括在本程序中。這個頭文件包括了C++中定義的基本標(biāo)準(zhǔn)輸入-輸出程序庫的聲明。此處它被包括進(jìn)來是因?yàn)樵诒境绦虻暮竺娌糠种袑⒂玫剿墓δ?。using namespace std;C++標(biāo)準(zhǔn)函數(shù)庫的所有元素都被聲明在一個名空間中,這就是std名空間。因此為了能夠訪問它的功能,我們用這條語句來表達(dá)我們將使用標(biāo)準(zhǔn)名空間中定義的元素。這條語句在使用標(biāo)準(zhǔn)函數(shù)庫的C++程序中頻繁出現(xiàn),本教程中大部分代碼例子中也將用到它。int main()這一行為主函數(shù)(main function)的起始聲明。main function是所有C++程序的運(yùn)行的起始點(diǎn)。不管它是在代碼的開頭,結(jié)尾還是中間 – 此函數(shù)中的代碼總是在程序開始運(yùn)行時第一個被執(zhí)行。并且,由于同樣的原因,所有C++程序都必須有一個main function。main 后面跟了一對圓括號(),表示它是一個函數(shù)。C++中所有函數(shù)都跟有一對圓括號(),括號中可以有一些輸入?yún)?shù)。如例題中顯示,主函數(shù)(main function)的內(nèi)容緊跟在它的聲明之后,由花括號({})括起來。cout << “Hellow World!”;這個語句在本程序中最重要。cout 是C++中的標(biāo)準(zhǔn)輸出流(通常為控制臺,即屏幕),這句話把一串字符串(本例中為”Hello World”)插入輸出流(控制臺輸出)中。cout 在的聲明在頭文件iostream.h中,所以要想使用cout 必須將該頭文件包括在程序開始處。注意這個句子以分號(;)結(jié)尾。分號標(biāo)示了一個語句的結(jié)束,C++的每一個語句都必須以分號結(jié)尾。(C++ 程序員最常犯的錯誤之一就是忘記在語句末尾寫上分號)。return 0;返回語句(return)引起主函數(shù) main()執(zhí)行結(jié)束,并將該語句后面所跟代碼(在本例中為0)返回。這是在程序執(zhí)行沒有出現(xiàn)任何錯誤的情況下最常見的程序結(jié)束方式。在后面的例子中你會看到所有C++程序都以類似的語句結(jié)束。

      你可能注意到并不是程序中的所有的行都會被執(zhí)行。程序中可以有注釋行(以//開頭),有編譯器預(yù)處理器的指示行(以#開頭),然后有函數(shù)的聲明(本例中main函數(shù)),最后是程序語句(例如調(diào)用cout <<),最后這些語句行全部被括在主函數(shù)的花括號({})內(nèi)。本例中程序被寫在不同的行中以方便閱讀。其實(shí)這并不是必須的。例如,以下程序 int main(){ cout << “ Hello World ”;return 0;} 也可以被寫成:

      int main(){ cout << “ Hello World ”;return 0;} 以上兩段程序是完全相同的。

      在C++中,語句的分隔是以分號(;)為分隔符的。分行寫代碼只是為了更方便人閱讀。以下程序包含更多的語句: // my second program in C++ #include

      int main(){ cout << “Hello World!”;cout << “I'm a C++ program”;return 0;} Hello World!I'm a C++ program 在這個例子中,我們在兩個不同的語句中調(diào)用了cout << 函數(shù)兩次。再一次說明分行寫程序代碼只是為了我們閱讀方便,因?yàn)檫@個main 函數(shù)也可以被寫為以下形式而沒有任何問題: int main(){ cout << “ Hello World!”;cout << “ I'm to C++ program ”;return 0;}

      為方便起見,我們也可以把代碼分為更多的行來寫: int main(){ cout << “Hello World!”;cout << “I'm a C++ program”;return 0;} 它的運(yùn)行結(jié)果將和上面的例子完全一樣。

      這個規(guī)則對預(yù)處理器指示行(以#號開始的行)并不適用,因?yàn)樗鼈儾⒉皇钦嬲恼Z句。它們由預(yù)處理器讀取并忽略,并不會生成任何代碼。因此他們每一個必須單獨(dú)成行,末尾不需要分號(;)

      注釋(Comments)注釋(comments)是源代碼的一部分,但它們會被編譯器忽略。它們不會生成任何執(zhí)行代碼。使用注釋的目的只是使程序員可以在源程序中插入一些說明解釋性的內(nèi)容。C++ 支持兩中插入注釋的方法: // line comment /* block comment */ 第一種方法為行注釋,它告訴編譯器忽略從//開始至本行結(jié)束的任何內(nèi)容。第二種為塊注釋(段注釋),告訴編譯器忽略在/*符號和*/符號之間的所有內(nèi)容,可能包含多行內(nèi)容。在以下我們的第二個程序中,我們插入了更多的注釋。/* my second program in C++ with more comments */

      #include

      int main(){ cout << “Hello World!”;// says Hello World!cout << “I'm a C++ program”;// says I'm a C++ program return 0;} Hello World!I'm a C++ program

      如果你在源程序中插入了注釋而沒有用//符號或/*和*/符號,編譯器會把它們當(dāng)成C++的語句,那么在編譯時就會出現(xiàn)一個或多個錯誤信息。1.2 變量和數(shù)據(jù)類型(Variables and Data types)

      你可能覺得這個“Hellow World”程序用處不大。我們寫了好幾行代碼,編譯,然后執(zhí)行生成的程序只是為了在屏幕上看到一句話。的確,我們直接在屏幕上打出這句話會更快。但是編程并不僅限于在屏幕上打出文字這么簡單的工作。為了能夠進(jìn)一步寫出可以執(zhí)行更有用的任務(wù)的程序,我們需要引入變量(variable)這個的概念。

      讓我們設(shè)想這樣一個例子,我要求你在腦子里記住5這個數(shù)字,然后再記住2這個數(shù)字。你已經(jīng)存儲了兩個數(shù)值在你的記憶里?,F(xiàn)在我要求你在我說的第一個數(shù)值上加1,你應(yīng)該保留6(即5+1)和2在你的記憶里?,F(xiàn)在如果我們將兩數(shù)相減可以得到結(jié)果4。

      所有這些你在腦子里做的事情與計(jì)算機(jī)用兩個變量可以做的事情非常相似。同樣的處理過程用C++來表示可以寫成下面一段代碼: a = 5;b = 2;a = a + 1;result = a38(7 個數(shù)字(7digits))double 8 雙精度浮點(diǎn)數(shù)(double precision floating point number)1.7e + /308(15 digits)bool 1 布爾Boolean值。它只能是真(true)或假(false)兩值之一。true 或 false wchar_t 2 寬字符(Wide character)。這是為存儲兩字節(jié)(2 bytes)長的國際字符而設(shè)計(jì)的類型。一個寬字符(1 wide characters)

      * 字節(jié)數(shù)一列和范圍一列可能根據(jù)程序編譯和運(yùn)行的系統(tǒng)不同而有所不同。這里列出的數(shù)值是多數(shù)32位系統(tǒng)的常用數(shù)據(jù)。對于其他系統(tǒng),通常的說法是整型(int)具有根據(jù)系統(tǒng)結(jié)構(gòu)建議的自然長度(即一個字one word的長度),而4中整型數(shù)據(jù)char, short, int, long的長度必須是遞增的,也就是說按順序每一類型必須大于等于其前面一個類型的長度。同樣的規(guī)則也適用于浮點(diǎn)數(shù)類型float, double和 long double,也是按遞增順序。

      除以上列出的基本數(shù)據(jù)類型外,還有指針(pointer)和void 參數(shù)表示類型,我們將在后面看到。

      變量的聲明(Declaration of variables)

      在C++中要使用一個變量必須先聲明(declare)該變量的數(shù)據(jù)類型。聲明一個新變量的語法是寫出數(shù)據(jù)類型標(biāo)識符(例如int, short, float...)后面跟一個有效的變量標(biāo)識名稱。例如: int a;float mynumber;以上兩個均為有效的變量聲明(variable declaration)。第一個聲明一個標(biāo)識為a 的整型變量(int variable),第二個聲明一個標(biāo)識為mynumber 的浮點(diǎn)型變量(float variable)。聲明之后,我們就可以在后面的程序中使用變量a和 mynumber 了。

      如果你需要聲明多個同一類型的變量,你可以將它們縮寫在同一行聲明中,在標(biāo)識之間用逗號(comma)分隔。例如: int a, b, c;以上語句同時定義了a、b、c 3個整型變量,它與下面的寫法完全等同: int a;int b;int c;整型數(shù)據(jù)類型(char, short, long 和 int)可以是有符號的(signed)或無符號的(unsigned),這取決于我們需要表示的數(shù)據(jù)范圍。有符號類型(signed)可以表示正數(shù)和負(fù)數(shù),而無符號類型(unsigned)只能表示正數(shù)和0。在定義一個整型數(shù)據(jù)變量時可以在數(shù)據(jù)類型前面加關(guān)鍵字 signed 或 unsigned 來聲明數(shù)據(jù)的符號類型。例如: unsigned short NumberOfSons;signed int MyAccountBalance;如果我們沒有特別寫出signed或 unsigned,變量默認(rèn)為signed,因此以上第二個聲明我們也可以寫成:

      int MyAccountBalance;因?yàn)橐陨蟽煞N表示方式意義完全一樣,因此我們在源程序通常省略關(guān)鍵字signed。

      唯一的例外是字符型(char)變量,這種變量獨(dú)立存在,與signed char 和 unsigned char型均不相同。

      short 和 long 可以被單獨(dú)用來表示整型基本數(shù)據(jù)類型,short 相當(dāng)于 short int,long 相當(dāng)于 long int。也就是說 short year;和 short int year;兩種聲明是等價的。

      最后,signed 和 unsigned 也可以被單獨(dú)用來表示簡單類型,意思分別同signed int 和 unsigned int 相同,即以下兩種聲明互相等同: unsigned MyBirthYear;unsigned int MyBirthYear;下面我們就用C++代碼來解決在這一節(jié)開頭提到的記憶問題,來看一下變量定義是如何在程序中起作用的。

      // operating with variables

      #include using namespace std;

      int main(){ // declaring variables: int a, b;int result;

      // process: a = 5;b = 2;a = a + 1;result = ab;cout << result;

      return 0;} 6

      字符串(strings)字符串是用來存儲一個以上字符的非數(shù)字值的變量。

      C++提供一個string類來支持字符串的操作,它不是一個基本的數(shù)據(jù)類型,但是在一般的使用中與基本數(shù)據(jù)類型非常相似。

      與普通數(shù)據(jù)類型不同的一點(diǎn)是,要想聲明和使用字符串類型的變量,需要引用頭文件,并且使用using namespace語句來使用標(biāo)準(zhǔn)名空間(std),如下面例子所示: // C++字符串例題 #include #include using namespace std;

      int main(){ string mystring = “This is a string”;cout << mystring;return 0;} This is a string 如上面例子所示,字符串變量可以被初始化為任何字符串值,就像數(shù)字類型變量可以被初始化為任何數(shù)字值一樣。

      以下兩種初始化格式對字符串變量都是可以使用的: string mystring = “This is a string”;string mystring(“This is a string”);字符串變量還可以進(jìn)行其他與基本數(shù)據(jù)類型變量一樣的操作,比如聲明的時候不指定初始值,和在運(yùn)行過程中被重新賦值。// C++字符串例題2 #include #include using namespace std;

      int main(){ string mystring;mystring = “This is the initial string content”;cout << mystring << endl;mystring = “This is a different string content”;cout << mystring << endl;return 0;} This is the initial string content This is a different string content 要了解更加詳細(xì)的C++字符串操作,建議參考Cplusplus上的string類reference。1.3 常量(Constants)

      一個常量(constant)是一個有固定值的表達(dá)式。字(Literals)

      字是用來在程序源碼中表達(dá)特定的值。在前面的內(nèi)容中我們已經(jīng)用了很多的字來給變量賦予特定的值。例如: a = 5;

      這句代碼中5就是一個字常量。

      字常量(literal constant)可以被分為整數(shù)(Integer Numbers), 浮點(diǎn)數(shù)(Floating-Point Numbers),字符(Characters)和字符串(Strings)。

      整數(shù)(Integer Numbers)1776 707-273 他們是整型常數(shù),表示十進(jìn)制整數(shù)值。注意表示整型常數(shù)時我們不需要些引號(quotes(“))或任何特殊字符。毫無疑問它是個常量:任何時候當(dāng)我們在程序中寫1776,我們指的就是1776這個數(shù)值。

      除十進(jìn)制整數(shù)另外,C++還允許使用八進(jìn)制(octal numbers)和十六進(jìn)制(hexadecimal numbers)的字常量(literal constants)。如果我們想要表示一個八進(jìn)制數(shù),我們必須在它前面加上一個0字符(zero character),而表示十六進(jìn)制數(shù)我們需要在它前面加字符0x(zero, x)。例如以下字常量(literal constants)互相等值: 75 // 十進(jìn)制 decimal 0113 // 八進(jìn)制 octal 0x4b // 十六進(jìn)制 hexadecimal 所有這些都表示同一個整數(shù): 75(seventy five),分別以十進(jìn)制數(shù),八進(jìn)制數(shù)和十六進(jìn)制數(shù)表示。

      像變量一樣,常量也是有數(shù)據(jù)類型的。默認(rèn)的整數(shù)字常量的類型為int型。我們可以通過在后面加字母u或l來迫使它為無符號(unsigned)的類型或長整型(long)。75 // int 75u // unsigned int 75l // long 75ul // unsigned long

      這里后綴u和l可以是大寫,也可以是小寫。

      浮點(diǎn)數(shù)(Floating Point Numbers)浮點(diǎn)數(shù)以小數(shù)(decimals)和/或指數(shù)冪(exponents)的形式表示。它們可以包括一個小數(shù)點(diǎn),一個e字符(表示”by ten at the Xth height“,這里X是后面跟的整數(shù)值),或兩者都包括。

      3.14159 // 3.14159 6.02e23 // 6.02 x 10^1023 1.6e-19 // 1.6 x 10^-19 3.0 // 3.0 以上是包含小數(shù)的以C++表示的4個有效數(shù)值。第一個是PI,第二個是Avogadro數(shù)之一,第三個是一個電子(electron)的電量(electric charge)(一個極小的數(shù)值)– 所有這些都是近似值。最后一個是浮點(diǎn)數(shù)字常量表示數(shù)3。

      浮點(diǎn)數(shù)的默認(rèn)數(shù)據(jù)類型為double。如果你想使用float或long double類型,可以在后面加f或l后綴,同樣大小寫都可以: 3.14159L // long double 6.02e23f // float

      字符和字符串(Characters and strings)此外還有非數(shù)字常量,例如: 'z' 'p' ”Hello world“ ”How do you do?“ 前兩個表達(dá)式表示單獨(dú)的字符(character),后面兩個表示由若干字符組成的字符串(string)。注意在表示單獨(dú)字符的時候,我們用單引號(single quotes(')),在表示字符串或多于一個字符的時候我們用雙引號(double quotes(”))。

      當(dāng)以常量方式表示單個字符和字符串時,必須寫上引號以便把他們和可能的變量標(biāo)識或保留字區(qū)分開,注意以下例子: x 'x' x 指一個變量名稱為 x, 而'x'指字符常量'x'。字符常量和字符串常量各有特點(diǎn),例如escape codes,這些是除此之外無法在源程序中表示的特殊的字符,例如換行符 newline(n)或跳躍符tab(t)。所有這些符號前面要加一個反斜杠inverted slash()。這里列出了這些escape codes: n 換行符newline r 回車carriage return t 跳躍符tabulation v 垂直跳躍vertical tabulation b backspace f page feed a 警告alert(beep)' 單引號single quotes(')“ 雙引號double quotes(”)? 問號question(?)反斜杠inverted slash()例如: 'n' 't' “Left t Right” “onentwonthree” 另外你可以數(shù)字ASCII 碼表示一個字符,這種表示方式是在反斜杠()之后加以8進(jìn)制數(shù)或十六進(jìn)制數(shù)表示的ASCII 碼。在第一種(八進(jìn)制octal)表示中,數(shù)字必需緊跟反斜杠(例如23或40),第二種(十六進(jìn)制hexacedimal),必須在數(shù)字之前寫一個x字符(例如x20或x4A)。

      如果每一行代碼以反斜杠inverted slash()結(jié)束,字符串常量可以分多行代碼表示: “string expressed in two lines” 你還可以將多個被空格blankspace、跳躍符tabulator、換行符newline或其他有效空白符號分隔開的字符串常量連接在一起:

      “we form” “a single” “string” “of characters” 最后如果我們想讓字符串使用寬字符(wchar_t),而不是窄字符(char),可以在常量的前面加前綴L:

      L“This is a wide character string” 寬字符通常用來存儲非英語字符,比如中文字符,一個字符占兩個字節(jié)。布爾型常量(Boolean Literals)布爾型只有兩個有效的值:true和false,其數(shù)據(jù)類型為bool。

      定義常量Defined constants(#define)使用預(yù)處理器指令#define,你可以將那些你經(jīng)常使用的常量定義為你自己取的名字而不需要借助于變量。它的格式是: #define identifier value 例如:

      #define PI 3.14159265 #define NEWLINE 'n' #define WIDTH 100 以上定義了三個常量。一旦做了這些聲明,你可以在后面的程序中使用這些常量,就像使用其它任何常量一樣,例如: circle = 2 * PI * r;cout << NEWLINE;實(shí)際上編譯器在遇到#define指令的時候做的只是把任何出現(xiàn)這些 常量名(在前面的例子中為PI, NEWLINE或WIDTH)的地方替換成他們被定義為的代碼(分別為3.14159265, 'n'和100)。因此,由#define定義的常量被稱為宏常量macro constants。

      #define 指令不是代碼語句,它是預(yù)處理器指令,因此指令行末尾不需要加分號semicolon(;)。如果你在宏定義行末尾加了分號(;),當(dāng)預(yù)處理器在程序中做常量替換的時候,分號也會被加到被替換的行中,這樣可能導(dǎo)致錯誤。

      聲明常量declared constants(const)通過使用const前綴,你可以定義指定類型的常量,就像定義一個變量一樣: const int width = 100;const char tab = 't';const zip = 12440;如果沒有指定類型(如上面最后例子中最后一行),編譯器會假設(shè)常量為整型int。1.4 操作符/運(yùn)算符(Operators)

      前面已經(jīng)學(xué)習(xí)了變量和常量,我們可以開始對它們進(jìn)行操作,這就要用到C++的操作符。有些語言,很多操作符都是一些關(guān)鍵字,比如add, equals等等。C++的操作符主要是由符號組成的。這些符號不在字母表中,但是在所有鍵盤上都可以找到。這個特點(diǎn)使得C++程序更簡潔,也更國際化。運(yùn)算符是C++語言的基礎(chǔ),所以非常重要。

      你不需要背下所有這一小節(jié)的內(nèi)容,這些細(xì)節(jié)知識僅供你以后需要時參考。賦值A(chǔ)ssignation(=)賦值運(yùn)算符的功能是將一個值賦給一個變量。a = 5;將整數(shù)5賦給變量a。= 運(yùn)算符左邊的部分叫做lvalue(left value),右邊的部分叫做rvalue(right value)。lvalue 必須是一個變量,而右邊的部分可以是一個常量,一個變量,一個運(yùn)算(operation)的結(jié)果或是前面幾項(xiàng)的任意組合。

      有必要強(qiáng)調(diào)賦值運(yùn)算符永遠(yuǎn)是將右邊的值賦給左邊,永遠(yuǎn)不會反過來。a = b;將變量b(rvalue)的值賦給變量a(lvalue),不論a當(dāng)時存儲的是什么值。同時考慮到我們只是將b的數(shù)值賦給a,以后如果b的值改變了并不會影響到a的值.例如:如果我們使用以下代碼(變量值的變化顯示在綠色注釋部分): // 賦值符號例子

      #include using namespace std;

      int main(){ int a, b;// a:?, b:? a = 10;// a:10, b:? b = 4;// a:10, b:4 a = b;// a:4, b:4 b = 7;// a:4, b:7

      cout << “a:”;cout << a;cout << “ b:”;cout << b;

      return 0;} a:4 b:7 以上代碼結(jié)果是a的值為4,b的值為7。最后一行中b的值被改變并不會影響到a,雖然在此之前我們聲明了a = b;(從右到左規(guī)則right-to-left rule)。

      C++擁有而其他語言沒有的一個特性是賦值符(=)可以被用作另一個賦值符的rvalue(或rvalue的一部分)。例如: a = 2 +(b = 5);等同于: b = 5;a = 2 + b;它的意思是:先將5賦給變量b,然后把前面對b的賦值運(yùn)算的結(jié)果(即5)加上2再賦給變量a,這樣最后a中的值為7。因此,下面的表達(dá)式在C++中也是正確的: a = b = c = 5;//將5同時賦給3個變量a, b和c。

      數(shù)學(xué)運(yùn)算符Arithmetic operators(+,-, *, /, %)C++語言支持的5種數(shù)學(xué)運(yùn)算符為: ? + 加addition ?5;a /= b;等同于 a = a / b;price *= units + 1;等同于 price = price *(units + 1);其他運(yùn)算符以此類推。例如: // 組合運(yùn)算符例子

      #include using namespace std;

      int main(){ int a, b=3;a = b;a+=2;// 相當(dāng)于 a=a+2 cout << a;return 0;} 5

      遞增和遞減Increase and decrease 書寫簡練的另一個例子是遞增(increase)運(yùn)算符(++)和遞減(decrease)運(yùn)算符(--)。它們使得變量中存儲的值加1或減1。它們分別等同于+=1和-=1。因此: a++;a+=1;a=a+1;在功能上全部等同,即全部使得變量a的值加1。

      它的存在是因?yàn)樽钤绲腃編譯器將以上三種表達(dá)式的編譯成不同的機(jī)器代碼,不同的機(jī)器代碼運(yùn)行速度不一樣?,F(xiàn)在,編譯器已經(jīng)基本自動實(shí)行代碼優(yōu)化,所以以上三種不同的表達(dá)方式編譯成的機(jī)器代碼在實(shí)際運(yùn)行上已基本相同。

      這個運(yùn)算符的一個特點(diǎn)是它既可以被用作prefix前綴,也可以被用作后綴suffix,也就是說它既可以被寫在變量標(biāo)識的前面(++a),也可以被寫在后面(a++)。雖然在簡單表達(dá)式如a++或++a中,這兩種寫法代表同樣的意思,但當(dāng)遞增increase或遞減decrease的運(yùn)算結(jié)果被直接用在其它的運(yùn)算式中時,它們就代表非常不同的意思了:當(dāng)遞增運(yùn)算符被用作前綴prefix(++a)時,變量a的值線增加,然后再計(jì)算整個表達(dá)式的值,因此增加后的值被用在了表達(dá)式的計(jì)算中;當(dāng)它被用作后綴suffix(a++)時,變量a的值在表達(dá)式計(jì)算后才增加,因此a在增加前所存儲的值被用在了表達(dá)式的計(jì)算中。注意以下兩個例子的不同: 例 1 例 2 B=3;A=++B;// A 的值為 4, B 的值為 4 B=3;A=B++;// A 的值為 3, B 的值為 4 在第一個例子中,B在它的值被賦給A之前增加1。而在第二個例子中B原來的值3被賦給 A然后B的值才加1變?yōu)?。

      關(guān)系運(yùn)算符Relational operators(==,!=, >, <, >=, <=)我們用關(guān)系運(yùn)算符來比較兩個表達(dá)式。如ANSI-C++ 標(biāo)準(zhǔn)中指出的,關(guān)系預(yù)算的結(jié)果是一個bool值,根據(jù)運(yùn)算結(jié)果的不同,它的值只能是真true或false。

      例如我們想通過比較兩個表達(dá)式來看它們是否相等或一個值是否比另一個的值大。以下為C++的關(guān)系運(yùn)算符: == 相等Equal!= 不等Different > 大于Greater than < 小于Less than >= 大于等于Greater or equal than <= 小于等于Less or equal than 下面你可以看到一些實(shí)際的例子:(7 == 5)將返回false.(5 > 4)將返回true.(3!= 2)將返回true.(6 >= 6)將返回true.(5 < 5)將返回false.當(dāng)然,除了使用數(shù)字常量,我們也可以使用任何有效表達(dá)式,包括變量。假設(shè)有a=2, b=3和c=6,(a == 5)將返回false.(a*b >= c)將返回true 因?yàn)樗鼘?shí)際是(2*3 >= 6)

      (b+4 > a*c)將返回false因?yàn)樗鼘?shí)際是(3+4 > 2*6)

      ((b=2)== a)將返回true.注意:運(yùn)算符=(單個等號)不同于運(yùn)算符==(雙等號)。第一個是賦值運(yùn)算符(將等號右邊的表達(dá)式值賦給左邊的變量);第二個(==)是一個判斷等于的關(guān)系運(yùn)算符,用來判斷運(yùn)算符兩邊的表達(dá)式是否相等。因此在上面例子中最后一個表達(dá)式((b=2)== a),我們首先將數(shù)值2賦給變量b,然后把它和變量a進(jìn)行比較。因?yàn)樽兞縜中存儲的也是數(shù)值2,所以整個運(yùn)算的結(jié)果為true。

      在ANSI-C++標(biāo)準(zhǔn)出現(xiàn)之前的許多編譯器中,就像C語言中,關(guān)系運(yùn)算并不返回值為真true或假false的bool值,而是返回一個整型數(shù)值最為結(jié)果,它的數(shù)值可以為0,代表“false”或一個非0數(shù)值(通常為1)來代表“true”。

      邏輯運(yùn)算符Logic operators(!, &&, ||)運(yùn)算符!等同于boolean 運(yùn)算NOT(取非),它只有一個操作數(shù)(operand),寫在它的右邊。它做的唯一工作就是取該操作數(shù)的反面值,也就是說如果操作數(shù)值為真true,那么運(yùn)算后值變?yōu)榧賔alse,如果操作數(shù)值為假false,則運(yùn)算結(jié)果為真true。它就好像是說取與操作數(shù)相反的值。例如:

      !(5 == 5)返回false,因?yàn)樗疫叺谋磉_(dá)式(5 == 5)為真true.!(6 <= 4)返回true因?yàn)?6 <= 4)為假false.!true 返回假false.!false 返回真true.邏輯運(yùn)算符&&和||是用來計(jì)算兩個表達(dá)式而獲得一個結(jié)果值。它們分別對應(yīng)邏輯運(yùn)算中的與運(yùn)算AND 和或運(yùn)算OR。它們的運(yùn)算結(jié)果取決于兩個操作數(shù)(operand)的關(guān)系: 第一個操作數(shù) a 第二個操作數(shù) b 結(jié)果 a && b 結(jié)果 a || b true true true true true false false true false true false true false false false false 例如 :

      ((5 == 5)&&(3 > 6))返回false(true && false).((5 == 5)||(3 > 6))返回true(true || false).條件運(yùn)算符Conditional operator(?)條件運(yùn)算符計(jì)算一個表達(dá)式的值并根據(jù)表達(dá)式的計(jì)算結(jié)果為真true或假false而返回不同值。它的格式是:

      condition ? result1 : result2(條件?返回值1:返回值2)

      如果條件condition 為真true,整個表達(dá)式將返回esult1,否則將返回result2。7==5 ? 4 : 3 返回3,因?yàn)?不等于5.7==5+2 ? 4 : 3 返回4,因?yàn)?等于5+2.5>3 ? a : b 返回a,因?yàn)?大于3.a>b ? a : b 返回較大值,a 或b.// 條件運(yùn)算符例子

      #include using namespace std;int main(){ int a,b,c;

      a=2;b=7;c =(a>b)? a : b;

      cout << c;

      return 0;} 7 上面的例子中a的值為2,b的值為7,所以表達(dá)式(a>b)運(yùn)算值為假(false),所以整個表達(dá)式(a>b)?a:b要取分號后面的值,也就是b的值7。因此最后輸出 c 的值為7。

      逗號運(yùn)算符(,)逗號運(yùn)算符(,)用來分開多個表達(dá)式,并只取最右邊的表達(dá)式的值返回。

      例如有以下代碼: a =(b=3, b+2);

      這行代碼首先將3賦值給變量b,然后將 b+2 賦值給變量 a。所以最后變量a 的值為5,而變量b的值為3。

      位運(yùn)算符Bitwise Operators(&, |, ^, ~, <<, >>)位運(yùn)算符以比特位改寫變量存儲的數(shù)值,也就是改寫變量值的二進(jìn)制表示: op asm Description & AND 邏輯與 Logic AND | OR 邏輯或Logic OR ^ XOR 邏輯異或Logical exclusive OR ~ NOT 對1取補(bǔ)(位反轉(zhuǎn))Complement to one(bit inversion)<< SHL 左移Shift Left >> SHR 右移Shift Right

      變量類型轉(zhuǎn)換運(yùn)算符Explicit type casting operators 變量類型轉(zhuǎn)換運(yùn)算符可以將一種類型的數(shù)據(jù)轉(zhuǎn)換為另一種類型的數(shù)據(jù)。在寫C++中有幾種方法可以實(shí)現(xiàn)這種操作,最常用的一種,也是與C兼容的一種,是在原轉(zhuǎn)換的表達(dá)式前面加用括號()括起的新數(shù)據(jù)類型: int i;float f = 3.14;i =(int)f;以上代碼將浮點(diǎn)型數(shù)字3.14轉(zhuǎn)換成一個整數(shù)值(3)。這里類型轉(zhuǎn)換操作符為(int)。在C++中實(shí)現(xiàn)這一操作的另一種方法是使用構(gòu)造函數(shù)constructor 的形式:在要轉(zhuǎn)換的表達(dá)式前加變量類型并將表達(dá)式括在括號中: i = int(f);以上兩種類型轉(zhuǎn)換的方法在C++中都是合法的。另外ANSI-C++針對面向?qū)ο缶幊蹋╫bject oriented programming)增加了新的類型轉(zhuǎn)換操作符(參考Section 5.4, Advanced class type-casting).sizeof()這個運(yùn)算符接受一個輸入?yún)?shù),該參數(shù)可以是一個變量類型或一個變量自己,返回該變量類型(variable type)或?qū)ο?object)所占的字節(jié)數(shù): a = sizeof(char);這將會返回1給a,因?yàn)閏har是一個常為1個字節(jié)的變量類型。

      sizeof返回的值是一個常數(shù),因此它總是在程序執(zhí)行前就被固定了。

      其它運(yùn)算符

      在本教程后面的章節(jié)里我們將看到更多的運(yùn)算符,比如指向指針的運(yùn)算或面向?qū)ο缶幊烫赜械倪\(yùn)算,等等,我們會在它們各自的章節(jié)里進(jìn)行詳細(xì)討論。

      運(yùn)算符的優(yōu)先度 Precedence of operators 當(dāng)多個操作數(shù)組成復(fù)雜的表達(dá)式時,我們可能會疑惑哪個運(yùn)算先被計(jì)算,哪個后被計(jì)算。例如以下表達(dá)式: a = 5 + 7 % 2 我們可以懷疑它實(shí)際上表示:

      a = 5 +(7 % 2)結(jié)果為6,還是 a =(5 + 7)% 2 結(jié)果為0? 正確答案為第一個,結(jié)果為6。每一個運(yùn)算符有一個固定的優(yōu)先級,不僅對數(shù)學(xué)運(yùn)算符(我們可能在學(xué)習(xí)數(shù)學(xué)的時候已經(jīng)很了解它們的優(yōu)先順序了),所有在C++中出現(xiàn)的運(yùn)算符都有優(yōu)先級。從最從最高級到最低級,運(yùn)算的優(yōu)先級按下表排列: 優(yōu)先級

      Level 操作符 Operator 說明 Description 結(jié)合方向 Grouping 1 :: 范圍 從左到右()[].-> ++--dynamic_cast static_cast reinterpret_cast const_cast typeid 后綴 從左到右 ++--~!sizeof new delete 一元(前綴)從右到左

      * & 指針和取地址

      +加減 從左到右 8 << >> 位移 從左到右 < > <= >= 關(guān)系操作符 從左到右 10 ==!= 等于、不等于 從左到右 11 & 按位與運(yùn)算 從左到右 12 ^ 按位異或運(yùn)算 從左到右 13 | 按位或運(yùn)算 從左到右 14 && 邏輯與運(yùn)算 從左到右 15 || 邏輯或運(yùn)算 從左到右 16 ?: 條件運(yùn)算 從右到左 = *= /= %= +=-= >>= <<= &= ^= |= 賦值運(yùn)算 從右到左 18 , 逗號 從左到右

      結(jié)合方向Grouping定義了當(dāng)有同優(yōu)先級的多個運(yùn)算符在一起時,哪一個必須被首先運(yùn)算,最右邊的還是最左邊的。

      所有這些運(yùn)算符的優(yōu)先級順序可以通過使用括號parenthesis signs(和)來控制,而且更易讀懂,例如以下例子: a = 5 + 7 % 2;根據(jù)我們想要實(shí)現(xiàn)的計(jì)算的不同,可以寫成: a = 5 +(7 % 2);或者 a =(5 + 7)% 2;所以如果你想寫一個復(fù)雜的表達(dá)式而不敢肯定各個運(yùn)算的執(zhí)行順序,那么就加上括號。這樣還可以使代碼更易讀懂。

      1.5 控制臺交互(Communication through console)控制臺(console)是電腦的最基本交互接口,通常包括鍵盤(keyboard)和屏幕(screen)。鍵盤通常為標(biāo)準(zhǔn)輸入設(shè)備,而 屏幕為標(biāo)準(zhǔn)輸出設(shè)備。

      在C++的iostream函數(shù)庫中,一個程序的標(biāo)準(zhǔn)輸入輸出操作依靠兩種數(shù)據(jù)流:cin 給輸入使用和cout給輸出使用。另外,cerr和clog也已經(jīng)被實(shí)現(xiàn)――它們是兩種特殊設(shè)計(jì)的數(shù)據(jù)流專門用來顯示出錯信息。它們可以被重新定向到標(biāo)準(zhǔn)輸出設(shè)備或到一個日志文件(log file)。因此cout(標(biāo)準(zhǔn)輸出流)通常被定向到屏幕,而cin(標(biāo)準(zhǔn)輸入流)通常被定向到鍵盤。通過控制這兩種數(shù)據(jù)流,你可以在程序中與用戶交互,因?yàn)槟憧梢栽谄聊簧巷@示輸出并從鍵盤接收用戶的輸入。

      輸出Output(cout)輸出流cout與重載(overloaded)運(yùn)算符<<一起使用:

      cout << “Output sentence”;// 打印Output sentence到屏幕上 cout << 120;// 打印數(shù)字 120 到屏幕上 cout << x;// 打印變量 x 的值到屏幕上

      運(yùn)算符<<又叫插入運(yùn)算符(insertion operator)因?yàn)樗鼘⒑竺嫠臄?shù)據(jù)插入到它前面的數(shù)據(jù)流中。在以上的例子中,字符串常量Output sentence,數(shù)字常量120和變量x先后被插入輸出流cout中。注意第一句中字符串常量是被雙引號引起來的。每當(dāng)我們使用字符串常量的時候,必須用引號把字符串引起來,以便將它和變量名明顯的區(qū)分開來。例如,下面兩個語句是不同的:

      cout << “Hello”;// 打印字符串Hello到屏幕上

      cout << Hello;// 把變量Hello存儲的內(nèi)容打印到屏幕上

      插入運(yùn)算符insertion operator(<<)可以在同一語句中被多次使用: cout << “Hello, ” << “I am ” << “a C++ sentence”;上面這一行語句將會打印 Hello, I am a C++ sentence 到屏幕上。插入運(yùn)算符(<<)的重復(fù)使用在我們想要打印變量和內(nèi)容的組合內(nèi)容或多個變量時有所體現(xiàn):

      cout << “Hello, I am ” << age << “ years old and my zipcode is ” << zipcode;如果我們假設(shè)變量age的值為24,變量zipcode的值為90064,以上句子的輸出將為: Hello, I am 24 years old and my zipcode is 90064 必須注意,除非我們明確指定,cout并不會自動在其輸出內(nèi)容的末尾加換行符,因此下面的語句:

      cout << “This is a sentence.”;cout << “This is another sentence.”;將會有如下內(nèi)容輸出到屏幕:

      This is a sentence.This is another sentence.雖然我們分別調(diào)用了兩次cout,兩個句子還是被輸出在同一行。所以,為了在輸出中換行,我們必須插入一個換行符來明確表達(dá)這一要求。在C++中換行符可以寫作n: cout << “First sentence.n ”;cout << “Second sentence.nThird sentence.”;將會產(chǎn)生如下輸出: First sentence.Second sentence.Third sentence.另外,你也可以用操作符endl來換行,例如: cout << “First sentence.” << endl;cout << “Second sentence.” << endl;將會輸出:

      First sentence.Second sentence.當(dāng)操作符endl被用在buffered streams中時有一點(diǎn)特殊:它們被flushed。不過cout 默認(rèn)為unbuffered,所以不會被影響。你可以暫時不管這一點(diǎn)。

      你可以使用n或endl來指定cout輸出換行,請注意前面所講的兩者的不同用法。

      輸入Input(cin)C++中的標(biāo)準(zhǔn)輸入是通過在cin數(shù)據(jù)流上重載運(yùn)算符extraction(>>)來實(shí)現(xiàn)的。它后面必須跟一個變量以便存儲讀入的數(shù)據(jù)。例如: int age;cin >> age;聲明一個整型變量age然后等待用戶從鍵盤輸入到cin并將輸入值存儲在這個變量中。cin 只能在鍵盤輸入回車鍵(RETURN)后才能處理前面輸入的內(nèi)容。因此即使你只要求輸入一個單獨(dú)的字符,在用戶按下回車鍵(RETURN)之前cin將不會處理用戶的輸入的字符。在使用cin輸入的時候必須考慮后面的變量類型。如果你要求輸入一個整數(shù),extraction(>>)后面必須跟一個整型變量,如果要求一個字符,后面必須跟一個字符型變量,如果要求一個字符串,后面必須跟一個字符串型變量。// i/o example #include int main(){ int i;cout << “Please enter an integer value: ”;cin >> i;cout << “The value you entered is ” << i;cout << “ and its double is ” << i*2 << “.n”;return 0;} Please enter an integer value: 702 The value you entered is 702 and its double is 1404.使用程序的用戶可以使引起錯誤的原因之一,即使是在最簡單的需要用cin做輸入的程序中(就像我們上面看到的這個程序)。因?yàn)槿绻阋筝斎胍粋€整數(shù)數(shù)值,而用戶輸入了一個名字(一個字符串),其結(jié)果可能導(dǎo)致程序產(chǎn)生錯誤操作,因?yàn)樗皇俏覀兤谕麖挠脩籼帿@得的數(shù)據(jù)。當(dāng)你使用由cin 輸入的數(shù)據(jù)的時候,你不得不假設(shè)程序的用戶將會完全合作而不會在程序要求輸入整數(shù)的時候輸入他的名字。后面當(dāng)我們看到怎樣使用字符串的時候,我們將會同時看到一些解決這一類出錯問題的辦法。你也可以利用cin 要求用戶輸入多個數(shù)據(jù) : cin >> a >> b;等同于: cin >> a;cin >> b;在以上兩種情況下用戶都必須輸入兩個數(shù)據(jù),一個給變量a,一個給變量b。輸入時兩個變量之間可以以任何有效的空白符號間隔,包括空格,跳躍符tab或換行。

      cin和字符串

      我們可以像讀取基本類型數(shù)據(jù)一樣,使用cin和>>操作符來讀取字符串,例如: cin >> mystring;但是,cin >> 只能讀取一個單詞,一旦碰到任何空格,讀取操作就會停止。在很多時候這并不是我們想要的操作,比如我們希望用戶輸入一個英文句子,那么這種方法就無法讀取完整的句子,因?yàn)橐欢〞龅娇崭瘛?/p>

      要一次讀取一整行輸入,需要使用C++的函數(shù) getline,相對于是用cin,我們更建議使用getline來讀取用戶輸入。例如:

      // 讀取字符串例子 #include #include using namespace std;

      int main(){ string mystr;cout << “What's your name? ”;getline(cin, mystr);cout << “Hello ” << mystr << “.n”;cout << “What is your favorite color? ”;getline(cin, mystr);cout << “I like ” << mystr << “ too!n”;return 0;} What's your name? Aqua Hello Aqua.What is your favorite color? blue I like blue too!你可能注意到在上面的例子中,兩次調(diào)用 getline 函數(shù)我們都是用了同一個字符串變量(mystr)。在第二次調(diào)用的時候,程序會自動用第二次輸入的內(nèi)容取代以前的內(nèi)容。

      字符串流(stringstream)

      標(biāo)準(zhǔn)頭文件 定義了一個叫做 stringstream 的類,使用這個類可以對基于字符串的對象進(jìn)行像流(stream)一樣的操作。這樣,我們可以對字符串進(jìn)行抽取和插入操作,這對將字符串與數(shù)值互相轉(zhuǎn)換非常有用。例如,如果我們想將一個字符串轉(zhuǎn)換為一個整數(shù),可以這樣寫: string mystr(“1204”);int myint;stringstream(mystr)>> myint;這個例子中先定義了一個字符串類型的對象mystr,初始值為“1204”,又定義了一個整數(shù)變量myint。然后我們使用 stringstream 類的構(gòu)造函數(shù)定義了這個類的對象,并以字符串變量mystr為參數(shù)。因?yàn)槲覀兛梢韵袷褂昧饕粯邮褂胹tringstream 的對象,所以我們可以像使用cin那樣使用操作符 >> 后面跟一個整數(shù)變量來進(jìn)行提取整數(shù)數(shù)據(jù)。這段代碼執(zhí)行之后變量 myint 存儲的是數(shù)值 1204。// 字符串流的使用示例 #include #include #include using namespace std;

      int main(){ string mystr;float price=0;int quantity=0;

      cout << “Enter price: ”;getline(cin,mystr);stringstream(mystr)>> price;cout << “Enter quantity: ”;getline(cin,mystr);stringstream(mystr)>> quantity;cout << “Total price: ” << price*quantity << endl;return 0;} Enter price: 22.25 Enter quantity: 7 Total price: 155.75 在這個例子中,我們要求用戶輸入數(shù)值,但不同于從標(biāo)準(zhǔn)輸入中直接讀取數(shù)值,我們使用函數(shù)getline從標(biāo)注輸入流cin中讀取字符串對象(mystr),然后再從這個字符串對象中提取數(shù)值price和quantity。

      通過使用這種方法,我們可以對用戶的輸入有更多的控制,因?yàn)樗鼘⒂脩糨斎肱c對輸入的解釋分離,只要求用戶輸入整行的內(nèi)容,然后再對用戶輸入的內(nèi)容進(jìn)行檢驗(yàn)操作。這種做法在用戶輸入比較集中的程序中是非常推薦使用的。第二章 控制結(jié)構(gòu)和函數(shù)

      (Control structures and Functions)1.控制結(jié)構(gòu)

      Control Structures 2.函數(shù)I Functions I 3.函數(shù)II Functions II 2.1 控制結(jié)構(gòu)(Control Structures)

      一個程序的語句往往并不僅限于線性順序結(jié)構(gòu)。在程序的執(zhí)行過程中它可能被分成兩支執(zhí)行,可能重復(fù)某些語句,也可能根據(jù)一些判斷結(jié)果而執(zhí)行不同的語句。因此C++ 提供一些控制結(jié)構(gòu)語句(control structures)來實(shí)現(xiàn)這些執(zhí)行順序。

      為了介紹程序的執(zhí)行順序,我們需要先介紹一個新概念:語句塊(block of instructions)。一個語句塊(A block of instructions)是一組互相之間由分號semicolons(;)分隔開但整體被花括號curly bracket signs: { and }括起來的語句。

      本節(jié)中我們將看到的大多數(shù)控制結(jié)構(gòu)允許一個通用的statement做參數(shù),這個statement根據(jù)需要可以是一條語句,也可以是一組語句組成的語句塊。如果我們只需要一條語句做statement,它可以不被括在花括號({})內(nèi)。但如果我們需要多條語句共同做statement,則必須把它們括在花括號內(nèi)({})以組成一個語句塊。

      條件結(jié)構(gòu)Conditional structure: if and else 條件結(jié)構(gòu)用來實(shí)現(xiàn)僅在某種條件滿足的情況下才執(zhí)行一條語句或一個語句塊。它的形式是: if(condition)statement 這里 condition 是一個將被計(jì)算的表達(dá)式(expression)。如果表達(dá)式值為真,即條件(condition)為true,statement 將被執(zhí)行。否則,statement 將被忽略(不被執(zhí)行),程序從整個條件結(jié)構(gòu)之后的下一條語句繼續(xù)執(zhí)行。

      例如,以下程序段實(shí)現(xiàn)只有當(dāng)變量x存儲的值確實(shí)為100的時候才輸出“x is 100”: if(x == 100)cout << “x is 100”;如果我們需要在條件condition為真true的時候執(zhí)行一條以上的語句,我們可以花括號{}將語句括起來組成一個語句塊: if(x == 100){ cout << “x is ”;cout << x;} 我們可以用關(guān)鍵字else 來指定當(dāng)條件不能被滿足時需要執(zhí)行的語句,它需要和if 一起使用,形式是:

      if(condition)statement1 else statement2 例如: if(x == 100)cout << “x is 100”;else cout << “x is not 100”;以上程序如果x的值為100,則在屏幕上打出x is 100,如果x不是100,而且也只有在x不是100的時候,屏幕上將打出x is not 100。

      多個if + else 的結(jié)構(gòu)被連接起來使用來判斷數(shù)值的范圍。以下例子顯示了如何用它來判斷變量 x中當(dāng)前存儲的數(shù)值是正值,負(fù)值還是既不正也不負(fù),即等于0。if(x > 0)cout << “x is positive”;else if(x < 0)cout << “x is negative”;else cout << “x is 0”;記住當(dāng)我們需要執(zhí)行多條語句時,必須使用花括號{}將它們括起來以組成一個語句塊block of instructions。

      重復(fù)結(jié)構(gòu) Iteration structures 或循環(huán)loops 循環(huán)Loops 的目的是重復(fù)執(zhí)行一組語句一定的次數(shù)或直到滿足某種條件。while 循環(huán) 格式是:

      while(表達(dá)式expression)語句statement 它的功能是當(dāng)expression 的值為真true時重復(fù)執(zhí)行statement。例如,下面我們將用while循環(huán)來寫一個倒計(jì)數(shù)程序: // custom countdown using while #include int main(){ int n;cout << “Enter the starting number > ”;cin >> n;while(n>0){ cout << n << “, ”;--n;} cout << “FIRE!”;return 0;} Enter the starting number > 8 8, 7, 6, 5, 4, 3, 2, 1, FIRE!程序開始時提示用戶輸入一個倒計(jì)數(shù)的初始值。然后while 循環(huán)開始,如果用戶輸入的數(shù)值滿足條件n>0(即 n 比0 大),后面跟的語句塊將會被執(zhí)行一定的次數(shù),直到條件(n>0)不再滿足(變?yōu)閒alse)。

      以上程序的所有處理過程可以用以下的描述來解釋: 從main開始: 1.用戶輸入一個數(shù)值賦給n.2.while語句檢查(n>0)是否成立,這時有兩種可能: o true: 執(zhí)行statement(到第3步)o false: 跳過statement.程序直接執(zhí)行第5步.3.執(zhí)行statement: cout << n << “, ”;--n;(將n 的值打印在屏幕上,然后將n 的值減1).4.語句塊結(jié)束,自動返回第2步。

      5.繼續(xù)執(zhí)行語句塊之后的程序:打印 FIRE!,程序結(jié)束。

      我們必須考慮到循環(huán)必須在某個點(diǎn)結(jié)束,因此在語句塊之內(nèi)(loop的statement之內(nèi))我們必須提供一些方法使得條件condition 可以在某個時刻變?yōu)榧?false,否則循環(huán)將無限重復(fù)下去。在這個例子里,我們用語句--n;使得循環(huán)在重復(fù)一定的次數(shù)后變?yōu)閒alse :當(dāng) n 變?yōu)?,倒計(jì)數(shù)結(jié)束。do-while 循環(huán) 格式:

      do 語句statement while(條件condition);它的功能與while 循環(huán)一抹一樣,除了在do-while循環(huán)中是先執(zhí)行statement 然后才檢查條件condition,而不想while循環(huán)中先檢查條件然后才執(zhí)行statement。這樣,即使條件condition從來沒有被滿足過,statement 仍至少被執(zhí)行一次。例如,下面的程序重復(fù)輸出(echoes)用戶輸入的任何數(shù)值,直到用戶輸入0為止。// number echoer #include int main(){ unsigned long n;do { cout << “Enter number(0 to end): ”;cin >> n;cout << “You entered: ” << n << “n”;} while(n!= 0);return 0;} Enter number(0 to end): 12345 You entered: 12345 Enter number(0 to end): 160277 You entered: 160277 Enter number(0 to end): 0 You entered: 0 do-while 循環(huán)通常被用在判斷循環(huán)結(jié)束的條件是在循環(huán)語句內(nèi)部被決定的情況下,比如以上的例子,在循環(huán)的語句塊內(nèi)用戶的輸入決定了循環(huán)是否結(jié)束。如果用戶永遠(yuǎn)不輸入0,則循環(huán)永遠(yuǎn)不會結(jié)束。for 循環(huán) 格式是:

      for(initialization;condition;increase)statement;它的主要功能是當(dāng)條件condition 為真true時重復(fù)執(zhí)行語句statement,類似while 循環(huán)。但除此之外,for 還提供了寫初始化語句initialization 和增值語句increase 的地方。因此這種循環(huán)結(jié)構(gòu)是特別為執(zhí)行由計(jì)數(shù)器控制的循環(huán)而設(shè)計(jì)的。它按以下方式工作:

      1.執(zhí)行初始化initialization。通常它是設(shè)置一個計(jì)數(shù)器變量(counter variable)的初始值,初始化僅被執(zhí)行一次。

      2.檢查條件condition,如果條件為真true,繼續(xù)循環(huán),否則循環(huán)結(jié)束循環(huán)中語句statement 被跳過。

      3.執(zhí)行語句statement。像以前一樣,它可以是一個單獨(dú)的語句,也可以是一個由花括號{ }括起來的語句塊。

      4.最后增值域(increase field)中的語句被執(zhí)行,循環(huán)返回第2步。注意增值域中可能是任何語句,而不一定只是將計(jì)數(shù)器增加的語句。例如下面的例子中計(jì)數(shù)器實(shí)際為減1,而不是加1。

      下面是用for循環(huán)實(shí)現(xiàn)的倒計(jì)數(shù)的例子: // countdown using a for loop #include int main(){ for(int n=10;n>0;n--){ cout << n << “, ”;} cout << “FIRE!”;return 0;} 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, FIRE!初始化initialization 和增值increase 域是可選的(即可以為空)。但這些域?yàn)榭盏臅r候,它們和其他域之間間隔的分號不可以省略。例如我們可以寫:for(;n<10;)來表示沒有初始化和增值語句;或for(;n<10;n++)來表示有增值語句但沒有初始化語句。另外我們也可以在for循環(huán)初始化或增值域中放一條以上的語句,中間用逗號 coma(,)隔開。例如假設(shè)我們想在循環(huán)中初始化一個以上的變量,可以用以下的程序來實(shí)現(xiàn): for(n=0, i=100;n!=i;n++, i--){ // whatever here...} 這個循環(huán)將被執(zhí)行50 次,如果n 和i 在循還內(nèi)部都不被改變的話:

      n初始值為0,i初始值為100,條件是(n!=i)(即n不能等于i)。因?yàn)槊看窝h(huán)n加1,而且i減1,循環(huán)的條件將會在第50次循環(huán)之后變?yōu)榧賔alse(n 和 i 都等于50)。分支控制和跳轉(zhuǎn)(Bifurcation of control and jumps)break 語句

      通過使用break語句,即使在結(jié)束條件沒有滿足的情況下,我們也可以跳出一個循環(huán)。它可以被用來結(jié)束一個無限循環(huán)(infinite loop),或強(qiáng)迫循環(huán)在其自然結(jié)束之前結(jié)束。例如,我們想要在倒計(jì)數(shù)自然結(jié)束之前強(qiáng)迫它停止(也許因?yàn)橐粋€引擎故障): // break loop example #include int main(){ int n;for(n=10;n>0;n--){ cout << n << “, ”;if(n==3){ cout << “countdown aborted!”;break;} return 0;} 10, 9, 8, 7, 6, 5, 4, 3, countdown aborted!continue 語句

      continue語句使得程序跳過當(dāng)前循環(huán)中剩下的部分而直接進(jìn)入下一次循環(huán),就好像循環(huán)中語句塊的結(jié)尾已經(jīng)到了使得循環(huán)進(jìn)入下一次重復(fù)。例如,下面例子中倒計(jì)數(shù)時我們將跳過數(shù)字5的輸出:

      // continue loop example #include int main(){ for(int n=10;n>0;n--){ if(n==5)continue;cout << n << “, ”;} cout << “FIRE!”;return 0;} 10, 9, 8, 7, 6, 4, 3, 2, 1, FIRE!goto 語句

      通過使用goto語句可以使程序從一點(diǎn)跳轉(zhuǎn)到另外一點(diǎn)。你必須謹(jǐn)慎只用這條語句,因?yàn)樗膱?zhí)行可以忽略任何嵌套限制。

      跳轉(zhuǎn)的目標(biāo)點(diǎn)可以由一個標(biāo)示符(label)來標(biāo)明,該標(biāo)示符作為goto語句的參數(shù)。一個標(biāo)示符(label)由一個標(biāo)識名稱后面跟一個冒號colon(:)組成。

      通常除了底層程序愛好者使用這條語句,它在結(jié)構(gòu)化或面向?qū)ο蟮木幊讨胁⒉怀S谩O旅娴睦又形覀冇胓oto來實(shí)現(xiàn)倒計(jì)數(shù)循環(huán): // goto loop example #include int main(){ int n=10;loop: cout << n << “, ”;n--;if(n>0)goto loop;cout << “FIRE!”;return 0;} 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, FIRE!exit 函數(shù)

      exit是一個在cstdlib(stdlib.h)庫中定義的函數(shù)。

      exit的目的是一個特定的退出代碼來結(jié)束程序的運(yùn)行,它的原型(prototype)是: void exit(int exit code);exit code是由操作系統(tǒng)使用或被調(diào)用程序使用。通常exit code為0表示程序正常結(jié)束,任何其他值表示程序執(zhí)行過程中出現(xiàn)了錯誤。

      選擇結(jié)構(gòu)The selective Structure: switch switch 語句的語法比較特殊。它的目標(biāo)是對一個表達(dá)式檢查多個可能常量值,有些像我們在本節(jié)開頭學(xué)習(xí)的把幾個if 和else if 語句連接起來的結(jié)構(gòu)。它的形式是: switch(expression){ case constant1: block of instructions 1 break;case constant2: block of instructions 2 break;...default: default block of instructions } 它按以下方式執(zhí)行:

      switch 計(jì)算表達(dá)式expression 的值,并檢查它是否與第一個常量constant1相等,如果相等,程序執(zhí)行常量1后面的語句塊block of instructions 1 直到碰到關(guān)鍵字break,程序跳轉(zhuǎn)到switch 選擇結(jié)構(gòu)的結(jié)尾處。如果expression 不等于constant1,程序檢查表達(dá)式expression 的值是否等于第二個常量constant2,如果相等,程序?qū)?zhí)行常量2后面的語句塊block of instructions 2 直到碰到關(guān)鍵字break。

      依此類推,直到最后如果表達(dá)式expression 的值不等于任何前面的常量(你可以用case語句指明任意數(shù)量的常量值來要求檢查),程序?qū)?zhí)行默認(rèn)區(qū)default: 后面的語句,如果它存在的話。default: 選項(xiàng)是可以省略的。下面的兩段代碼段功能相同:

      switch example if-else equivalent switch(x){ case 1: cout << “x is 1”;break;case 2: cout << “x is 2”;break;default: cout << “value of x unknown”;} if(x == 1){ cout << “x is 1”;} else if(x == 2){ cout << “x is 2”;} else { cout << “value of x unknown”;} 前面已經(jīng)提到switch的語法有點(diǎn)特殊。注意每個語句塊結(jié)尾包含的break語句。這是必須的,因?yàn)槿绻贿@樣做,例如在語句塊block of instructions 1 的結(jié)尾沒有break,程序執(zhí)行將不會跳轉(zhuǎn)到switch選擇的結(jié)尾處(}),而是繼續(xù)執(zhí)行下面的語句塊,直到第一次遇到break語句或到switch選擇結(jié)構(gòu)的結(jié)尾。因此,不需要在每一個case 域內(nèi)加花括號{ }。這個特點(diǎn)同時可以幫助實(shí)現(xiàn)對不同的可能值執(zhí)行相同的語句塊。例如: switch(x){ case 1: case 2: case 3: cout << “x is 1, 2 or 3”;break;default: cout << “x is not 1, 2 nor 3”;} 注意switch只能被用來比較表達(dá)式和不同常量的值constants。因此我們不能夠把變量或范圍放在case之后,例如(case(n*2):)或(case(1..3):)都不可以,因?yàn)樗鼈儾皇怯行У某A?。如果你需要檢查范圍或非常量數(shù)值,使用連續(xù)的if 和else if 語句。2.2 函數(shù)I(Functions I)

      通過使用函數(shù)(functions)我們可以把我們的程序以更模塊化的形式組織起來,從而利用C++所能提供的所有結(jié)構(gòu)化編程的潛力。

      一個函數(shù)(function)是一個可以從程序其它地方調(diào)用執(zhí)行的語句塊。以下是它的格式:

      type name(argument1, argument2,...)statement

      這里:

      ? type 是函數(shù)返回的數(shù)據(jù)的類型 ? name 是函數(shù)被調(diào)用時使用的名

      ? argument 是函數(shù)調(diào)用需要傳入的參量(可以聲明任意多個參量)。每個參量(argument)由一個數(shù)據(jù)類型后面跟一個標(biāo)識名稱組成,就像變量聲明中一樣(例如,int x)。參量僅在函數(shù)范圍內(nèi)有效,可以和函數(shù)中的其它變量一樣使用,它們使得函數(shù)在被調(diào)用時可以傳入?yún)?shù),不同的參數(shù)用逗號(comma)隔開.? statement 是函數(shù)的內(nèi)容。它可以是一句指令,也可以是一組指令組成的語句塊。如果是一組指令,則語句塊必須用花括號{}括起來,這也是我們最常見到情況。其實(shí)為了使程序的格式更加統(tǒng)一清晰,建議在僅有一條指令的時候也使用花括號,這是一個良好的編程習(xí)慣。下面看一下第一個函數(shù)的例子: // function example #include int addition(int a, int b){ int r;r=a+b;return(r);}

      int main(){ int z;z = addition(5,3);cout << “The result is ” << z;return 0;} The result is 8 記得在我們教程開始時說過:一個C++程序總是從main函數(shù)開始執(zhí)行。因此我們從那里開始。

      我們可以看到 main 函數(shù)以定義一個整型變量z 開始。緊跟著我們看到調(diào)用addition 函數(shù)。我們可以看到函數(shù)調(diào)用的寫法和上面函數(shù)定義本身十分相似:

      參數(shù)有明顯的對應(yīng)關(guān)系。在main 函數(shù)中我們調(diào)用addition 函數(shù),并傳入兩個數(shù)值: 5 和3,它們對應(yīng)函數(shù)addition 中定義的參數(shù)int a 和int b。當(dāng)函數(shù)在main 中被調(diào)用時,程序執(zhí)行的控制權(quán)從main轉(zhuǎn)移到函數(shù)addition。調(diào)用傳遞的兩個參數(shù)的數(shù)值(5 和3)被復(fù)制到函數(shù)的本地變量(local variables)int a 和int b 中。函數(shù)addition 中定義了新的變量(int r;),通過表達(dá)式r=a+b;, 它把a(bǔ) 加b 的結(jié)果賦給r。因?yàn)閭鬟^來的參數(shù)a 和b 的值分別為5 和3,所以結(jié)果是8。下面一行代碼: return(r);結(jié)束函數(shù)addition,并把控制權(quán)交還給調(diào)用它的函數(shù)(main),從調(diào)用addition的地方開始繼續(xù)向下執(zhí)行。另外,return 在調(diào)用的時候后面跟著變量r(return(r);), 它當(dāng)時的值為8, 這個值被稱為函數(shù)的返回值。

      函數(shù)返回的數(shù)值就是函數(shù)的計(jì)算結(jié)果,因此,z 將存儲函數(shù)addition(5, 3)返回的數(shù)值, 即8。用另一種方式解釋,你也可以想象成調(diào)用函數(shù)(addition(5,3))被替換成了它的返回值(8)。

      接下來main中的下一行代碼是: cout << “The result is ” << z;它把結(jié)果打印在屏幕上。

      變量的范圍(Scope of variables)你必須考慮到變量的范圍只是在定義該變量的函數(shù)或指令塊內(nèi)有效,而不能在它的函數(shù)或指令塊之外使用。例如,在上面的例子里就不可能在main 中直接使用變量a, b 或 r,因?yàn)樗鼈兪呛瘮?shù)addition的本地變量(local variable)。在函數(shù)addition中也不可能直接使用變量z,因?yàn)樗莔ain的本地變量。

      因此,本地變量(local variables)的范圍是局限于聲明它的嵌套范圍之內(nèi)的。盡管如此,你還可以定義全局變量(global variables),它們可以在代碼的任何位置被訪問,不管在函數(shù)以內(nèi)還是以外。要定義全局變量,你必須在所有函數(shù)或代碼塊之外定義它們,也就是說,直接在程序體中聲明它們。這里是另一個關(guān)于函數(shù)的例子: // function example #include int subtraction(int a, int b){ int r;r=a-b;return(r);}

      int main(){ int x=5, y=3, z;z = subtraction(7,2);cout << “The first result is ” << z << 'n';cout << “The second result is ” << subtraction(7,2)<< 'n';cout << “The third result is ” << subtraction(x,y)<< 'n';z= 4 + subtraction(x,y);cout << “The fourth result is ” << z << 'n';return 0;} The first result is 5 The second result is 5 The third result is 2 The fourth result is 6 在這個例子中,我們定義了函數(shù)subtraction。這個函數(shù)的功能是計(jì)算傳入的兩個參數(shù)的差值并將結(jié)果返回。

      在 main 函數(shù)中,函數(shù)subtraction被調(diào)用了多次。我們用了幾種不同的調(diào)用方法,因此你可以看到在不同的情況下函數(shù)如何被調(diào)用。為了更好的理解這些例子,你需要考慮到被調(diào)用的函數(shù)其實(shí)完全可以由它所返回的值來代替。例如在上面例子中第一種情況下(這種調(diào)用你應(yīng)該已經(jīng)知道了,因?yàn)槲覀冊谇懊娴睦又幸呀?jīng)用過這種形式的調(diào)用): z = subtraction(7,2);cout << “The first result is ” << z;如果我們把函數(shù)調(diào)用用它的結(jié)果(也就是5)替換,我們將得到: z = 5;cout << “The first result is ” << z;同樣的

      cout << “The second result is ” << subtraction(7,2);與前面的調(diào)用有同樣的結(jié)果,但在這里我們把對函數(shù)subtraction 的調(diào)用直接用作cout的參數(shù)。這可以簡單想象成我們寫的是: cout << “The second result is ” << 5;因?yàn)? 是subtraction(7,2)的結(jié)果。在

      cout << “The third result is ” << subtraction(x,y);中,與前面的調(diào)用唯一的不同之處是這里調(diào)用subtraction 時的參數(shù)使用的是變量而不是常量。這樣用時毫無問題的。在這個例子里,傳入函數(shù)subtraction 的參數(shù)值是變量x 和y中存儲的數(shù)值,即分別為5 和3,結(jié)果為2。第四種調(diào)用也是一樣的。只要知道除了 z = 4 + subtraction(x,y);我們也可以寫成:

      z = subtraction(x,y)+ 4;它們的結(jié)果是完全一樣的。注意在整個表達(dá)式的結(jié)尾寫上分號semicolon sign(;)。它并不需要總是跟在函數(shù)調(diào)用的后面,因?yàn)槟憧梢杂幸淮伟阉鼈兿胂蟪珊瘮?shù)被它的結(jié)果所替代: z = 4 + 2;z = 2 + 4;沒有返回值類型的函數(shù),使用void.如果你記得函數(shù)聲明的格式:

      type name(argument1, argument2...)statement 就會知道函數(shù)聲明必須以一個數(shù)據(jù)類型(type)開頭,它是函數(shù)由return 語句所返回?cái)?shù)據(jù)類型。但是如果我們并不打算返回任何數(shù)據(jù)那該怎么辦呢? 假設(shè)我們要寫一個函數(shù),它的功能是打印在屏幕上打印一些信息。我們不需要它返回任何值,而且我們也不需要它接受任何參數(shù)。C語言為這些情況設(shè)計(jì)了void 類型。讓我們看一下下面的例子:

      // void 函數(shù)示例 #include using namespace std;

      void printmessage(){ cout << “I'm a function!”;}

      int main(){ printmessage();return 0;} I'm a function!void還可以被用在函數(shù)參數(shù)位置,表示我們明確希望這個函數(shù)在被調(diào)用時不需要任何參數(shù)。例如上面的函數(shù)printmessage也可以寫為以下形式: void printmessage(void){ cout << “I'm a function!”;} 雖然在C++ 中void可以被省略,我們還是建議寫出void,以便明確指出函數(shù)不需要參數(shù)。你必須時刻知道的是調(diào)用一個函數(shù)時要寫出它的名字并把參數(shù)寫在后面的括號內(nèi)。但如果函數(shù)不需要參數(shù),后面的括號并不能省略。因此調(diào)用函數(shù) printmessage 的格式是 printmessage();函數(shù)名稱后面的括號就明確表示了它是一個函數(shù)調(diào)用,而不是一個變量名稱或其它什么語句。以下調(diào)用函數(shù)的方式就不對: printmessage;2.3 函數(shù)II(Functions II)

      參數(shù)按數(shù)值傳遞和按地址傳遞(Arguments passed by value and by reference)到目前為止,我們看到的所有函數(shù)中,傳遞到函數(shù)中的參數(shù)全部是按數(shù)值傳遞的(by value)。也就是說,當(dāng)我們調(diào)用一個帶有參數(shù)的函數(shù)時,我們傳遞到函數(shù)中的是變量的數(shù)值而不是變量本身。例如,假設(shè)我們用下面的代碼調(diào)用我們的第一個函數(shù)addition : int x=5, y=3, z;z = addition(x , y);在這個例子里我們調(diào)用函數(shù)addition 同時將x和y的值傳給它,即分別為5和3,而不是兩個變量:

      這樣,當(dāng)函數(shù)addition被調(diào)用時,它的變量a和b的值分別變?yōu)?和3,但在函數(shù)addition內(nèi)對變量a 或b 所做的任何修改不會影響變量他外面的變量x 和 y 的值,因?yàn)樽兞縳和y并沒有把它們自己傳遞給函數(shù),而只是傳遞了他們的數(shù)值。

      但在某些情況下你可能需要在一個函數(shù)內(nèi)控制一個函數(shù)以外的變量。要實(shí)現(xiàn)這種操作,我們必須使用按地址傳遞的參數(shù)(arguments passed by reference),就象下面例子中的函數(shù)duplicate:

      // passing parameters by reference #include

      void duplicate(int& a, int& b, int& c){ a*=2;b*=2;c*=2;}

      int main(){ int x=1, y=3, z=7;duplicate(x, y, z);cout << “x=” << x << “, y=” << y << “, z=” << z;return 0;} x=2, y=6, z=14 第一個應(yīng)該注意的事項(xiàng)是在函數(shù)duplicate的聲明(declaration)中,每一個變量的類型后面跟了一個地址符ampersand sign(&),它的作用是指明變量是按地址傳遞的(by reference),而不是像通常一樣按數(shù)值傳遞的(by value)。當(dāng)按地址傳遞(pass by reference)一個變量的時候,我們是在傳遞這個變量本身,我們在函數(shù)中對變量所做的任何修改將會影響到函數(shù)外面被傳遞的變量。

      用另一種方式來說,我們已經(jīng)把變量a, b,c和調(diào)用函數(shù)時使用的參數(shù)(x, y和 z)聯(lián)系起來了,因此如果我們在函數(shù)內(nèi)對a 進(jìn)行操作,函數(shù)外面的x 值也會改變。同樣,任何對b 的改變也會影響y,對c 的改變也會影響z>。

      這就是為什么上面的程序中,主程序main中的三個變量x, y和z在調(diào)用函數(shù)duplicate 后打印結(jié)果顯示他們的值增加了一倍。如果在聲明下面的函數(shù):

      void duplicate(int& a, int& b, int& c)時,我們是按這樣聲明的:

      void duplicate(int a, int b, int c)也就是不寫地址符 ampersand(&),我們也就沒有將參數(shù)的地址傳遞給函數(shù),而是傳遞了它們的值,因此,屏幕上顯示的輸出結(jié)果x, y,z 的值將不會改變,仍是1,3,7。

      這種用地址符 ampersand(&)來聲明按地址“by reference”傳遞參數(shù)的方式只是在C++中適用。在C 語言中,我們必須用指針(pointers)來做相同的操作。

      按地址傳遞(Passing by reference)是一個使函數(shù)返回多個值的有效方法。例如,下面是一個函數(shù),它可以返回第一個輸入?yún)?shù)的前一個和后一個數(shù)值。// more than one returning value #include void prevnext(int x, int& prev, int& next){ prev = x-1;next = x+1;}

      int main(){ int x=100, y, z;prevnext(x, y, z);cout << “Previous=” << y << “, Next=” << z;return 0;} Previous=99, Next=101

      參數(shù)的默認(rèn)值(Default values in arguments)當(dāng)聲明一個函數(shù)的時候我們可以給每一個參數(shù)指定一個默認(rèn)值。如果當(dāng)函數(shù)被調(diào)用時沒有給出該參數(shù)的值,那么這個默認(rèn)值將被使用。指定參數(shù)默認(rèn)值只需要在函數(shù)聲明時把一個數(shù)值賦給參數(shù)。如果函數(shù)被調(diào)用時沒有數(shù)值傳遞給該參數(shù),那么默認(rèn)值將被使用。但如果有指定的數(shù)值傳遞給參數(shù),那么默認(rèn)值將被指定的數(shù)值取代。例如: // default values in functions #include int divide(int a, int b=2){ int r;r=a/b;return(r);}

      int main(){ cout << divide(12);cout << endl;cout << divide(20,4);return 0;} 6 5 我們可以看到在程序中有兩次調(diào)用函數(shù)divide。第一次調(diào)用: divide(12)只有一個參數(shù)被指明,但函數(shù)divide允許有兩個參數(shù)。因此函數(shù)divide 假設(shè)第二個參數(shù)的值為2,因?yàn)槲覀円呀?jīng)定義了它為該參數(shù)缺省的默認(rèn)值(注意函數(shù)聲明中的int b=2)。因此這次函數(shù)調(diào)用的結(jié)果是 6(12/2)。在第二次調(diào)用中: divide(20,4)這里有兩個參數(shù),所以默認(rèn)值(int b=2)被傳入的參數(shù)值4所取代,使得最后結(jié)果為 5(20/4).函數(shù)重載(Overloaded functions)兩個不同的函數(shù)可以用同樣的名字,只要它們的參量(arguments)的原型(prototype)不同,也就是說你可以把同一個名字給多個函數(shù),如果它們用不同數(shù)量的參數(shù),或不同類型的參數(shù)。例如:

      // overloaded function #include

      int divide(int a, int b){ return(a/b);}

      float divide(float a, float b){ return(a/b);}

      int main(){ int x=5,y=2;float n=5.0,m=2.0;cout << divide(x,y);cout << “n”;cout << divide(n,m);cout << “n”;return 0;} 2 2.5 在這個例子里,我們用同一個名字定義了兩個不同函數(shù),當(dāng)它們其中一個接受兩個整型(int)參數(shù),另一個則接受兩個浮點(diǎn)型(float)參數(shù)。編譯器(compiler)通過檢查傳入的參數(shù)的類型來確定是哪一個函數(shù)被調(diào)用。如果調(diào)用傳入的是兩個整數(shù)參數(shù),那么是原型定義中有兩個整型(int)參量的函數(shù)被調(diào)用,如果傳入的是兩個浮點(diǎn)數(shù),那么是原型定義中有兩個浮點(diǎn)型(float)參量的函數(shù)被調(diào)用。

      為了簡單起見,這里我們用的兩個函數(shù)的代碼相同,但這并不是必須的。你可以讓兩個函數(shù)用同一個名字同時完成完全不同的操作。

      Inline 函數(shù)(inline functions)

      inline 指令可以被放在函數(shù)聲明之前,要求該函數(shù)必須在被調(diào)用的地方以代碼形式被編譯。這相當(dāng)于一個宏定義(macro)。它的好處只對短小的函數(shù)有效,這種情況下因?yàn)楸苊饬苏{(diào)用函數(shù)的一些常規(guī)操作的時間(overhead),如參數(shù)堆棧操作的時間,所以編譯結(jié)果的運(yùn)行代碼會更快一些。

      它的聲明形式是:

      inline type name(arguments...){ instructions...} 它的調(diào)用和其他的函數(shù)調(diào)用一樣。調(diào)用函數(shù)的時候并不需要寫關(guān)鍵字inline,只有在函數(shù)聲明前需要寫。

      遞歸(Recursivity)

      遞歸(recursivity)指函數(shù)將被自己調(diào)用的特點(diǎn)。它對排序(sorting)和階乘(factorial)運(yùn)算很有用。例如要獲得一個數(shù)字n的階乘,它的數(shù)學(xué)公式是: n!= n *(n-1)*(n-2)*(n-3)...* 1 更具體一些,5!(factorial of 5)是: 5!= 5 * 4 * 3 * 2 * 1 = 120 而用一個遞歸函數(shù)來實(shí)現(xiàn)這個運(yùn)算將如以下代碼: // factorial calculator #include

      long factorial(long a){ if(a > 1)return(a * factorial(a-1));else return(1);}

      int main(){ long l;cout << “Type a number: ”;cin >> l;cout << “!” << l << “ = ” << factorial(l);return 0;} Type a number: 9!9 = 362880 注意我們在函數(shù)factorial中是怎樣調(diào)用它自己的,但只是在參數(shù)值大于1的時候才做調(diào)用,因?yàn)榉駝t函數(shù)會進(jìn)入死循環(huán)(an infinite recursive loop),當(dāng)參數(shù)到達(dá)0的時候,函數(shù)不繼續(xù)用負(fù)數(shù)乘下去(最終可能導(dǎo)致運(yùn)行時的堆棧溢出錯誤(stack overflow error)。

      這個函數(shù)有一定的局限性,為簡單起見,函數(shù)設(shè)計(jì)中使用的數(shù)據(jù)類型為長整型(long)。在實(shí)際的標(biāo)準(zhǔn)系統(tǒng)中,長整型long無法存儲12!以上的階乘值。

      函數(shù)的聲明(Declaring functions)

      到目前為止,我們定義的所有函數(shù)都是在它們第一次被調(diào)用(通常是在main中)之前,而把main 函數(shù)放在最后。如果重復(fù)以上幾個例子,但把main 函數(shù)放在其它被它調(diào)用的函數(shù)之前,你就會遇到編譯錯誤。原因是在調(diào)用一個函數(shù)之前,函數(shù)必須已經(jīng)被定義了,就像我們前面例子中所做的。

      但實(shí)際上還有一種方法來避免在main 或其它函數(shù)之前寫出所有被他們調(diào)用的函數(shù)的代碼,那就是在使用前先聲明函數(shù)的原型定義。聲明函數(shù)就是對函數(shù)在的完整定義之前做一個短小重要的聲明,以便讓編譯器知道函數(shù)的參數(shù)和返回值類型。它的形式是:

      type name(argument_type1, argument_type2,...);它與一個函數(shù)的頭定義(header definition)一樣,除了:

      ? 它不包括函數(shù)的內(nèi)容,也就是它不包括函數(shù)后面花括號{}內(nèi)的所有語句。? 它以一個分號semicolon sign(;)結(jié)束。

      ? 在參數(shù)列舉中只需要寫出各個參數(shù)的數(shù)據(jù)類型就夠了,至于每個參數(shù)的名字可以寫,也可以不寫,但是我們建議寫上。例如:

      // 聲明函數(shù)原型

      #include

      void odd(int a);void even(int a);

      int main(){ int i;do { cout << “Type a number:(0 to exit)”;cin >> i;odd(i);} while(i!=0);return 0;}

      void odd(int a){ if((a%2)!=0)cout << “Number is odd.n”;else even(a);}

      void even(int a){ if((a%2)==0)cout << “Number is even.n”;else odd(a);} Type a number(0 to exit): 9 Number is odd.Type a number(0 to exit): 6 Number is even.Type a number(0 to exit): 1030 Number is even.Type a number(0 to exit): 0 Number is even.這個例子的確不是很有效率,我相信現(xiàn)在你已經(jīng)可以只用一半行數(shù)的代碼來完成同樣的功能。但這個例子顯示了函數(shù)原型(prototyping functions)是怎樣工作的。并且在這個具體的例子中,兩個函數(shù)中至少有一個是必須定義原型的。這里我們首先看到的是函數(shù)odd 和even的原型: void odd(int a);void even(int a);這樣使得這兩個函數(shù)可以在它們被完整定義之前就被使用,例如在main中被調(diào)用,這樣main就可以被放在邏輯上更合理的位置:即程序代碼的開頭部分。

      盡管如此,這個程序需要至少一個函數(shù)原型定義的特殊原因是因?yàn)樵趏dd 函數(shù)里需要調(diào)用even 函數(shù),而在even 函數(shù)里也同樣需要調(diào)用odd函數(shù)。如果兩個函數(shù)任何一個都沒被提前定義原型的話,就會出現(xiàn)編譯錯誤,因?yàn)榛蛘遫dd 在even 函數(shù)中是不可見的(因?yàn)樗€沒有被定義),或者even 函數(shù)在odd函數(shù)中是不可見的。

      很多程序員建議給所有的函數(shù)定義原型。這也是我的建議,特別是在有很多函數(shù)或函數(shù)很長的情況下。把所有函數(shù)的原型定義放在一個地方,可以使我們在決定怎樣調(diào)用這些函數(shù)的時候輕松一些,同時也有助于生成頭文件。

      第三章 高級數(shù)據(jù)類型(Advanced Data)1.數(shù)組 Arrays 2.字符序列

      Characters Sequences 3.指針 Pointers 4.動態(tài)內(nèi)存分配 Dynamic memory 5.數(shù)據(jù)結(jié)構(gòu) Data Structures 6.自定義數(shù)據(jù)類型

      User defined data types 3.1 數(shù)組(Arrays)

      數(shù)組(Arrays)是在內(nèi)存中連續(xù)存儲的一組同種數(shù)據(jù)類型的元素(變量),每一數(shù)組有一個唯一名稱,通過在名稱后面加索引(index)的方式可以引用它的每一個元素。

      也就是說,例如我們有5個整型數(shù)值需要存儲,但我們不需要定義5個不同的變量名稱,而是用一個數(shù)組(array)來存儲這5個不同的數(shù)值。注意數(shù)組中的元素必須是同一數(shù)據(jù)類型的,在這個例子中為整型(int)。

      例如一個存儲5個整數(shù)叫做billy的數(shù)組可以用下圖來表示:

      這里每一個空白框代表數(shù)組的一個元素,在這個例子中為一個整數(shù)值。白框上面的數(shù)字0 到4 代表元素的索引(index)。注意無論數(shù)組的長度如何,它的第一個元素的索引總是從0開始的。

      同其它的變量一樣,數(shù)組必須先被聲明然后才能被使用。一種典型的數(shù)組聲明顯示如下: type name [elements];這里type 是可以使任何一種有效的對象數(shù)據(jù)類型(object type),如 int, float...等,name 是一個有效地變量標(biāo)識(identifier),而由中括號[]引起來的elements 域指明數(shù)組的大小,即可以存儲多少個元素。

      因此,要定義上面圖中顯示的 billy 數(shù)組,用一下語句就可以了: int billy [5];備注:在定義一個數(shù)組的時候,中括號[]中的elements 域必須是一個常量數(shù)值,因?yàn)閿?shù)組是內(nèi)存中一塊有固定大小的靜態(tài)空間,編譯器必須在編譯所有相關(guān)指令之前先能夠確定要給該數(shù)組分配多少內(nèi)存空間。

      初始化數(shù)組(Initializing arrays)當(dāng)聲明一個本地范圍內(nèi)(在一個函數(shù)內(nèi))的數(shù)組時,除非我們特別指定,否則數(shù)組將不會被初始化,因此它的內(nèi)容在我們將數(shù)值存儲進(jìn)去之前是不定的。如果我們聲明一個全局?jǐn)?shù)組(在所有函數(shù)之外),則它的內(nèi)容將被初始化為所有元素均為0。因此,如果全局范圍內(nèi)我們聲明: int billy [5];那么billy 中的每一個元素將會被初始化為0:

      另外,我們還可以在聲明一個變量的同時把初始值付給數(shù)組中的每一個元素,這個賦值用花括號{ }來完成。例如:

      int billy [5] = { 16, 2, 77, 40, 12071 };這個聲明將生成如下數(shù)組:

      花括號中我們要初始化的元素?cái)?shù)值個數(shù)必須和數(shù)組聲明時方括號[ ]中指定的數(shù)組長度相符。例如,在上面例子中數(shù)組billy 聲明中的長度為5,因此在后面花括號中的初始值也有5個,每個元素一個數(shù)值。

      因?yàn)檫@是一種信息的重復(fù),因此C++允許在這種情況下數(shù)組[ ]中為空白,而數(shù)組的長度將有后面花括號{}中數(shù)值的個數(shù)來決定,如下例所示。int billy [] = { 16, 2, 77, 40, 12071 };存取數(shù)組中數(shù)值(Access to the values of an Array)在程序中我們可以讀取和修改數(shù)組任一元素的數(shù)值,就像操作其他普通變量一樣。格式如下: name[index] 繼續(xù)上面的例子,數(shù)組billy 有5個元素,其中每一元素都是整型int,我們引用其中每一個元素的名字分別為如下所示:

      例如,要把數(shù)值75存入數(shù)組billy 中第3個元素的語句可以是: billy[2] = 75;又例如,要把數(shù)組billy 中第3個元素的值賦給變量a,我們可以這樣寫: a = billy[2];因此,在所有使用中,表達(dá)式billy[2]就像任何其他整型變量一樣。

      注意數(shù)組billy 的第3個元素為billy[2],因?yàn)樗饕?index)從0開始,第1個元素是billy[0],第2個元素是billy[1],因此第3個是 billy[2]。同樣的原因,最后一個元素是billy[4]。如果我們寫billy[5],那么是在使用billy的第6個元素,因此會超出數(shù)組的長度。

      在C++ 中對數(shù)組使用超出范圍的index是合法的,這就會產(chǎn)生問題,因?yàn)樗粫a(chǎn)生編譯錯誤而不易被察覺,但是在運(yùn)行時會產(chǎn)生意想不到的結(jié)果,甚至導(dǎo)致嚴(yán)重運(yùn)行錯誤。超出范圍的index 之所以合法的原因我們在后面學(xué)習(xí)指針(pointer)的時候會了解。學(xué)到這里,我們必須能夠清楚的了解方括號[ ]在對數(shù)組操作中的兩種不同用法。它們完成兩種任務(wù):一種是在聲明數(shù)組的時候定義數(shù)組的長度;另一種是在引用具體的數(shù)組元素的時候指明一個索引號(index)。我們要注意不要把這兩種用法混淆。int billy[5];// 聲明新數(shù)組(以數(shù)據(jù)類型名稱開頭)billy[2] = 75;// 存儲數(shù)組的一個元素 其它合法的數(shù)組操作:

      billy[0] = a;// a為一個整型變量 billy[a] = 75;b = billy [a+2];billy[billy[a]] = billy[2] + 5;

      // arrays example #include

      int billy [ ] = {16, 2, 77, 40, 12071};int n, result=0;

      int main(){ for(n=0;n<5;n++){ result += billy[n];}

      cout << result;return 0;} 12206

      多維數(shù)組(Multidimensional Arrays)

      多維數(shù)組(Multidimensional Arrays)可以被描述為數(shù)組的數(shù)組。例如,一個2維數(shù)組(bidimensional array)可以被想象成一個有同一數(shù)據(jù)類型的2維表格。

      jimmy 顯示了一個整型(int)的3x5二維數(shù)組,聲明這一數(shù)組的的方式是: int jimmy [3][5];而引用這一數(shù)組中第2列第4排元素的表達(dá)式為:jimmy[1][3]

      (記住數(shù)組的索引總是從0開始)。多維數(shù)組(Multidimensional arrays)并不局限于2維。如果需要,它可以有任意多維,雖然需要3維以上的時候并不多。但是考慮一下一個有很多維的數(shù)組所需要的內(nèi)存空間,例如: char century [100][365][24][60][60];給一個世紀(jì)中的每一秒賦一個字符(char),那么就是多于30億的字符!如果我們定義這樣一個數(shù)組,需要消耗3000M的內(nèi)存。

      多維數(shù)組只是一個抽象的概念,因?yàn)槲覀冎恍枰迅鱾€索引的乘積放入一個簡單的數(shù)組中就可以獲得同樣的結(jié)果。例如:

      int jimmy [3][5];效果上等價于 int jimmy [15];(3 * 5 = 15)唯一的區(qū)別是編譯器幫我們記住每一個想象中的維度的深度。下面的例子中我們就可以看到,兩段代碼一個使用2維數(shù)組,另一個使用簡單數(shù)組,都獲得同樣的結(jié)果,即都在內(nèi)存中開辟了一塊叫做jimmy的空間,這個空間有15個連續(xù)地址位置,程序結(jié)束后都在相同的位置上存儲了相同的數(shù)值,如后面圖中所示: // multidimensional array #include #define WIDTH 5 #define HEIGHT 3

      int jimmy [HEIGHT][WIDTH];int n,m;

      int main(){ for(n=0;n

      return 0;} // pseudo-multidimensional array #include #define WIDTH 5 #define HEIGHT 3

      int jimmy [HEIGHT * WIDTH];int n,m;

      int main(){ for(n=0;n

      #define HEIGHT 4 而不需要對程序的其他部分作任何修改。

      數(shù)組參數(shù)(Arrays as parameters)

      有時候我們需要將數(shù)組作為參數(shù)傳給函數(shù)。在C++ 中將一整塊內(nèi)存中的數(shù)值作為參數(shù)完整的傳遞給一個函數(shù)是不可能的,即使是一個規(guī)整的數(shù)組也不可能,但是允許傳遞它的地址。它們的實(shí)際作用是一樣的,但傳遞地址更快速有效。

      要定義數(shù)組為參數(shù),我們只需要在聲明函數(shù)的時候指明參數(shù)數(shù)組的基本數(shù)據(jù)類型,一個標(biāo)識后面再跟一對空括號[]就可以了。例如以下的函數(shù): void procedure(int arg[])接受一個叫做arg的整型數(shù)組為參數(shù)。為了給這個函數(shù)傳遞一個按如下定義的數(shù)組: int myarray [40];其調(diào)用方式可寫為: procedure(myarray);下面我們來看一個完整的例子: // arrays as parameters #include

      void printarray(int arg[ ], int length){ for(int n=0;n

      int main(){ int firstarray[ ] = {5, 10, 15};int secondarray[ ] = {2, 4, 6, 8, 10};printarray(firstarray,3);printarray(secondarray,5);return 0;} 5 10 15 2 4 6 8 10 可以看到,函數(shù)的第一個參數(shù)(int arg[ ])接受任何整型數(shù)組為參數(shù),不管其長度如何。因此,我們用了第2個參數(shù)來告知函數(shù)我們傳給它的第一個參數(shù)數(shù)組的長度。這樣函數(shù)中打印數(shù)組內(nèi)容的for 循環(huán)才能知道需要檢查的數(shù)組范圍。

      在函數(shù)的聲明中也包含多維數(shù)組參數(shù)。定義一個3維數(shù)組(tridimensional array)的形式是:

      base_type[ ][depth][depth] 例如,一個函數(shù)包含多維數(shù)組參數(shù)的函數(shù)可以定義為: void procedure(int myarray[ ][3][4])注意第一對括號[ ]中為空,而后面兩對不為空。這是必須的,因?yàn)榫幾g器必須能夠在函數(shù)中確定每一個增加的維度的深度。

      數(shù)組作為函數(shù)的參數(shù),不管是多維數(shù)組還是簡單數(shù)組,都是初級程序員容易出錯的地方。建議閱讀章節(jié)3.3, 指針(Pointers),以便更好的理解數(shù)組(arrays)是如何操作的。

      3.2 字符序列(Character Sequences)

      前面基礎(chǔ)知識部分講C++變量類型的時候,我們已經(jīng)提到過C++的標(biāo)準(zhǔn)函數(shù)庫提供了一個string類來支持對字符串的操作。然而,字符串實(shí)際就是一串連續(xù)的字符序列,所以我們也可以用簡單的字符數(shù)組來表示它。例如,下面這個數(shù)組: char jenny [20];是一個可以存儲最多20個字符類型數(shù)據(jù)的數(shù)組。你可以把它想象成:

      理論上這數(shù)組可以存儲長度為20的字符序列,但是它也可以存儲比這短的字符序列,而且實(shí)際中常常如此。例如,jenny 在程序的某一點(diǎn)可以只存儲字符串“Hello” 或者“Merry christmas”。因此,既然字符數(shù)組經(jīng)常被用于存儲短于其總長的字符串,就形成了一種習(xí)慣在字符串的有效內(nèi)容的結(jié)尾處加一個空字符(null character)來表示字符結(jié)束,它的常量表示可寫為0 或'