官术网_书友最值得收藏!

4.13 示例

現在我們給出幾個具體的示例程序,它們都使用了本章講述的C++/C基礎知識,供C++/C初級程序員學習。

例1:從鍵盤輸入一行字符,直到按下回車鍵,然后將所有字符轉換成大寫字符并反序輸出。

從鍵盤讀入字符使用getchar()庫函數,讀入字符串使用gets()庫函數,因此需要預先申請在內存中保存字符串的緩沖區。但是我們無法預知用戶到底會輸入多少個字符才結束,因此要預留足夠的空間。轉換工作使用庫函數toupper()完成,輸出字符使用putchar()庫函數。完整的程序見示例4-18。

示例4-18

                #include <stdio.h>
                #include <stdlib.h>
                #include <string.h>
                int main(void)
                {
                      char temp[255] = { '\0' };
                      printf("Input a string, then press <CR> : \n");
                      gets(temp);
                          /*
                          *  或者使用:int i=0;
                          *          while((temp[i]=getchar())!='\n')i++;
                          *          temp[i]='\0';
                          */
                      unsigned int strLen = strlen(temp);
                      for(int j = strLen -1; j >= 0; j--) {
                          temp[j] = toupper(temp[j]);
                          putchar(temp[j]);
                      }
                      putchar('\n');
                      return 0;
                }

例2:計算正整數n的階乘。可以使用迭代法計算也可以使用遞歸法計算,我們將在第7章中給出遞歸法的程序。注意這種計算可能導致結果“上溢”(試著輸入20并查看輸出)。程序見示例4-19。

示例4-19

                #include <stdio.h>
                int main(void)
                {
                  unsigned long n = 0, fact = 1;
                  printf("Input a positive number : ");
                  scanf("%d", &n);
                  for(unsigned int k = 1; k <= n; k++)
                      fact = fact * k;
                  printf("The factorial of %d is %d: \n", n, fact);
                  return 0;
                }

例3:輸入一個正整數n,計算斜邊長在n以內的所有可能的邊長為整數的直角三角形的邊長組合。最笨的辦法是使用三重循環,每一重循環都迭代n次。不過這樣檢測出來的三角形有重復的(如<5, 3, 4>和<5, 4, 3>是同一個三角形),而且性能太低,執行了許多無謂的循環檢測。我們僅檢測斜邊和一條直角邊固定的情況下,另一條直角邊大于或等于第一條直角邊并小于斜邊的情況就可以了。不過這樣還是執行了一些無用的檢測。我們知道,如果斜邊和第一條直角邊固定,則第二條直角邊必定小于等于 的整數部分的值,因此我們按照這個算法來搜索。程序見示例4-20,讀者可能還有更高效率的解法,請編程試一試。

示例4-20

                #include <stdio.h>
                #include <math.h>
                int main(void)
                {
                }
                    unsigned int n = 0, count = 0;
                    printf ("Input a positive number : ");
                    scanf ("%u", &n);
                    printf ("The list of right-angled triangles: \n");
                    for(unsigned int r=1;r<=n;r++){  /*斜邊r從1到n迭代*/
                        unsigned long rsquare = r * r;
                      for(unsigned int p=1;p<r;p++){  /*第一條直角邊p從1到r迭代*/
                          unsigned int psquare = p * p;
                          unsigned int w = (unsigned int)sqrt (rsquare - psquare);
                            for( unsigned int q = p; q <= w; q++) { /*第二條直角邊q從p到w迭代*/
                              if( rsquare == (psquare + (q * q) ) ) {
                                  printf ("%u\t\t%u\t\t%u \n", r, p, q);
                                  count++;
                              }
                             }
                          }
                      }
                    if(count == 0) {
                            printf ("No such right-angled triangles!\n");
                    }else {
                            printf ("There are %d right-angled triangles in total!\n", count);
                    }
                    return 0;
                }

計算機不僅可以解決數學領域的復雜計算,還可以通過計算來解決邏輯推理難題。現在的“人工智能”就是利用計算機“不知疲倦”的計算能力來進行定理證明、邏輯推理和決策支持等工作的。

例4:協助破案。假設已經查清,有A、B、C、D、E五個嫌疑人可能參與制造了一起銀行搶劫案,但是不知道其中到底哪幾個人是真正的案犯。不過,有確鑿證據表明:

① 如果A參與了作案,則B一定也會參與。

② B和C兩人中只有一人參與了作案。

③ C和D要么都參與了作案,要么都沒有參與。

④ D和E兩個人中至少有一人參與作案。

⑤ 如果E作案,則A和D一定參與作案。

是不是有點繞口?我們可以用數理邏輯中的正規表達式來表示上述論斷:

① A→B

②(B∧?C)∨(?B∧C)

③(C∧D)∨(?C∧?D)

④(D∨E)

⑤ E→(A∧D)

我們現在用1(可理解為TRUE)表示作案,0(可理解為FALSE)表示未作案,則每個人的取值范圍就是{0,1}。然后我們在5個人取值的所有可能的組合空間中進行搜索,如果某個組合同時滿足這5條線索,那么它就是本案的答案了。上述正規表達式可以進一步表示為下列C++/C邏輯表達式:

① A == 0 ||(A == 1 && B == 1)

② B + C == 1

③ C == D

④ D + E >= 1

⑤ E == 0 ||(E == 1 && A == 1 && D == 1)

我們用另一個變量sum來表示組合空間中某一個組合能夠同時滿足的論斷個數,如果出現了這樣一個組合——它同時滿足了這5條論斷——那么它就是我們要找的組合。當然,同時滿足所有論斷的組合可能不止一個,因此我們有必要搜索整個組合空間(雖然在本案中這種情況不應該存在,但是在做其他類似的搜索時不要忘記這一點)。程序見示例4-21。

示例4-21

      #include <stdio.h>
      int main (void)
      {
          int count=0;      // 滿足所有條件的答案個數
          int sum=0;       // 累計滿足的條件個數
          int A, B, C, D, E;
          for ( A = 0; A < 2; A++) {
              for ( B = 0; B < 2; B++) {
                      for ( C = 0; C < 2; C++) {
                          for ( D = 0; D < 2; D++) {
                            for ( E = 0; E < 2; E++) {
                                sum=0;   // 計數器清0
                                sum += ( A == 0 || ( A == 1 && B == 1 ) ) ? 1 : 0;
                                sum += ( ( B + C ) == 1 ) ? 1 : 0;
                                sum += ( C == D ) ? 1 : 0;
                                sum += ( ( D + E ) >= 1 ) ? 1 : 0;
                                sum += ( E == 0 || ( E == 1 && A == 1 && D == 1 ) ) ? 1 : 0;
                                if(sum==5){   // 找到一個滿足所有條件的組合
                                    count++;
                                    printf ("http:// This is the %d th answer:\n", count);
                                    printf ("Suspect A is %s.\n", ( A == 1 ) ? "a criminal" : "not a
                                        criminal");
                                    printf ("Suspect B is %s.\n", ( B == 1 ) ? "a criminal" : "not a
                                        criminal");
                                    printf ("Suspect C is %s.\n", ( C == 1 ) ? "a criminal" : "not a
                                        criminal");
                                    printf ("Suspect D is %s.\n", ( D == 1 ) ? "a criminal" : "not a
                                        criminal");
                                    printf ("Suspect E is %s.\n", ( E == 1 ) ? "a criminal" : "not a
                                        criminal");
                                    printf ("\n");
                                    }
                                }
                            }
                          }
                      }
              }
          return 0;
      }

輸出結果如下:

      // This is the 1 th answer:
            Suspect A is not a criminal.
            Suspect B is not a criminal.
            Suspect C is a criminal.
            Suspect D is a criminal.
      Suspect E is not a criminal.

在這個例子中,goto語句還是很有用的!

例5:數值計算。最后我們舉一個數值計算的例子:使用迭代法計算超越方程f (x)= 0的近似解。

理論證明:最高次冪不高于4的一元方程的根可用根式來表示,而高于4次的則一般不存在根的解析表達式,對于超越方程則更不太可能存在。所以對于超越方程,要借助數值計算來尋找方程的近似解。

已知方程x6 -8 x -4 = 0,求它的近似解,要求誤差小于10-10

迭代法是這樣的:首先將方程f (x) = 0改寫為如下的等價形式:

x = g (x)

然后在可能的根區間[a, b]上任取一點x0,代入g (x),得到x1 = g (x0),一般說來x1x0;再把x1代入g (x),得到x2 = g (x1);……這樣就計算出了一系列值:

x0, x1, x2, …, xn-1, xn, …

當(xn - xn-1)的絕對值小于給定的誤差時就可以認為xn是所求的根了。

我們把方程改寫為 。取x0 = 1,程序見示例4-22。

示例4-22

            #include <stdio.h>
            #include <math.h>
            double g(double x);
            int main(void)
            {
              double x0 = 1, x1 = 0;
              int count = 0;
              printf("x%d = %10f\n", count, x0);
              while( fabs( x1- x0 ) >= 1e-10 ){
                  x1 = x0;
                  x0 = g(x1);
                  count++;
                  printf("x%d = %10f\n", count, x0);
              }
              printf("approximate x = %10f\n", x0);
              return 0;
            }
            double g(double x)
            {
              return pow(x, 6) / 8.0-0.5;
            }
            x0=   1.000000
            x1=  -0.375000
            x2=  -0.499652
            x3=  -0.498055
            x4=  -0.498092
            x5=  -0.498091
            x6=  -0.498091
            x7=  -0.498091
            x8=  -0.498091
            approximate x=  -0.498091

我們看到,在第5次迭代后就已經找到了滿足誤差條件的解,所以后面的迭代就是不必要的了。

主站蜘蛛池模板: 玛纳斯县| 宁蒗| 勐海县| 施秉县| 河北区| 宝山区| 延津县| 榆树市| 南漳县| 城市| 灵石县| 偃师市| 弥渡县| 德惠市| 会同县| 礼泉县| 通海县| 波密县| 河东区| 福贡县| 余江县| 陈巴尔虎旗| 云浮市| 乌兰县| 涞水县| 鹤壁市| 科技| 玉龙| 壶关县| 常熟市| 徐水县| 湄潭县| 重庆市| 大邑县| 肇东市| 易门县| 成安县| 宜宾县| 通河县| 扎鲁特旗| 炎陵县|