1. 程式人生 > >C語言博客作業——函數

C語言博客作業——函數

正序 常量 color 大小寫轉換 總結 整數 分答 類型 進制

一、PTA實驗作業

題目1:6-6 使用函數輸出水仙花數

1.本題PTA提交列表

技術分享圖片
技術分享圖片

2. 設計思路

int narcissistic( int number ) //函數定義

  • 1.定義整數型變量a.i分別來存放number分離的出來的數和進行digit次冪運算的循環次數
  • 2.定義x=number,b=1,c=number,sum=0,定義整數型變量digit來存放位數
  • 3.利用循環求出數的位數 for(digit=1;;digit++){ x=x/10;if(x==0){break;}}
  • 4.a=c%10 把c即number的數一個個分離出來存放在a
  • 5.利用for循環,把分離出來的數a進行digit次冪運算後存放在b
  • 6.sum=sum+b;求每個位上的數字的digit次冪之和
  • 7.c=c/10 把分離出來的數去掉
  • 8.b=1 清空b的值繼續進入下一次循環求a的digit次冪運算結果
  • 9.重復步驟4,直到c=0
  • 10.判斷sum與number的關系:相等返回1,不相等返回0

void PrintN( int m, int n ) //函數定義

  • 1.定義整數型變量i來存放循環次數
  • 2.for(i=m+1;i<=n-1;i++){ //列出開區間(m,n)裏所有數
    if(narcissistic(i)){ //調用上一個函數,如果滿足水仙花數
    printf("%d\n",i); //輸出水仙花數i
    }
    }

3.本題調試過程碰到問題及PTA提交列表情況說明。

  • 1.一開始就遇到技術分享圖片
    原來題目所給的代碼並沒有調用#include ‘‘math.h‘‘
    於是利用for循環進行重復累積,並且提出疑問:是否可以 在函數定義中再調用#include‘‘math.h‘‘ 答案是:不可以

  • 2.進行調試後發現沒有進入循環,後監視變量發現忘記給c賦初值了....(可怕的老毛病)
    技術分享圖片
  • 3.為了提高運行效率而有意減少未知數的定義導致number的值被改變而影響後續的比較
    技術分享圖片
    技術分享圖片
  • 解決方法:定義一個數c附上number的值然後對c進行分離而不去改變number的值,避免對後續工作造成影響

  • 4.發現多輸出一個本身的數
    技術分享圖片
  • 解決方法:回過頭來審題發現是 開區間 於是技術分享圖片

  • 5.終於運行出與樣例一樣的答案,但是....果然pta不是吃素的...
    技術分享圖片
  • 解決方法:根據pta的提示
  • (1)增加一個條件技術分享圖片
    ,但是輸出技術分享圖片
    即: 在不返回的函數裏不可以return 任何東西
  • (2)最大區間答案錯誤:在輸入較大數後發現只輸出3位數字的數字,但是誤以為四位數並沒有水仙花數,一籌莫展之下去詢問了同學後發現
    自己審題上的錯誤,並不是所有數都是各個位數的三次方而是 digit次冪之和
  • 6.遇到下面這句陌生的話不要著急,解決的方法非常簡單:關閉黑框框即可
    技術分享圖片

題目2:6-7 使用函數輸出指定範圍內的完數

1.本題PTA提交列表

技術分享圖片
技術分享圖片
技術分享圖片

2. 設計思路

int factorsum(int number) //函數定義

  • 1.定義整數型變量i和sum分別來存放循環次數和所有因子和
  • 2.利用for (i = 2; i<number; i++) { //尋找number的因子
    if (number%i == 0) {
    sum += i; //所有因子相加
    }
    }
  • 3.返回sum的值

函數定義 void PrintPN(int m, int n)

  • 1.定義整數型變量i,j分別來存放循環次數和所有可能的因子,定義flag=0存放沒有完數的情況,flag=1存放有完數的情況,並給flag賦初值=0
  • 2.利用for (i = m; i <= n; i++) 列出(m,n)內所有數
  • 3.調用函數判斷i是否為完數: if (factorsum(i) == i) //若因子相加等於本身,即符合完數
  • 4.若是,則flag=1,並輸出表達式的前一小部分表達式 : printf("%d = 1", i);
  • 5.利用for (j = 2; j<i; j++) { //尋找number的因子
    if (i%j == 0) {
    printf(" + %d", j); //輸出表達式後部分因子相加的式子
    }
  • 6.完成一個完數的表達式後換行
  • 7.判斷flag是否為0,如是,則輸出 No perfect number

3.本題調試過程碰到問題及PTA提交列表情況說明。

  • 1.定義兩個函數時,可以先確定一個函數無誤後註釋掉再去調試另一個函數
  • 2.根據自己的思路寫好代碼後輸出發現嚴重錯誤:技術分享圖片
    啥呀這是.....滾去調試
    技術分享圖片
    技術分享圖片
    發現i=6,j=5 然後result竟然=1進入循環.... 難道是整數/整數=整數的問題?然而並不是,吃了那麽多次虧當然已經變成i*1.0/j了.....
    可是result憑啥等於1啊...重新觀察result,發現我竟然給result定義成整數型...得出小經驗:如果結果應該為小數但是卻輸出整數有兩種情況:
    (1)整數/整數=整數 (2)一開始就給結果定義成整數呀
  • 解決方法:顯然把int改成double啦
  • 3.部分答案正確技術分享圖片
  • 解決方法:根據pta的提示,針對特殊點如只輸入一個1等通過添加if語句來對代碼進行完善
  • 4.最大範圍內運行超時:代碼效率問題
    因為剛剛學習了通過int(x)可以強制把x變成整數型,所以利用x=int(x)的方法來判斷整除 技術分享圖片
    但是如果是在本題這種大範圍內執行需要多一次操作的代碼無疑是大大降低了代碼的執行效率的,而且從學長那了解到這種方法還可能帶來浮點誤差(加紅)
  • 解決方法:創新無果於是利用最經典傳統的方式取余是否等於0來判斷是否整除

題目3:7-1 求組合數

1.本題PTA提交列表

技術分享圖片
技術分享圖片

2. 設計思路

  • 1.函數聲明 double fact(int x)
  • 2.定義兩個整數型變量m,n 定義浮點型變量result來存放結果
  • 3.輸入兩個整數m,n
  • 4.判斷m與n是否相等,若是,則result=1
  • 5.若不是,則調用函數進行計算result = fact(n)/(fact(m)*fact(n-m))
  • 6.輸出結果
    定義函數 double fact(int n) 來求n!
  • 1.定義整數型變量i,浮點型變量result
  • 2.賦初值:result=1 i=1
  • 3.result=result*i
  • 4.i++,重復步驟3直到i>n
  • 5.返回result的值

3.本題調試過程碰到問題及PTA提交列表情況說明。

  • 1.浮點錯誤
  • 解決方法:像這種求n!結果的數都應該定義結果為double型而不是int型
  • 2.答案錯誤
  • 解決方法:答案應該整數輸出
    技術分享圖片
    技術分享圖片

二、同學代碼結對互評

1.同學互評照片。

技術分享圖片

2.我的代碼、互評同學代碼截圖

劉艷欽同學的代碼
int reverse( int number )
{
  int i=1,x,sum=0;         //定義整數型變量i,x,sum分別存放符號,分離出來的數字,逆序後的數
  while(number){        
    x = number%10;         //從個位開始分離輸入的數存放在x
    sum = sum * 10 +x;     //把上一次分離出來的數*10然後在加上新分離出來的數組成新數
    number=number/10;            //把分離出的數從number中去掉
    } 
    sum=sum*i;               //把符號加到number上(此處針對負數)
    return sum;               //返回sum的值
}
林曉露同學的代碼
int reverse( int number )
{  
  int i,j,k,down,sum;
  k=number;
  i=1;
  sum=0;
  while(number/10!=0){
    number=number/10;
    i++;}//計算number的位數
  for(j=i;j>0;j--){//根據number的位數循環輸出逆序數
    down=k%10;
    sum=sum+down*pow(10,j);
    k=k/10;
  }
  if(sum%10==0)//當最後是0時舍去
    sum=sum/10;
  return sum;
}

3.我和同學代碼不同在哪裏?有哪些各自優勢?你更喜歡哪種代碼風格?如果同學代碼有錯的也請幫忙指出來哪裏出問題。

  • 不同點:設計思路不同:我——利用取余的方式把number從後面一個個取出數字後再依次10, 先分離出來的數10的次數便多,也就是位於新數的前面實現了逆序
    林曉露同學——利用一個數的每個數字在正序和逆序中10的總和不變來實現逆序,eg(512中5在正序中10兩次,而後在逆序中10零次,2在正序中10零次而後兩次)
  • 在這一題上,我更喜歡我的代碼風格,因為我的代碼的運行效率相對會高一些而且整潔一些,但是曉露同學的代碼設計思路更容易讓人理解而且更有數學思想
    雖然我一開始的想法也是偏向曉露同學的設計思路,但是題目所給的主函數並沒有為我們提供#include

三、截圖本周題目集的PTA最後排名

技術分享圖片

四、本周學習總結

1.你學會了什麽?

1.1 C語言哪些數據類型?

技術分享圖片

1.2 字符型數據需要註意地方?

  • 1.字符常量:用單引號擴起來的一個字符,eg ‘A‘
    轉義字符:特殊的字符常量,都是以 ‘ ’開頭 (代表一個字符)
    註意:所有字符都可以用轉義字符表示
  • 2.字符變量:用來存放字符,且只能存放一個字符
    定義的方式是char c
    賦值的方式是c=‘A‘ 或者是 c=65
    輸入輸出的方式是 %c
    但是字符型數據和整數型數據可以相互賦值,即字符型數據可以以字符形式輸出,也可以以整數形式輸出

1.3 自增自減運算符?

  • ++是自增運算符,是單目運算符,其作用是使單個變量的值增1。它有兩種使用情況:
  • 1)前置:++i,先執行i=i+1,再使用i值;
  • 2)後置:i++,先使用i值,再執行i=i+1。
    例如:
    j=3; k=++j;執行後, k=4,j=4。上述語句等效為:j=3; j=j+1; k=j;
    j=3; k=j++;執行後, k=3,j=4。上述語句等效為:j=3; k=j; j=j+1;

  • --是自減運算符,是單目運算符,其作用是使單個變量的值減1。它有兩種使用情況:
  • 1)前置:--i,先執行i=i-1,再使用i值;
  • 2)後置:i--,先使用i值,再執行i=i-1。
    例如:
    j=3; k=--j;執行後,k=2,j=2。 上述語句等效為:j=3; j=j-1; k=j;
    j=3; k=j--;執行後,k=3,j=2。上述語句等效為:j=3; k=j ; j=j-1;
  • 註意:
    1)自增和自減運算符,只能用於變量,不能用於常量和表達式。例如5++,--(a+b)等都是非法的。
    2)自增、自減運算符及負號運算符的結合方向是從右向左。

1.4 運算符優先級?

運算符共分為15級,1級優先級最高,15級優先級最低。
同一優先級的運算符,運算次序由結合方向所決定。(結合性:單目運算符,三目運算符和各種賦值運算符是從右至左 其他都是 從左至右)
簡單記就是:! > 算術運算符 > 關系運算符 > && > || > 賦值運算符
再詳細一點,附帶一個口訣。(網上找的)
括號成員第一; //括號運算符 成員運算符. ->
全體單目第二; //所有的單目運算符比如++、 --、 +(正)、 -(負) 、指針運算*、&
乘除余三,加減四; //這個"余"是指取余運算即%
移位五,關系六; //移位運算符:<< >> ,關系:> < >= <= 等
等於(與)不等排第七; //即== 和!=
位與異或和位或; "三分天下"八九十; //這幾個都是位運算: 位與(&)異或(^)位或(|)
邏輯或跟與; //邏輯運算符:|| 和 &&
十二和十一; //註意順序:優先級(||) 底於 優先級(&&)
條件高於賦值, //三目運算符優先級排到13 位只比賦值運算符和","高
逗號運算級最低! //逗號運算符優先級最低

1.5 C語言哪些表達式?

表達式:

  • 1 算數表達式:
    單目:+, -, ++, --。
    雙目:+,-,*,/,%。
  • 2 賦值表達式:
    簡單賦值:=
    復合賦值:+=,-=,*=,,/=%=,!=。
  • 3 關系表達式:>,>=,<,<=,!=。
  • 4 邏輯表達式:!,&&,||
  • 5 條件表達式:
    exp1? exp2:exp3
    例:

    if(x>0)
    y=x+2;      =====    y=(x>0)?x+2:x*x
    else
    y=x*x;
  • 6.逗號表達式:,
    表達式1,表達式2,表達式3........表達式N
    先計算表達式1,然後計算表達式2.。。。。並將表達式n的值作為逗號表達式的值。
    Int a,b,c;
    (a=2),(b=3),(c=a+b);
    逗號運算符的優先權最低,左結合
  • 註意:(1)可以看到一個表達式也可以沒有操作符,例如“4”這種形式就是最簡單的表達式形式,即最簡單的表達式只有一個常量或一個變量名稱而沒有操作符。
    (2)函數調用也是表達式

  • 課堂派
    技術分享圖片
    由y=012可知y是個八進制,換成十進制=10
    由後置先使用x值可知,表達式就等於10

1.6 其他內容?

  • 1.數字字符和數字轉換
    number=ch-‘0‘
    ch=number+‘0‘
  • 2.大小寫轉換
    小寫轉大寫:ch-‘a‘+‘A‘
    大寫轉小寫:ch+‘A‘-‘a‘
  • 3.強制類型轉換
    double n=3.14
    x=int(x)=3
  • 4.自動類型轉換
    非賦值運算:水平方向,垂直方向,類型小的轉類型大的
    賦值運算:變量= 表達式
    將賦值運算符右側表達式的類型,自動轉換成賦值號左側變量的類型
  • 註意:邏輯運算符註意P138
    在邏輯表達式的求解中,並不是所有的邏輯運算符都執行,只有在必須執行下個邏輯運算符才能求出表達式的值時,才執行下一個運算符則執行語句:
    eg:
    t均為int型變量,
    設x、y
    x=y=3;t=++xll ++y;
    y的值為一3
  • 位運算應用
    2的整數次方的數特點: 轉成2進制後?
    只有一個尾部1其他都是0.即1000
    只有1個1的二進制數-1後,怎樣形式? 0111
    再和自己本身進行&運算,結果?可判斷該數為2的整數次方
    int pow_2(int n){
    if((n1)&n)==0) return 1;
    else return 0;

2.本周的內容,你還不會什麽?

  • 1.對位運算還很不熟悉,如位邏輯運算,移位運算,復合位賦值運算都還不太熟悉,也不會它具體的靈活運用,除了了解到老師上課舉例的找2的整數次方的數
  • 2.對異或還有二進制,八進制,十六進制的轉換的都不熟練
  • 3.對自動類型轉換也不熟悉

3.循環結構考試總結

  • 1.哪題做錯了,怎麽改?
    最後一題的設計思路過於復雜導致部分正確和運行超時
    技術分享圖片
    技術分享圖片
    但是現在還是沒有完全正確還在調試和修改的階段.....
  • 2.考試結果滿意麽,怎麽改進?
  • 1.不滿意
  • 2.設計思路還是不夠清晰和明確,特別是在時間有限的情況下,經過調試還是會發現總是出現一些常見的小錯誤還是一直在犯
  • 改進:
    1)在今後的代碼中更要有時間觀念,就是要在平時就訓練自己寫代碼的效率而不是只追求完成
    2)常見的錯誤在博客上總結後要經常閱讀來提醒自己
    3)老話:practice makes perfect~~ 依然是繼續不停敲代碼!敲代碼!敲代碼!
    4)對於最後一題這種比較靈活復雜的題也要多看多思考多練習
  • 3.其他總結。
    1)我覺得我預習效率太低了,做預習作業的情況不太理想
    2)作業效率也很低,雖然現在都已經開學半學期也打了挺多代碼,但是總是會被幾題代碼困住好久動彈不得,導致每天都被作業追著跑
    3)這周的學習內容太多了,有點不好消化,八進制十六進制和對位運算還不夠理解

C語言博客作業——函數