2.循環(huán)結(jié)構(gòu)程序設(shè)計(jì)

內(nèi)容

for 循環(huán)

  1. 輸出1团赏,2,3也榄,...,n的值
    #include<stdio.h>
    
    int main()
    {
        int n;
        scanf("%d", &n);
        for(int i=1; i<=n; i++){
            printf("%d\n", i);
        }
        return 0;   
    } 
    
    1. for循環(huán)的格式: for(初始化; 條件; 調(diào)整) 循環(huán)體;
    2. 注意理解for循環(huán)的執(zhí)行過程
    3. 在循環(huán)內(nèi)定義變量的i兵迅,循環(huán)體外不可見。盡量縮小變量定義的范圍薪贫。
  2. 輸出所有形如aabb的4位完全平方數(shù)恍箭。
    #include<stdio.h>
    #include<math.h>
    
    int main()
    {
        // 兩層循環(huán)嵌套 
        for(int i=1; i<10; i++){
            for(int j=0; j<10; j++){
                // 得到 aabb 這種數(shù) 
                int n = i*1100+j*11;
                // 開方,四舍五入 
                int m = floor(sqrt(n) + 0.5);
                if(m*m == n){
                printf("%d\n", n);
                } 
            }
        }
        return 0;   
    }
    
    1. 偽代碼瞧省,實(shí)際應(yīng)用中扯夭,不需要太拘泥于偽代碼的格式,主要目標(biāo)是描述算法梗概鞍匾,避開細(xì)節(jié)交洗,啟發(fā)思路。
    2. 浮點(diǎn)運(yùn)算可能存在誤差橡淑。在進(jìn)行浮點(diǎn)數(shù)比較時(shí)构拳,應(yīng)考慮到浮點(diǎn)誤差。
    // 解答二 枚舉法
    #include<stdio.h>
    #include<math.h>
    
    int main()
    {
        for(int i=1; ; i++){
            int x = i*i;
            if(x < 1000){
                continue;
            }
            if(x > 9999){
                break;
            }
            int hi = x/100;
            int low = x%100;
            if(hi/10 == hi%10  && low/10 == low%10){
                printf("%d\n", x);
            }
        } 
        return 0;   
    }
    
    注:把所有平方數(shù)都列舉出來梁棠,選出滿足條件的置森,四位數(shù),aabb型符糊。

while循環(huán)和do-while循環(huán)

  1. 3n+1問題
    對于任意大于1的自然數(shù)n凫海,若n為奇數(shù),則將n變?yōu)?n+1濒蒋,否則變?yōu)閚的一半盐碱。經(jīng)過若干次這樣的變換把兔,一定會使n變?yōu)?沪伙。求變換次數(shù)。
    #include<stdio.h>
    
    int main()
    {
        int n, times;
        scanf("%d", &n);
        times = 0;
        while(n != 1){
            if(n%2 == 0){
                n = n/2;
            }else{
                n = 3*n+1;
            }
            times++;
        }
        printf("%d", times);
        return 0;   
    }
    
    1. while循環(huán)的格式為:while(條件) 循環(huán)體;
    2. 當(dāng)需要統(tǒng)計(jì)某種事物個(gè)數(shù)時(shí)县好,可以用一個(gè)變量來充當(dāng)計(jì)數(shù)器围橡。
    3. 不要忘記測試,一個(gè)看上去正確的程序可能隱含錯(cuò)誤缕贡。
    4. 在觀察無法找出錯(cuò)誤時(shí)翁授,可以用“輸出中間結(jié)果”的方法查錯(cuò)。
    5. 在32位的系統(tǒng)中晾咪,運(yùn)算器一次最多可以處理32位的數(shù)據(jù)收擦,寄存器的最大寬度也是32位的。然后谍倦, C語言中對數(shù)據(jù)寬度的規(guī)定是指針變量塞赂、long型變量的寬度推薦是處理器一次能夠處理的最大寬度,所以就是32位昼蛀,也就是4個(gè)字節(jié)宴猾。同理圆存,在64位系統(tǒng)中,運(yùn)算器仇哆、寄存器等一次處理的寬度是64位沦辙,也就是8個(gè)字節(jié),所以指針變量讹剔、long型變量等也就都是8個(gè)字節(jié)了油讯。
  2. 近似計(jì)算
    計(jì)算Π/4=1-1/3+1/5-1/7+...,直到最后一項(xiàng)小于10的負(fù)6次方延欠。
    #include<stdio.h>
    
    int main()
    {
        double sum = 0;
        for(int i = 0; ; i++){
            double term = 1.0/(i*2+1);
            if(i%2 == 0){
                sum = sum+term;
            }else{
                sum = sum-term;
            }
            if(term < 1e-6){
                break;
            }
        }
        printf("%.6f", sum);
        return 0;   
    }
    
    do-while語句不常使用撞羽。

循環(huán)的代價(jià)

  1. 階乘之和
    輸入n,計(jì)算S=1衫冻!+2诀紊!+3!+...+n隅俘!的末6位(不含前導(dǎo)0)邻奠。n<=10的6次方。

    #include<stdio.h>
    
    int main()
    {
        int n;
        scanf("%d", &n);
        int six = 0;
        for(int i = 1; i<=n; i++){
            int s = 1;
            for(int j =1; j<=i; j++){
                s = s*j;
            }
            six += s;
        }
        printf("%d", six%1000000);
        return 0;   
    } 
    

    用上面的程序會發(fā)現(xiàn)兩個(gè)問題:
    - 輸入100時(shí)为居,會出現(xiàn)負(fù)數(shù)碌宴,乘法溢出了。
    - 輸入10的6次方蒙畴,也會溢出贰镣,同時(shí)發(fā)現(xiàn)太慢了。

    從題目可以知道膳凝,他只要最后面的六位碑隆,可以在中間結(jié)果上每次都取模。

    #include<stdio.h>
    
    int main()
    {
        const int MOD = 1000000;
        int n;
        scanf("%d", &n);
        int six = 0;
        for(int i = 1; i<=n; i++){
            int s = 1;
            for(int j =1; j<=i; j++){
                s = (s*j)%MOD;
            }
            six = (six+s)%MOD;
        }
        printf("%d", six);
        return 0;   
    } 
    

    測試幾組數(shù)據(jù)蹬音,發(fā)現(xiàn)從40開始上煤,答案始終不變,原因是25著淆!的末尾有6個(gè)0劫狠,所以從第25項(xiàng)開始,后面所有項(xiàng)都不會影響末尾的6位數(shù)字永部,所以可以放棄使用每次都%一下的方法独泞,只需if(n>25 n=25;)

算法競賽中的輸入輸出框架

  1. 數(shù)據(jù)統(tǒng)計(jì)
    輸入一些整數(shù),求出它們的最小值苔埋、最大值和平均值(保留3位小數(shù))懦砂。輸入保證這些數(shù)都是不超過1000的整數(shù)。
    #include<stdio.h>
    
    int main()
    {
        int x, n=0, min, max, s = 0;
        while(scanf("%d", &x) == 1){
            s += x;
            if(x < min){
                min = x;
            } 
            if(x > max){
                max = x;
            }
            n++;
        }
        printf("%d %d %.3f\n", min, max, (double)x/n);
        return 0;   
    }
    
    上面的程序,如何停止輸入呢孕惜?
    • windows中愧薛,輸入完畢后按Enter鍵,再按ctrl+z鍵衫画,最后再按Enter
    • Linux中毫炉,輸入完畢后按Ctrl+D鍵即可結(jié)束輸入
    #include<stdio.h>
    #define INF 1000000000
    
    int main()
    {
        int x, n=0, s = 0, kase=0;
        while(scanf("%d", &n) == 1 && n){
            int s = 0, min=INF, max=-INF;
            for(int i = 0; i<n; i++){
                scanf("%d", &x);
                s += x;
                if(x < min){
                    min = x;
                } 
                if(x > max){
                    max = x;
                }
            }
            if(kase) printf("\n");
            printf("case %d: %d %d %.3f\n", ++kase, min, max, (double)s/n);
        } 
        return 0;   
    }
    

練習(xí)

  1. 水仙花數(shù)
    輸出100-999中的所有水仙花數(shù)。若3位數(shù)ABC滿足ABC= A3 + B3 + C3削罩,則稱其為水仙花數(shù)瞄勾。例如153=13+53+33,所以153是水仙花數(shù)弥激。
    #include<stdio.h>
    #include<math.h>
    
    int main()
    {
        int daffodil;
        for(int i=100; i<=999; i++){
            int unit = i%10;
            int tens = i/10%10;
            int hundreds = i/100;
            bool j = (i == (int)(pow(unit, 3)+pow(tens, 3)+pow(hundreds, 3)));
            if(j){
                printf("%d = %d^3 + %d^3 + %d^3\n", i, hundreds, tens, unit);
            }
        }
    
        return 0;   
    }
    
    這道題沒有難度进陡,主要就是熟悉熟悉循環(huán)的運(yùn)用。
  2. 韓信點(diǎn)兵
    #include<stdio.h>
    
    int main()
    {
    
        while(true){
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            bool isExist = false;
            int i=0;
            for(i = 10; i<=100; i++){
                if(i%3 == a && i%5 == b && i%7 == c){
                    isExist = true;
                    break;
                }
            }
            if(isExist){
                printf("case: %d\n", i);
            }else{
                printf("case: No answer\n");
            }
        }
    
        return 0;
    }
    
    這道題目說“每次只看排尾”微服,意思也就是只看余數(shù)趾疚,這樣遍歷,一次一次試就可以了以蕴,雖然效率不高糙麦。
  3. 倒三角形
    #include<stdio.h>
    
    int main()
    {
        int n;
        scanf("%d", &n);
        for(int i=1; i<=n; i++){
            // 輸出前面的空格 
            for(int j=1; j<i; j++){
                printf(" ");
            }
            // 輸出中間的* 
            for(int k=1; k<=1+2*(n-i); k++){
                printf("*");
            }
            // 輸出后面的空格 
            for(int j=1; j<i; j++){
                printf(" ");
            }
            printf("\n");
        }
        return 0;
    }
    
  4. 子序列的和
    #include<stdio.h>
    #include<math.h>
    
    int main()
    {
        int n, m;
        int sign =0;
        while(scanf("%d%d", &n, &m) == 2){
            if(n == 0 && m == 0){
                break;
            }
            double result;
            result = 0;
            for(double i=n; i<=m; i++){
                result += 1.0/pow(i,2);
            }
            sign++;
            printf("Case %d: %.5f\n", sign, result);
        }
    
        return 0;
    }
    
    scanf 的返回值為輸入值的個(gè)數(shù)。
  5. 分?jǐn)?shù)化小數(shù)
    #include<stdio.h>
    
    int main()
    {
        int sign = 0;
        int a, b, c;
        while(scanf("%d%d%d", &a, &b, &c) != EOF){
            if(a==0 && b==0 && c==0){
                break;
            }
            double d = 1.0*a/b;
            sign++;
            printf("Case %d: %.*f", sign, c, d);
        
        }   
    
        return 0;
        
    }
    
    注意:%.*f
  6. 排列
    #include<stdio.h>
    
    int main()
    {
        for(int i=1; i<=9; i++){
            for(int j=1; j<=9; j++){
                for(int k=1; k<=9; k++){
                    if(i==j || i==k || j==k){
                        continue;
                    }
                    int a = i*100+j*10+k*1;
                    int b = i*200+j*20+k*2;
                    int c = i*300+j*30+k*3;
                    if(a<999 && b<999 && c<999){
                        printf("%d %d %d\n", a, b, c);
                    }
                }
            }
        }
        return 0;
    }  
    
  7. 猜猜下面程序的輸出內(nèi)容丛肮,一定要運(yùn)行一遍赡磅。
    #include<stdio.h>
    
    int main()
    {
        float i;
        for(i=0; i != 10; i += 0.1){
            printf("%.1f\n", i);
        }
        return 0;
    }
    
    double和float都不能用==來比較。根據(jù)浮點(diǎn)數(shù)的存儲參考IEEE 754浮點(diǎn)數(shù)標(biāo)準(zhǔn)
    0.4 ≈ 二進(jìn)制0.011 001100110011...
    0.3 ≈ 二進(jìn)制0.0100110011001100...
    0.7 ≈ 二進(jìn)制0.1011001100110011...
    但是宝与,float只存前幾位焚廊,兩個(gè)float想加只有前幾位參與操作,損失后面的精度习劫,如果前面的不一樣樣比較就出現(xiàn)不想等咆瘟,如果都一樣這里就相等,但你換別的數(shù)字試試可能也不相等榜聂,原因就是精度損失搞疗。
    可以把要比較的兩個(gè)數(shù)相減的絕對值與一個(gè)較小的數(shù)比嗓蘑,例如须肆,fabs(f1-f2)<1e-6
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市桩皿,隨后出現(xiàn)的幾起案子豌汇,更是在濱河造成了極大的恐慌,老刑警劉巖泄隔,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件拒贱,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)逻澳,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門闸天,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人斜做,你說我怎么就攤上這事苞氮≌鸺担” “怎么了荔仁?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長粘茄。 經(jīng)常有香客問我霸旗,道長贷帮,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任诱告,我火速辦了婚禮撵枢,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘精居。我一直安慰自己诲侮,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布箱蟆。 她就那樣靜靜地躺著沟绪,像睡著了一般。 火紅的嫁衣襯著肌膚如雪空猜。 梳的紋絲不亂的頭發(fā)上绽慈,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天,我揣著相機(jī)與錄音辈毯,去河邊找鬼坝疼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛谆沃,可吹牛的內(nèi)容都是我干的钝凶。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼唁影,長吁一口氣:“原來是場噩夢啊……” “哼耕陷!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起据沈,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤哟沫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后锌介,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體嗜诀,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡猾警,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了隆敢。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片发皿。...
    茶點(diǎn)故事閱讀 38,117評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拂蝎,靈堂內(nèi)的尸體忽然破棺而出雳窟,到底是詐尸還是另有隱情,我是刑警寧澤匣屡,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布封救,位于F島的核電站,受9級特大地震影響捣作,放射性物質(zhì)發(fā)生泄漏誉结。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一券躁、第九天 我趴在偏房一處隱蔽的房頂上張望惩坑。 院中可真熱鬧,春花似錦也拜、人聲如沸以舒。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蔓钟。三九已至,卻和暖如春卵贱,著一層夾襖步出監(jiān)牢的瞬間滥沫,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工键俱, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留兰绣,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓编振,卻偏偏與公主長得像缀辩,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子踪央,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容