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

循環(huán)結(jié)構(gòu)

使用循環(huán)結(jié)構(gòu)的程序可以解決一些按一定規(guī)則重復(fù)執(zhí)行的問題而無須重復(fù)書寫源代碼,這是程序設(shè)計中最能發(fā)揮計算機(jī)特長的程序結(jié)構(gòu)。首先介紹while語句。

while語句是用來實現(xiàn)“當(dāng)型”循環(huán)結(jié)構(gòu),其一般形式如下:

    while(表達(dá)式成立)
     執(zhí)行一條語句;或者是:
    
     while(表達(dá)式成立)
    {
     語句1;
     語句2;
     ...
    }

即當(dāng)表達(dá)式的值為真時,執(zhí)行while語句中的內(nèi)嵌語句。

例如,求1+2+3+…+100的值的程序可以這樣寫:

1 //計算1+2+3+…+100的值
2 #include <iostream>
3 using namespace std;
4 
5 int main()
6 {
7  int i=1,sum=0;
8  while(i<=100)           //當(dāng)i<=100時,則執(zhí)行循環(huán)體內(nèi)的語句
9  {
10   sum=sum+i;
11   i++;
12  }
13  cout<<sum<<endl;
14  system("pause");
15  return 0;
16 }

【上機(jī)實踐】 計算15的階乘

試計算1×2×3×4×…×15的值。

【例題描述】 電文保密

魔法世界電報局的電文保密的規(guī)律是將每個英文字母變成其后的第4個字母,如A變成E,a變成e。最后的4個大寫字母W、X、Y、Z分別變?yōu)锳、B、C、D。非字母字符不變。輸入一行字符,要求輸出相應(yīng)的密碼。

1 //電文保密
2 #include <iostream>
3 #include <math.h>
4 using namespace std;
5 
6 int main()
7 {
8  char c;
9  while((c=getchar())!='\n')
10  {
11   if((c>='a' && c<='z') || (c>='A' && c<='Z'))  //當(dāng)字符為英文字母時
12   {
13    c=c+4;
14    if(c>'Z' && c<='Z'+4 || c>'z')
15     c=c-26;
16   }
17   cout<<c;
18  }
19  system("pause");
20  return 0;
21 }

第9行的語句并不是從終端敲入一個字符馬上輸出一個字符。而是直到按Enter鍵后將所有字符送入內(nèi)存緩沖區(qū),然后每次從緩沖區(qū)讀一個字符,再輸出該字符。

【例題描述】 求魔法力

每個魔法學(xué)徒的魔法力是不同的,試編寫一個程序,從鍵盤讀入每個學(xué)徒的魔法力,求全部魔法學(xué)徒的魔法力總和。當(dāng)用戶輸入0時,程序結(jié)束。

1 //求魔法力
2 #include <iostream>
3 using namespace std;
4 
5 int main()
6 {
7  int sum=0,n;〖BHDG1*4〗
8  while(true)        //表示永遠(yuǎn)為真,即永遠(yuǎn)循環(huán),也可以用while(1)
9  {
10   cout<<"輸入一個整數(shù)(0表示結(jié)束)";
11   cin>>n;
12   if(n==0)
13    break;//跳出該層循環(huán)
14   sum+=n;
15  }
16  cout<<"總和為: "<<sum<<endl;
17  system("pause");
18  return 0;
19 }

【上機(jī)實踐】 火柴游戲

魔法學(xué)院流行一種火柴游戲,即21根火柴,兩人輪流取,每人可取1~4根,不可多取,也不可不取,誰取最后一根誰輸,假設(shè)楚繼光先取,張琪曼后取,如何編程讓張琪曼贏。

這是一道簡單的博弈題,取勝策略:只需讓后方取火柴的數(shù)量與前方取火柴數(shù)量之和等于5即可。

1 設(shè)變量num=21,即火柴數(shù)
2 設(shè)變量man表示楚繼光,可設(shè)另一個變量表示張琪曼,也可以不設(shè)
3 當(dāng)火柴未取完時
4 {
5   屏幕輸出現(xiàn)在的火柴數(shù)
6   輸入這一次楚繼光取的火柴數(shù)即變量man
7   如果楚繼光取的火柴數(shù)違反規(guī)定
8     coutinue;          //無效重取,即本次循環(huán)無效,繼續(xù)下輪循環(huán)
9   否則輸出張琪曼取的火柴數(shù)(即5-man)和剩余的火柴數(shù)(即num-5)
10   更新現(xiàn)在的火柴數(shù)即num=num-5
11 }
12 屏幕輸出"你輸了! "

【上機(jī)實踐】 整數(shù)猜想

魔法世界的魔法師們相信“萬法歸一”的說法,即天下所有的學(xué)問,到了最后都是相通的。令人驚訝的是,居然有魔法師宣稱從數(shù)學(xué)角度證明了該說法的正確性,這就是所謂的整數(shù)猜想:即對于任意給定的大于1的一個正整數(shù),如果它是一個偶數(shù)請將其除以2,若是奇數(shù)就將其乘以3加1,對其運(yùn)算結(jié)果,如果它不是1,則重復(fù)上述操作經(jīng)過。經(jīng)過若干步操作后,總會得到結(jié)果1。

對于這道題,由于事先無法知道要經(jīng)過多少步才能得到結(jié)果1。所以用while是比較合適的。剩下的就簡單了,模擬運(yùn)算即可。

偽代碼如下所示:

1 輸入任一大于1的正整數(shù)i
2 當(dāng)(i>1)時
3 {
4  如果i為偶數(shù)時
5   i=i/2
6  否則
7   i=i*3+1
8  輸出更新后的i值
9 }

【上機(jī)實踐】 求圓周率

圓周率,一般以π來表示,是一個在數(shù)學(xué)及物理學(xué)普遍存在的數(shù)學(xué)常數(shù)。它定義為圓形之周長與直徑之比。如圖2.5所示,早在遠(yuǎn)古時代的中國,有一位叫祖沖之的數(shù)學(xué)家第一次將圓周率(π)值計算到小數(shù)點(diǎn)后七位,即3.1415926到3.1415927之間。而魔法世界的魔法師對于圓周率的精確度相求是相當(dāng)高的,例如用35位精度的圓周率值來計算一個能把太陽系包起來的一個圓的周長,誤差還不到質(zhì)子直徑的百萬分之一。

圖2.5

現(xiàn)用π/4=1-1/3+1/5-1/7+…公式求π的近似值,直到某一項的絕對值小于10-6為止。

由公式π/4=1-1/3+1/5-1/7+…可推出π=(1-1/3+1/5-1/7+…)×4,問題是(1-1/3+1/5-1/7+…)的值怎么算呢?

設(shè)變量ans為最終結(jié)果,初始值0,使用while()循環(huán)進(jìn)行逐項累加直到某一項的絕對值小于10-6為止。

但是累加每一項的時候,分母在不斷地遞增(每次多2),所以需要定義一個變量來保存分母的值,此外每一項的正負(fù)號也在不斷變換,這可能也需要一個變量來表示,例如x=-x即可完成正負(fù)號的轉(zhuǎn)變。

偽代碼如下所示:

1 float n=1.0             //n表示分母,初始為1 
2 float t=1,ans=0 //t為循環(huán)中要加的每一項
3 
4 則當(dāng)(t的絕對值>1e-6)時 //1e-6即1乘以10的-6次方
5 {
6  ans=ans+t//累加
7  更新分母的值
8  改變正負(fù)號
9  更新t的值
10 }
11 輸出ans*4的值

【上機(jī)實踐】 求最大公約數(shù)和最小公倍數(shù)

輸入兩個正整數(shù)a和b,求其最大公約數(shù)和最小公倍數(shù)。

我們使用輾轉(zhuǎn)相除法(歐幾里得算法)來求最大公約數(shù),即將大的數(shù)a除以小的數(shù)b,得余數(shù)c,a=b,b=c,如此反復(fù)直到余數(shù)為0,此時的b為最大公約數(shù)。

例如a=24,b=10,則c=24%10=4,

由a=b,b=c得a=10,b=4,則c=10%4=2

由a=b,b=c得a=4,b=2,則c=4%2=0,故最大公約數(shù)為b=2。

最小公倍數(shù)公式為初始數(shù)a×初始數(shù)b/最大公約數(shù)。

偽代碼如下所示:

1 輸入a,b的值
2 如果a<b
3  交換a和b的值
4 當(dāng)(b!=0)
5 {
6  c=a%b
7  a=b
8  b=c
9 }
10 輸出最大公約數(shù)
11 輸出最小公倍數(shù)

【上機(jī)實踐】 求Sn的值

光明系魔法的魔法力增長值遵循Sn=a+aa+aaa+aaaa+…的公式,其中a是一個數(shù)字。例如某學(xué)徒初始魔法力為3,則4年后的魔法力為3+33+333+3333,試求n年后該學(xué)徒的魔法力Sn,其中a,n由鍵盤輸入。

因為年數(shù)n是鍵盤輸入的,所以我們必須控制while結(jié)構(gòu)循環(huán)n次后就結(jié)束,這可以用一個變量充當(dāng)計數(shù)器,每循環(huán)一次,計數(shù)器+1,直到計數(shù)器>n退出循環(huán)即可。

難點(diǎn)是循環(huán)中如果更改需累加的項數(shù),即項數(shù)由a變?yōu)閍a,由aa變?yōu)閍aa…,一個想法是使用a=a×10+a,將a的值擴(kuò)大10倍后再加上a,當(dāng)然這可能需要其他變量的輔助完成才行。

【例題描述】 埃及分?jǐn)?shù)

魔法學(xué)院院長將家中11匹馬分給3個兒子,老大1/2,老二1/4,老三1/6。3個兒子正在無奈之際,鄰居把自己家的馬牽來,老大二分之一,牽走了6匹;老二四分之一,牽走了3匹;老三六分之一,牽走了2匹。一共11匹,分完后,鄰居把自己的馬牽了回去。即11/12=1/2+1/4+1/6。這種分子是1的分?jǐn)?shù),叫作埃及分?jǐn)?shù),因為古代埃及人在進(jìn)行分?jǐn)?shù)運(yùn)算時,只使用分子是1的分?jǐn)?shù)。

現(xiàn)輸入一個真分?jǐn)?shù),請將該分?jǐn)?shù)分解為埃及分?jǐn)?shù)。例如,8/11=1/2+1/5+1/55+1/110。

若真分?jǐn)?shù)a/b中的分子a能整除分母b,則真分?jǐn)?shù)經(jīng)過化簡直接就可以得到埃及分?jǐn)?shù),否則若真分?jǐn)?shù)的分子不能整除分母,則可以從原來的分?jǐn)?shù)中分解出一個分母c=b/a+1的埃及分?jǐn)?shù)。

分解后剩下的部分形成一個新的a/b,即a=a×c-b,b=b×c。繼續(xù)用這種方法將剩余部分反復(fù)分解,最后可得到結(jié)果。

1 //埃及分?jǐn)?shù)
2 #include<iostream>
3 using namespace std;
4 
5 int main()
6 {
7  long int a,b,c;
8  cin>>a>>b;       //輸入分子a和分母b
9  while(1)
10  {
11   if(b%a!=0) //若分子不能整除分母
12    c=b/a+1; //則分解出一個分母為b/a+1的埃及分?jǐn)?shù)
13   else //否則,輸出化簡后的真分?jǐn)?shù)(埃及分?jǐn)?shù))
14   {
15    c=b/a;
16    a=1;
17   }
18 
19   if(a==1) //若分子已經(jīng)為1了
20   {
21    cout<<"1/"<<c;
22    break;  //則結(jié)束
23   }
24   else
25    cout<<"1/"<<c<<"+";
26 
27   a=a*c-b;  //求出余數(shù)的分子
28   b=b*c;   //求出余數(shù)的分母
29 
30   if(a==3)  //若余數(shù)為3,輸出最后兩個埃及分?jǐn)?shù)如3/14=1/7+1/14
31   {
32    cout<<"1/"<<b/2<<"+"<<"1/"<<b;
33    break;
34   }
35  }
36  system("pause");
37  return 0;
38 }

do~while語句的特點(diǎn)是先執(zhí)行循環(huán)體,然后判斷循環(huán)條件是否成立。其一般形式為

  do
     循環(huán)體語句
    while(表達(dá)式);

例如,求1+2+3+…+100的值的程序我們可以這樣寫:

1 //計算1+2+3+…+100的值
2 #include <iostream>
3 using namespace std;
4 
5 int main()
6 {
7  int i=1,sum=0;
8  do
9  {
10   sum=sum+i;
11   i++;
12  } while(i<=100);
13  cout<<sum<<endl;
14  system("pause");
15  return 0;
16 }

while與do~while循環(huán)的比較是while先判斷表達(dá)式是否為真,如果為真才執(zhí)行循環(huán),如果為假則不執(zhí)行循環(huán)。而do~while是先不管表達(dá)式的值為何值,先執(zhí)行循環(huán)體內(nèi)的語句一遍,然后再進(jìn)行表達(dá)式的判斷以決定是否繼續(xù)執(zhí)行該循環(huán)。

注意不要忘了do~while語句結(jié)束后的分號。

【例題描述】 菜單程序的實現(xiàn)

如圖2.6所示,張琪曼要編寫一個小學(xué)生算術(shù)練習(xí)系統(tǒng),該系統(tǒng)的菜單項包括1.加法;2.減法;3.乘法;4.除法;5.退出。編程實現(xiàn)進(jìn)入系統(tǒng)后顯示菜單,等待用戶選擇,然后執(zhí)行相應(yīng)的功能(設(shè)每個子功能暫設(shè)置為一個輸出結(jié)果的功能),執(zhí)行完畢后返回主菜單,直至選擇退出。

圖2.6

1 //菜單程序的實現(xiàn)
2 #include <iostream>
3 using namespace std;
4 
5 int main()
6 {
7  int c;
8  int a,b;
9  do
10  {
11   system("cls");           //清屏
12   cout<<"小學(xué)生算術(shù)練習(xí)系統(tǒng)\n";
13   cout<<" 1.加法\n";
14   cout<<" 2.減法\n";
15   cout<<" 3.乘法\n";
16   cout<<" 4.除法\n";
17   cout<<" 5.退出\n";
18   cout<<"請選擇(1~5): ";
19   cin>>c;
20   if(c!=5)
21   {
22     cout<<"請輸入兩個數(shù),以空格間隔";
23     cin>>a>>b;
24     switch(c)
25     {
26      case 1:cout<<a<<"+"<<b<<"="<<a+b<<endl;break;
27      case 2:cout<<a<<"-"<<b<<"="<<a-b<<endl;break;
28      case 3:cout<<a<<"*"<<b<<"="<<a*b<<endl;break;
29      case 4:if(b!=0)
30           cout<<a<<"/"<<b<<"="<<a/b<<endl;
31         else
32           cout<<"除數(shù)不能為0!";
33         break;
34      default:cout<<"錯誤的輸入,請重新選擇\n"<<endl;
35     }
36     system("pause");
37   }
38   else
39   {
40    cout<<"練習(xí)結(jié)束!\n";
41    break;
42   }
43  }while(1);
44  system("pause");
45  return 0;
46 }

for語句是C++語言里使用最為靈活的語句,它完全可以代替while語句。一般形式如下:

    for(循環(huán)變量賦初值;循環(huán)條件;循環(huán)變量增值)
       表達(dá)式1   表達(dá)式2  表達(dá)式3

它的執(zhí)行過程如下:

(1)先求解表達(dá)式1。

(2)求解表達(dá)式2,若其值為真,則執(zhí)行for語句的內(nèi)嵌語句,然后執(zhí)行下面第(3)步。若為假,則結(jié)束循環(huán),轉(zhuǎn)到第(5)步。

(3)求解表達(dá)式3。

(4)轉(zhuǎn)回上面第(2)步驟繼續(xù)執(zhí)行。

(5)循環(huán)結(jié)束,執(zhí)行for語句下面的一個語句。

例如求1+2+3+…+100的值的程序我們可以這樣寫:

1 //計算1+2+3+…+100的值
2 #include <iostream>
3 using namespace std;
4 
5 int main()
6 {
7  int sum=0,i;          //定義循環(huán)變量i
8  for(i=1;i<=100;i++) //i賦初值; 循環(huán)條件;i每次自增1
9  {
10   sum+=i; //即sum=sum+i
11  }
12  cout<<sum<<endl;
13  system("pause");
14  return 0;
15 }

for語句是很簡單和方便的,使用該語句完全可以替代其他的循環(huán)語句。

表達(dá)式1、2、3可以根據(jù)實際情況省略(注意不可省略分號)。但程序設(shè)計者應(yīng)另外設(shè)法保證循環(huán)能正常結(jié)束。以下幾個程序和上面的程序結(jié)果是一樣的。

程序一:

1 //計算1+2+3+…+100的值
2 #include <iostream>
3 using namespace std;
4 
5 int main()
6 {
7  int sum=0,i=1;             //此處賦初值
8  for(;i<=100;i++)
9  {
10   sum+=i;//即sum=sum+i
11  }
12  cout<<sum<<endl;
13  system("pause");
14  return 0;
15 }

程序二:

1 //計算1+2+3+…+100的值
2 #include <iostream>
3 using namespace std;
4 
5 int main()
6 {
7  int sum=0,i=1;             //此處賦初值
8  for(;i<=100;)
9  {
10   sum+=i; //即sum=sum+i
11   i++; //循環(huán)變量遞增寫在此處
12  }
13  cout<<sum<<endl;
14  system("pause");
15  return 0;
16 }

程序三:

1 //計算1+2+3+…+100的值
2 #include <iostream>
3 using namespace std;
4 
5 int main()
6 {
7  int sum=0,i=1;         //此處賦初值
8  for(;;)
9  {
10   if(i>100) //此處進(jìn)行判斷
11    break;
12   sum+=i; //即sum=sum+i
13   i++; //循環(huán)變量遞增寫在此處
14  }
15  cout<<sum<<endl;
16  system("pause");
17  return 0;
18 }

【上機(jī)實踐】 計算數(shù)列和

墨老師在黑板上寫了一行字:“試編程計算12+22+32+…+502的和?!比缓笳f:“同學(xué)們是不是看到這種題目就很頭痛???我告訴大家,其實解決這種問題很簡單的,吃一片止痛藥就好啦。”

可以用for循環(huán)語句循環(huán)50次累加每一項,用循環(huán)變量表示當(dāng)前計算的項數(shù),求和的每一項為項數(shù)的平方。

【例題描述】 顯示ASCII碼

目前計算機(jī)中用得最廣泛的字符集及其編碼,是由美國國家標(biāo)準(zhǔn)局(ANSI)制定的ASCII碼(American Standard Code for Information Interchange,美國標(biāo)準(zhǔn)信息交換碼),它已被國際標(biāo)準(zhǔn)化組織(ISO)定為國際標(biāo)準(zhǔn),稱為ISO 646標(biāo)準(zhǔn)。請編寫一個程序,顯示ASCII碼為15~127的字符。

參考程序如下所示:

1 //顯示ASCII碼
2 #include <iostream>
3 #include <iomanip>
4 using namespace std;
5 
6 int main()
7 {
8  int i,n=0;
9  for(i=15;i<128;i++)
10  {
11   if (n%10==0 && n>0)
12    cout<<endl;             //每顯示十個換一行
13   cout <<setw(4)<<i<<":"<<(char)i<<" ";
14   n++;
15  }
16  cout<<endl;
17  system("pause");
18  return 0;
19 }

【上機(jī)實踐】 同構(gòu)數(shù)

張琪曼很喜歡研究數(shù)字規(guī)律。她發(fā)現(xiàn)有一些數(shù)值平方后會有一種奇怪的現(xiàn)象,她把會出現(xiàn)這種現(xiàn)象的數(shù)叫“同構(gòu)數(shù)”?!巴瑯?gòu)數(shù)”是指這樣的一種數(shù),會出現(xiàn)在它的平方數(shù)的右端的數(shù)。例如,5是25右邊的數(shù),25是625右邊的數(shù),5和25都是同構(gòu)數(shù)。張琪曼覺得這些數(shù)并不止一兩個,請幫她找出2~10000之間全部同構(gòu)數(shù)。

偽代碼為:

1 for循環(huán)窮舉從2~10000的每一個數(shù)i
2 {
3   計算該數(shù)的平方數(shù)即j
4   依次從后向前比較i和j的位數(shù)是否相等
5   {
6     如果i的所有位數(shù)比較完畢仍然相等
7     則輸出該數(shù)i
8     否則
9     跳出進(jìn)行下一個數(shù)的窮舉
10     }
11 }

【上機(jī)實踐】 求e的近似值

e(指自然底數(shù)e)與圓周率π被認(rèn)為是數(shù)學(xué)中最重要的兩個超越數(shù)(不滿足任何整系數(shù)代數(shù)方程的數(shù),稱超越數(shù))。而且e、π與虛數(shù)i三者之間有一個相當(dāng)有名的關(guān)系式:e(iπ)=-1。通常我們可以通過公式e=1+1/1!+1/2!+1/3!+…計算到它前n項或到某一項小于規(guī)定值作為近似值。試計算e的值計算到前一百項。

計算階乘時無須一遍遍地反復(fù)算,完全可以利用前一項已算法的值遞推出下一項的值,例如當(dāng)計算出5!后,計算6!即為6×5!。

例如某項值為t=1/n!,則下一項即為t/(n+1)。

偽代碼如下所示:

1 定義浮點(diǎn)數(shù)ans=1,t=1
2 for(循環(huán)一百次)
3 {
4  遞推出下一項值t
5  ans+=t            //累加
6 }
7 輸出ans的值

【例題描述】 兔子永生

修羅王在恐怖的冥域中找到了傳說中的不死秘術(shù),為了安全起見,他對一對剛出生的小兔子施展了此秘術(shù),現(xiàn)在假設(shè)秘術(shù)使得所有的兔子都不死,而兔子在出生兩個月后,就有繁殖能力,那么40個月后可以繁殖多少對兔子?

如圖2.7所示:

圖2.7

第一個月小兔子沒有繁殖能力,所以還是一對;

兩個月后,生下一對小兔后總數(shù)共有兩對;

三個月以后,老兔子又生下一對,因為小兔子還沒有繁殖能力,所以一共是三對;

……

這就是有名的斐波那契數(shù)列(Fibonacci),這個數(shù)列有如下特點(diǎn):第1、2兩個數(shù)為1、1。從第3個數(shù)開始,該數(shù)是其前面兩個數(shù)之和。即:1、1、2、3、5、8、13…

1 //兔子永生
2 #include <iostream>
3 using namespace std;
4 
5 int main()
6 {
7  int f1=1,f2=1,i;
8  for(i=1;i<=20;i++)
9  {
10   cout<<f1<<''<<f2; 
11   if(i%2==0)        //當(dāng)一行輸出兩次f1和f2(即4個數(shù)字)的值后另起一行
12    cout<<'\n';
13   f1=f1+f2;
14   f2=f2+f1;
15  }
16  system("pause");
17  return 0;
18 }

【上機(jī)實踐】 求分子序列和

有一分子序列:2/1,3/2,5/3,8/5,13/8,21/13,…,求出這個數(shù)列的前20項之和。

偽代碼為:

1 定義浮點(diǎn)數(shù)a=2,b=1,ans=0;//其中a為分子,b為分母
2 for(循環(huán)20次)
3 {
4  ans=ans+a/b;
5  更新分子a和分母b的值;
6 }
7 輸出ans的值;

【例題描述】 計算圓面積

如圖2.8所示,魔法學(xué)院計劃建設(shè)一個圓形廣場,試依次計算半徑r=1到r=10時的圓面積,直到面積area大于100為止。

圖2.8

1 //計算r=1到r=10時的圓面積,直到面積area大于100為止
2 # include <iostream>
3 using namespace std;
4 int main()
5 {
6  float area;int r;
7  for(r=1;r<=10;r++)
8  {
9   area=3.14*r*r;
10   if(area>100)
11    break;           //跳出當(dāng)前循環(huán)體,執(zhí)行循環(huán)體下面的語句
12   cout<<r<<":area="<<area<<endl;
13  }
14  system("pause");
15  return 0;
16 }

【例題描述】 不能被3整除的數(shù)

與世界上的多數(shù)古代文明相同,魔法世界也認(rèn)為3是一個神圣的數(shù)字,所有能被3整除的數(shù)字也是神圣的數(shù)字,試將100~200之間不能被3整除的數(shù)輸出。

1 //把100~200之間不能被3整除的數(shù)輸出
2 #include <iostream>
3 using namespace std;
4 int main()
5 {
6  int n;
7  for(n=100;n<=200;n++)
8  {
9   if(n%3==0)
10    continue;           //跳出當(dāng)前循環(huán)體,執(zhí)行循環(huán)體下面的語句
11   cout<<n<<' ';
12  }
13  system("pause");
14  return 0;
15 }

break可以用來從循環(huán)體內(nèi)跳出循環(huán)體,即提前結(jié)束循環(huán),接著執(zhí)行循環(huán)下面的語句。break語句不能用于循環(huán)語句和switch語句之外的任何其他語句中。

continue語句與break語句的區(qū)別是:continue語句只結(jié)束本次循環(huán),而不是終止整個循環(huán)的執(zhí)行。而break語句則是結(jié)束整個循環(huán)過程,不再判斷執(zhí)行循環(huán)的條件是否成立。

【例題描述】 九九乘法表

九九乘法表又稱九九乘法歌訣,在《荀子》、《管子》、《淮南子》、《戰(zhàn)國策》等中國古書中就能找到“三九二十七”“六八四十八”“四八三十二”“六六三十六”等句子。試編程輸出九九乘法表。

這道題需要兩層for循環(huán)語句嵌套完成,即:

for(i=1;i<=9;i++) for(j=1;j<=9;j++) cout<<i<<"*"<<j<<"="<<i*j<<' ';

注意兩層for循環(huán)的循環(huán)變量應(yīng)分別定義,即定義i和j。其運(yùn)行順序是執(zhí)行外循環(huán)到內(nèi)循環(huán)時,要先把內(nèi)循環(huán)的所有循環(huán)執(zhí)行完后再跳到外循環(huán)。

1 //九九乘法表
2 #include <iostream>
3 using namespace std;
4 
5 int main()
6 {
7  int i,j;
8  for(i=1;i<=9;i++)
9   for(j=1;j<=9;j++)
10    cout<<i<<'*'<<j<<"="<<i*j<<endl;
11  system("pause");
12  return 0;
13 }

【例題描述】 執(zhí)行任務(wù)

魔法學(xué)院要在A、B、C、D、E、F六個學(xué)員中盡可能多地挑若干人去執(zhí)行一項任務(wù),但有以下限制條件:

(1)A和B兩人中至少去一人;

(2)A和D不能一起去;

(3)A、E和F三人中要派兩人去;

(4)B和C都去或都不去;

(5)C和D兩人中去一個;

(6)若D不去,則E也不去。

問應(yīng)當(dāng)讓哪幾個人去?

用a、b、c、d、e、f六個變量表示六個人是否去執(zhí)行任務(wù)的狀態(tài),變量的值為1,則表示該人去;變量的值為0,則表示該人不參加執(zhí)行任務(wù),根據(jù)題意可寫出表達(dá)式:

a+b>=1 A和B兩人中至少去一人;

a+d!=2 A和D不能一起去;

a+e+f==2 A、E、F三人中要派兩人去;

b+c==0或b+c==2 B和C都去或都不去;

c+d==1 C和D兩人中去一個;

d+e==0或d==1 若D不去,則E也不去(都不去;或D去E隨便)。

上述各表達(dá)式之間的關(guān)系為“與”關(guān)系。窮舉每個人去或不去的各種可能情況,代入上述表達(dá)式中進(jìn)行推理運(yùn)算,使上述表達(dá)式均為“真”的情況就是正確的結(jié)果。

1 //執(zhí)行任務(wù)
2 #include<iostream>
3 using namespace std;
4 
5 int main()
6 {
7  int a,b,c,d,e,f;
8  for(a=1;a>=0;a--)/          /窮舉每個人是否去的所有情況
9   for(b=1;b>=0;b--)    //1:去 0:不去
10    for(c=1;c>=0;c--)
11     for(d=1;d>=0;d--)
12      for(e=1;e>=0;e--)
13       for(f=1;f>=0;f--)
14        if(a+b>=1&&a+d!=2&&a+e+f==2&&
15        (b+c==0||b+c==2)&&c+d==1&&(d+e==0||d==1))
16        {
17         cout<<"a:"<<a<<endl;
18         cout<<"b:"<<b<<endl;
19         cout<<"c:"<<c<<endl;
20         cout<<"d:"<<d<<endl;
21         cout<<"e:"<<e<<endl;
22         cout<<"f:"<<f<<endl;
23        }
24  system("pause");
25  return 0;
26 }

【例題描述】 打印三角形

使用循環(huán)結(jié)構(gòu)打印如下圖形:

      *
     ***
     *****
    *******

參考程序如下所示:

1 //打印三角形
2 #include <iostream>
3 using namespace std;
4 
5 int main()
6 {
7  for(int i=1;i<=4;i++)          //輸出行數(shù)
8  {
9   for(int j=1;j<=4-i;j++) //控制每行輸出的空格數(shù)
10    cout<<' ';
11   for(int j=1;j<=2*i-1;j++) //控制每行輸出的*的個數(shù)
12    cout<<'*';
13   cout<<endl;
14  }
15  system("pause");
16  return 0;
17 }

【上機(jī)實踐】 打印菱形

使用循環(huán)結(jié)構(gòu)打印如下圖形:

      *
     ***
     *****
    *******
     *****
     ***
      *

請完善下面的程序:

1 //打印菱形
2 #include <iostream>
3 using namespace std;
4 
5 int main()
6 {
7  for(int i=-3;i<=3;i++)       //輸出行數(shù)
8  {
9   int k=abs(i);
10   for(_____) //控制輸出每行空格數(shù)
11    cout<<' ';
12   for(_____) //控制輸出每行*號數(shù)
13    cout<<'*';
14   cout<<endl;
15  }
16  system("pause");
17  return 0;
18 }

【上機(jī)實踐】 打印數(shù)字菱形1

使用循環(huán)結(jié)構(gòu)打印如下圖形:

      4
     333
     22222
    1111111
     22222
     333
      4

請完善下面的程序:

1 //打印數(shù)字菱形1
2 #include <iostream>
3 using namespace std;
4 
5 int main()
6 {
7  for(int i=-3;i<=3;i++)       //控制輸出行數(shù)
8  {
9   int k=abs(i);
10   for(_____) //控制輸出每行的空格數(shù)
11    cout<<' ';
12   for(_____)  //控制輸出的數(shù)字
13    cout<<k+1;
14   cout<<endl;
15  }
16  system("pause");
17  return 0;
18 }

【上機(jī)實踐】 打印數(shù)字菱形2

使用循環(huán)結(jié)構(gòu)打印如下圖形:

      1
      212
     32123
    4321234
     32123
     212
      1

參考程序如下所示:

1 //打印數(shù)字菱形2
2 #include <iostream>
3 using namespace std;
4 
5 int main()
6 {
7  for(int i=-3;i<=3;i++)         //控制輸出的行數(shù)
8  {
9   int k=abs(i);
10   for(_____) //控制輸出的空格數(shù)
11    cout<<' ';
12   for(_____) //控制輸出的數(shù)字
13    cout<<_____;
14   cout<<endl;
15  }
16  system("pause");
17  return 0;
18 }

【例題描述】 判斷質(zhì)數(shù)

素數(shù)又稱質(zhì)數(shù)。指在一個大于1的自然數(shù)中,除了1和此整數(shù)自身外,沒法被其他自然數(shù)整除的數(shù)。換句話說,只有兩個正因數(shù)(1和自己)的自然數(shù)即為素數(shù)。比1大但不是素數(shù)的數(shù)稱為合數(shù)。1和0既非素數(shù)也非合數(shù)。合數(shù)是由若干個質(zhì)數(shù)相乘而得到的。所以,質(zhì)數(shù)是合數(shù)的基礎(chǔ),沒有質(zhì)數(shù)就沒有合數(shù)。所有的合數(shù)都可由若干個質(zhì)數(shù)相乘而得到。

從鍵盤輸入一個數(shù),并判斷該數(shù)是否是質(zhì)數(shù)。

1 //判斷質(zhì)數(shù)
2 # include <iostream>
3 # include <math.h>
4 using namespace std;
5 
6 int main()
7 {
8  int number,i,k;
9  cin>>number;
10  k=sqrt(number);          //k為輸入數(shù)的平方根,想一下為什么?
11  for(i=2;i<=k;i++)  //將輸入數(shù)用從2~k的一個一個數(shù)進(jìn)行整除
12   if(number%i==0)
13    break;  //只要能被整除,即跳出for循環(huán)
14  if(i>k)
15   cout<<number<<"是一個素數(shù)\n";
16  else
17   cout<<number<<"不是一個素數(shù)\n";
18  system("pause");
19  return 0;
20 }

【上機(jī)實踐】 求素數(shù)

編程求10~500之間的全部素數(shù)。

這個很簡單了,使用一個for循環(huán)枚舉10~500之間的每一個數(shù),再使用上面的判斷質(zhì)數(shù)的程序判斷即可。

我能想到的兩個優(yōu)化是:

(1)判斷一個數(shù)number是不是質(zhì)數(shù),只需要從2依次試除到,看能否被這些數(shù)整除即可。

(2)因為偶數(shù)肯定不是素數(shù),所以在for循環(huán)時,可以直接跳過,這樣可提高一倍的速度。

數(shù)學(xué)家歐幾里得最早在《幾何原本》中證明了素數(shù)有無窮多個:

假設(shè)只有有限個素數(shù)P1,P2,P3,…,Pn。令N=P1×P2×P3×…×Pn。那么,N+1是素數(shù)或者不是素數(shù)。

如果N+1為素數(shù),則N+1要大于P1,P2,P3,…,Pn,所以它不在那些假設(shè)的素數(shù)集合中。

如果N+1為合數(shù),因為任何一個合數(shù)都可以分解為幾個素數(shù)的積;而N和N+1的最大公約數(shù)是1,所以N+1不可能被P1,P2,P3,…,Pn整除,所以該合數(shù)分解得到的素因數(shù)肯定不在假設(shè)的素數(shù)集合中。

因此無論該數(shù)是素數(shù)還是合數(shù),都意味著在假設(shè)的有限個素數(shù)之外還存在著其他素數(shù)。

對任何有限個素數(shù)的集合來說,用上述的方法永遠(yuǎn)可以得到有一個素數(shù)不在假設(shè)的素數(shù)集合中的結(jié)論。

所以原先的假設(shè)不成立。也就是說,素數(shù)有無窮多個。

【例題描述】 防護(hù)罩

魔法世界的所有街區(qū)均為邊長為1公里的正方形,如圖2.9所示整齊地排列,為了防止黑暗勢力的魔法攻擊,魔法學(xué)校欲建立一個以中心四個街區(qū)的交點(diǎn)為圓心,半徑為r(r≥)公里的圓形魔法防護(hù)罩,試計算防護(hù)罩所能保護(hù)的完整街區(qū)數(shù)N。

圖2.9

由于圓的對稱性,所以只需要計算四分之一圓中所包含的完整的街區(qū)數(shù)N,將其中所包含的完整街區(qū)數(shù)以縱列劃分為組,設(shè)K為四分之一圓中共有K組街區(qū),顯然K為不超過r的最大整數(shù),如圖2.10所示。

圖2.10

則N=4×(第一組內(nèi)街區(qū)數(shù)+第二組內(nèi)街區(qū)數(shù)+…+第K組內(nèi)街區(qū)數(shù)),問題是每組內(nèi)的街區(qū)數(shù)如何計算呢?

現(xiàn)以第四組為例,作一直角三角形如圖2.11所示,可知斜邊為r,底邊為組數(shù),根據(jù)勾股定理,當(dāng)組數(shù)為a,則第a組街區(qū)數(shù)的最大取整數(shù)。

圖2.11

C++語言提供的取整函數(shù)有:

1.floor函數(shù)

floor(x)返回的是x的整數(shù)部分,方法是向負(fù)無窮大方向舍入。例如:

    floor(2.5)= 2
    floor(-2.5)= -3

2.ceil函數(shù)

ceil(x)返回的是不大于x的最小整數(shù),方法是向正無窮大方向舍入。例如:

    ceil(2.5)= 3
    ceil(-2.5)= -2

參考代碼如下所示:

1 //防護(hù)罩
2 #include <iostream>
3 #include <math.h>              //須加此頭文件
4 using namespace std;
5 
6 int main()
7 {
8  int N=0,i,temp;
9  double r,l;
10  cin>>r;
11  l=floor(r); //獲得組數(shù)
12  for(i=1;i<=l;i++)
13  {
14   temp=sqrt(r*r-i*i);
15   N=N+temp;
16  }
17  cout<<N*4;
18  system("pause");
19  return 0;
20 }

【例題描述】 完美數(shù)

魔法世界有一個畢達(dá)哥拉斯學(xué)派,他們將一個數(shù)如果恰好等于它的因子之和的數(shù)稱為“完美數(shù)”。并且認(rèn)為完美數(shù)具有神奇的魔力。例如6的因子為1、2、3,而6=1+2+3,因此6是“完美數(shù)”。創(chuàng)始人畢達(dá)哥拉斯說:“6象征著完滿的婚姻以及健康和美麗,因為它的部分是完整的,并且其和等于自身。”

請編程序找出1000之內(nèi)的所有完美數(shù)。

1 //求完美數(shù)
2 #include <iostream>
3 using namespace std;
4 #define M 1000              //定義尋找范圍
5 
6 int main()
7 {
8  int k0,k1,k2,k3,k4,k5,k6,k7,k8,k9; //保存因子,因子數(shù)一定不超過10個
9  int i,j,n,s;
10  for(j=2;j<=M;j++) //枚舉每一個數(shù)
11  {
12   n=0; //n指向因子保存的位置
13   s=j;
14   for(i=1;i<j;i++)
15   {
16    if((j%i)==0)
17    {
18     n++;
19     s=s-i;
20     switch(n) //判斷因子存在何處
21     {
22      case 1:k0=i;break;
23      case 2:k1=i;break;
24      case 3:k2=i;break;
25      case 4:k3=i;break;
26      case 5:k4=i;break;
27      case 6:k5=i;break;
28      case 7:k6=i;break;
29      case 8:k7=i;break;
30      case 9:k8=i;break;
31      case 10:k9=i;break;
32     }
33    }
34   }
35   if(s==0) //若減去所有因子后恰巧為0,則是完美數(shù)
36   {
37    cout<<j<<"是一個完美數(shù),它的因子是:";
38    if(n>1)
39     cout<<k0<<''<<k1<<' ';
40    if(n>2)
41     cout<<k2<<' ';
42    if(n>3)
43     cout<<k3<<' ';
44    if(n>4)
45     cout<<k4<<' ';
46    if(n>5)
47     cout<<k5<<' ';
48    if(n>6)
49     cout<<k6<<' ';
50    if(n>7)
51     cout<<k7<<' ';
52    if(n>8)
53     cout<<k8<<' ';
54    if(n>9)
55     cout<<k9<<' ';
56    cout<<"\n";
57   }
58  }
59  system("pause");
60  return 0;
61 }

后世的大數(shù)學(xué)家歐拉曾推算出完美數(shù)的獲得公式:

如果p是質(zhì)數(shù),且2p-1也是質(zhì)數(shù),那么(2p-1)×2p-1便是一個完美數(shù)。

例如p=2是一個質(zhì)數(shù),2p-1=3也是質(zhì)數(shù),則(2p-1)×2p-1=3×2=6是完美數(shù)。

例如p=3是一個質(zhì)數(shù),2p-1=7也是質(zhì)數(shù),則(2p-1)×2p-1=7×4=28是完美數(shù)。

但是2p-1什么條件下才是質(zhì)數(shù)呢?事實上,當(dāng)2p-1是質(zhì)數(shù)的時候,稱其為梅森素數(shù)。至今,人類只發(fā)現(xiàn)了47個梅森素數(shù),也就是只發(fā)現(xiàn)了47個完全數(shù)。

【例題描述】 除式還原1

魔法學(xué)院的后山出現(xiàn)一塊神秘石碑,石碑上有一個除式如圖2.12所示,據(jù)說解開此除式可以解開一個重大秘密。

圖2.12

由除式本身盡可能多地推出已知條件:

1.被除數(shù)的范圍是10000到99999,除數(shù)的范圍是10~99,且可以整除;

2.商為100~999之間,且十位數(shù)字為7;

3.商的第一位與除數(shù)的積為三位數(shù),且后兩位為77;

4.被除數(shù)的第三位一定為4;

5.7乘以除數(shù)的積為一個三位數(shù),且第二位為7;

6.商的最后一位不能為0,且與除數(shù)的積為一個兩位數(shù)。

由已知條件就可以采用窮舉的方法找出結(jié)果。

參考代碼如下所示:

1 //除式還原1 
2 #include<iostream>
3 using namespace std;
4 int main()
5 {
6  long int i;
7  int j,l;
8  for(i=10000;i<=99999;i++)        //條件1. i為被除數(shù)
9   //if(i%1000-i%100==400)  //條件4.被除數(shù)的第三位一定為4
10    for(j=10;j<=99;j++)  //條件1. j為除數(shù)
11    if(i%j==0 && (l=i/j)%100>=70 && l%100<80  //條件1.可整除,商的十位數(shù)為7
12    &&l%10!=0&&l>100&&l<=999) //商的個數(shù)不能為0,商l在100~999之間
13     if((j*(l%10))<100&&j*(l%10)>10)  //條件6.商的個數(shù)與除數(shù)的積為兩位數(shù)
14      if(j*7%100>=70&&j*7%100<80)  //條件5.7乘以除數(shù)的積的第二位為7
15       if(j*(l/100)%100==77&&j*(l/100)>100)  //商的第1位×除數(shù)的后兩位為77
16        cout<<i<<"/"<<j<<"="<<l;
17  system("pause");
18  return 0;
19 }

【例題描述】 換零錢1

楚繼光想把100元錢換成10元、5元、1元這樣的零錢,在這三種零錢中每種零錢都至少各有一張的情況下,共有多少種兌換方案?

設(shè)100元可以換10元x張、5元y張,1元z張,則:

100=10x+5y+z(x≥1,y≥1,z≥1)

分析上面的等式可以發(fā)現(xiàn),1≤x≤9,1≤y≤19,1≤z≤99。

因為x≥1,所以5y的取值范圍變成5≤5y≤100-10×1,解得1≤y≤18;同理,z的取值范圍為1≤z≤100-10×1-5×1,解得1≤z≤85,這樣使得內(nèi)層循環(huán)體執(zhí)行的次數(shù)由原來的9×19×99=16929次縮小到9×18×85=13770次,循環(huán)次數(shù)減少了3159次。另外,由于1元的零錢必為5的倍數(shù),所以還可再做優(yōu)化。

1 //換零錢基本算法
2 #include <iostream>
3 using namespace std;
4 
5 int main()
6 {
7  int i,j,k,count=0;
8  for(i=1;i<=9;i++)
9   for(j=1;j<=18;j++)
10    for(k=1;k<=85;k++)
11     if((i*10+j*5+k*1)==100)
12      count++;
13  cout<<count<<endl;
14  system("pause");
15  return 0;
16 }

用不等式減少循環(huán)套數(shù)量:

對于不定方程100=10x+5y+z,做如下變形:z=100-10x-5y。由于z是大于等于1的整數(shù),所以不定方程100=10x+5y+z解的個數(shù)就等于不等式100-10x-5y>0的解的個數(shù),易得1≤x≤9,1≤y≤18。故而可用二重循環(huán)求解。此時,只需9×18=162次循環(huán)體,效率提高了105倍。

1 //利用不等式優(yōu)化算法
2 #include <iostream>
3 using namespace std;
4 
5 int main()
6 {
7  int i,j,k,count=0;
8  for(i=1;i<=9;i++)
9   for(j=1;j<=18;j++)
10    if(i*10+j*5<100)
11      count++;
12  cout<<count<<endl;
13  system("pause");
14  return 0;
15 }

取1張10元的,則剩下的90元可以用1~17張5元和若干1元的相加得到,故共有17種方案;

取2張10元的,則剩下的80元可以用1~15張5元和若干1元的相加得到,故共有15種方案;

取8張10元的,則剩下的20元可以用1~3張5元和若干張1元的相加得到,故共有3種方案;

取9張10元的,則剩下的10元可以用1張5元和5張1元的相加得到,故共有1種方案。

綜上可得,總方案數(shù)為1+3+5+…+17=81種,則問題就變成了求9個數(shù)的和。用單重循環(huán)運(yùn)算9次即可。此時程序效率提升了共1881倍。

1 //利用排列組合優(yōu)化
2 #include <iostream>
3 using namespace std;
4 
5 int main()
6 {
7  int i,count=0;
8  for(i=1;i<=9;i++)
9   count+=2*i-1;
10  cout<<count<<endl;
11  system("pause");
12  return 0;
13 }

觀察數(shù)字序列1 3 5 7 9 11…,可以發(fā)現(xiàn)相鄰兩個數(shù)的差恒為2,這顯然是“等差數(shù)列”,記第一項為a1,相鄰兩個數(shù)之間的差為公差,記為d,記第n項為an,容易推導(dǎo)出:an=a1+(n-1)d,如上面第3個數(shù)為1+(3-1)×2=5。對于等差數(shù)列,我們有如下的公式來求出其前n項的和:

公式(1)用于求知道首項、末項和項數(shù)的等差數(shù)列的前n項和;

公式(2)用于求知道首項,公差和項數(shù)的等差數(shù)列的前n項和;

公式(3)用于求知道末項,公差和項數(shù)的等差數(shù)列的前n項和。

則無須循環(huán),直接用任何一個公式就可求出和為81。

1 //換零錢1——利用數(shù)學(xué)公式
2 #include <iostream>
3 using namespace std;
4 
5 int main()
6 {
7  cout<<(1+17)*9/2<<endl;
8  system("pause");
9  return 0;
10 }

【上機(jī)實踐】 換零錢2

楚繼光想把N元錢換成10元、5元、1元這樣的零錢,在這三種零錢中每種零錢都至少各有一張的情況下,共有多少種兌換方案(16≤N≤105

由于錢的數(shù)字變成了任意數(shù)N,問題變得復(fù)雜起來,如果用兩重循環(huán),105的數(shù)據(jù)量肯定超時(1秒)。有什么好的辦法嗎?

設(shè)N元可以換10元x張,5元y張,1元z張,x、y、z均不小于1。則題目的解為不等式N-10x-5y>0解的個數(shù)。

等差數(shù)列的項數(shù)為:可以換10元的最大張數(shù);等差數(shù)列的最末項為:當(dāng)有1張10元時,可以換5元的最大張數(shù)。由于是換成10元、5元和1元三種,每增加一張10元必定減少2張5元,所以等差數(shù)列的公差為2。

N元錢,當(dāng)有1張10元時,可以換5元的最大張數(shù)b為:

等差數(shù)列的公差為2,項數(shù)為a,最末項為b,使用等差數(shù)列的求和公式(3)得

Sum=a×b-(a×(a-1))/2×2=a×b-a×(a-1)=a×(b-a+1)

參考程序如下所示:

1 定義變量n,a,b,c,sum,其中sum為最終答案,a,b,c分別為10元,5元,1元的張數(shù)
2 輸入變量n的值
3 計算a的值
4 計算c的值
5 如果剩下的錢不夠一張5元和一張1元
6   則a--
7 計算b的值
8 計算c的值
9 如果c的值不足一元錢
10   則b--
11 計算sum的值
12 輸出sum的值

或者對于輸入的錢數(shù)x,必定需要一張10元、一張5元和一張1元的。為了簡化,可以將這16元錢從x中減去,剩下的錢所需要的錢的張數(shù)均為大于等于0。當(dāng)10元的張數(shù)為0(減去后)時,5元張數(shù)的最大值為(x-16)/5(整數(shù)相除自動去尾)。然后可以一張5元的換成5張1元的,即有(x-16)/5+1種換法。當(dāng)10元的張數(shù)為1時,5元張數(shù)的最大值少2,方法數(shù)也少2。一直到5元的張數(shù)為1或2時,10元張數(shù)達(dá)到最大(若10元張數(shù)更大,5元張數(shù)為-1或0)。若為奇數(shù),例如輸入x=100,方法的總和為17+15+13+11+9+…+1,運(yùn)用等差數(shù)列求和,count=(x+1)×(x+1)/4。若為偶數(shù),由于整數(shù)相除時自動去尾,count仍可以用原來的式子表示。

參考程序如下所示:

1 //換零錢2優(yōu)化
2 #include<iostream>
3 using namespace std;
4 int main()
5 {
6  int count=0,x,i;
7  cin>>x;
8  x=(x-16)/5+1;      //求5元面值張數(shù)的最大值,即10元張數(shù)=0時的方法數(shù)量
9  count=(x+1)*(x+1)/4; //等差求和
10  cout<<count<<endl;
11  system("pause");
12  return 0;
13 }
主站蜘蛛池模板: 平潭县| 苍梧县| 琼结县| 察哈| 巴中市| 宣武区| 塔河县| 招远市| 赫章县| 留坝县| 额济纳旗| 许昌县| 潜江市| 乡城县| 观塘区| 车致| 通榆县| 仙桃市| 从化市| 章丘市| 扬州市| 桓仁| 揭阳市| 南投县| 安庆市| 沈阳市| 合阳县| 手游| 郧西县| 沽源县| 宣恩县| 东乡县| 商都县| 上高县| 白沙| 奇台县| 永德县| 铜鼓县| 澜沧| 北安市| 廉江市|