1. 程式人生 > >C語言作業--函數

C語言作業--函數

pri 循環 哥德巴赫猜想 局部變量 函數調用 () img 調用 運行

一、PTA實驗作業

題目1: 400~499 中4出現的次數

1. 本題PTA提交列表

技術分享圖片

2. 設計思路

一、main函數

  • 1.函數聲明int fun(int x)
  • 2.定義變量i,k,i表示輸入的值,k存放4出現次數
  • 3.重復以下步驟直到i>499
  • 4.調用函數int fun(int x)計算i中k值
  • 5.累加k值
  • 6.輸出k值

二、函數int fun(int x)

  • 1.k賦初值0
  • 2.當x!=0時,重復下面步驟
  • 3.計算個位數字x%10,如果x%10==4,k++
  • 4.去除末位數字, x=x/10
  • 5.返回k值

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

k值輸出不對

技術分享圖片

調試

技術分享圖片

技術分享圖片

技術分享圖片

技術分享圖片

可以很清楚的看到m的值是i的個位數字,也就是說每次取個位數字後去除個位數字的語句沒有實現,導致k實際輸出的是個位數字為4的數字個數

改正:換do while語句為while語句,調試下看看有沒有實現去除個位數字

技術分享圖片

技術分享圖片

可以看到這次k記錄的數值就對了

小插曲:忽略main函數中的k+=fun(i)語句,看到k數值是1,2覺得沒實現累加,利用了靜態局部變量來實現對k進行累加,導致輸出一個幾千的數值。後改正

題目2:使用函數輸出水仙花數

1. 本題PTA提交列表

技術分享圖片

技術分享圖片

2. 設計思路

一、main函數

  • 1.定義整型變量m,n
  • 2.輸入m,n
  • 3.調用函數int narcissistic( number )判斷是否為水仙花數
  • 4..如果 narcissistic( m )==1,printf("%d is a narcissistic number\n", m)
  • 5.如果 narcissistic( n )==1,printf("%d is a narcissistic number\n",n)
  • 6.調用函數void PrintN( int m, int n )選出(m,n)中的水仙花數,輸出這些水仙花數

二、函數int narcissistic(int number )

  • 1.定義整型變量N,i,j,,number1,number2
  • 2.給N賦初值0
  • 3.定義整型變量sum,存放各個位數的數字的N次方和 ,並賦初值
    1. number1=number,number2=number
  • 5.如果number1不為0重復下面步驟
  • 6.去個位數: number1=number1/10
  • 7.N++,用來表示位數
  • 8.i=1,當i小於N的值時,重復下面步驟
  • 9.j=number2%10,sum=sum+pow(j,N)
  • 10.如果sum==number,返回1,否則,返回0

三、函數void PrintN( int m, int n )

  • 1.m++
  • 2.當m<n時,重復下面步驟
  • 3.如果narcissistic(m)==1,輸出這個數
  • 4.m++;

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

錯誤代碼:

#include <stdio.h>

int narcissistic( int number );
void PrintN( int m, int n );

int main()
{
    int m, n;

    scanf("%d %d", &m, &n);
    if ( narcissistic(m) ) printf("%d is a narcissistic number\n", m);
    PrintN(m, n);
    if ( narcissistic(n) ) printf("%d is a narcissistic number\n", n);

    return 0;
}

#include<math.h>
int narcissistic( int number )//調用函數 
{
        int N,i,j;
        int sum=0;
        while(number!=0){//如果number不為0執行循環體 
            j=number%10;//取個位數 
            N++;//累加N來計算水仙花數位數 
            number=number/10;//除去個位數得到新的number 
        }
        for(i=1;i<=N;i++){
            j=number%10;
            number=number/10;
            sum=sum+pow(j,N);//計算各個位數的數字的N次方和 
        }
        if(sum==number){//如果各個位數數字N次方和等於這個數 
             return 1;}//返回1 
             return 0;//否則返回0 
}
void PrintN( int m, int n ){
    int number;
    for(number==m;number<=n;number++){//當number在(m,n】範圍內執行循環體 
        if( narcissistic(number)==1){//如果為水仙花數 
            printf("%d\n",number);//輸出這個數 
        }
    } 
}

運行:

技術分享圖片

第二個函數沒有輸出,會不會是沒有進入這個函數?

技術分享圖片

135不是水仙花數,但是也輸出了,所以第一個函數調用是不是也有問題。。。。

技術分享圖片

技術分享圖片

變成輸出m到n所有數了,沒有實現判斷水仙花數

錯誤代碼:

#include <stdio.h>
int narcissistic( int number );
void PrintN( int m, int n );
int main()
{
    int m, n;
    scanf("%d %d", &m, &n);
    if ( narcissistic(m)) printf("%d is a narcissistic number\n", m);
    PrintN(m, n);
    if ( narcissistic(n))printf("%d is a narcissistic number\n", n);

    return 0;
}
#include<math.h>
int narcissistic( int number )//調用函數 
{
        int N,j,sum,i;
        N=0;
        sum=0;
      do{//如果number不為0執行循環體 
            number=number/10;//除去個位數得到新的number 
            N++;//位數加一 
        }   while(number!=0);
        for(i=1;i<=N;i++){
            j=number%10;//取個位數 
            number=number/10;//去除個位數 
            sum=sum+pow(j,N);//計算各個位數的數字的N次方和 
        }
        if(sum==number)//如果各個位數數字N次方和等於這個數 
             return 1;//返回1 
             return 0;//否則返回0 
}
void PrintN( int m, int n ){
     while(m<n){
    if( narcissistic(m)==1){//如果為水仙花數 
            printf("%d\n",m);}//輸出這個數   
                m++;
     }
}

調試:

發現m,n不能輸入,還有sum一直為0

技術分享圖片

錯誤:忽略了number定義的類型是全局變量,所以在取個位的循環結束後number=0,並且影響到後面出現的number,根據全局變量特點,它們的值都為0了,導致錯誤

改正:用number1,number2來存放number的值,number1,number2分別用於倆個循環,這樣就不改變number的值了

提交:
技術分享圖片

新錯誤:運行超時,沒有輸出

調試:

技術分享圖片

技術分享圖片

技術分享圖片

調試發現掉入循環出不去,仔細觀察發現循環條件是number1!=0,而我寫成number!=0,導致循環不能結束。

改正後:

技術分享圖片

不是很明白這個錯誤,但是知道錯誤是因為輸入範圍問題
再次閱讀題目,循環起點應該m+1而不是m,在循環開始前執行m++,提交正確

題目3:求組合數

1. 本題PTA提交列表

技術分享圖片

2. 設計思路

一、main函數

  • 1.定義倆個整型變量,m,n
  • 2.定義倆個浮點型變量result,表示組合數結果
  • 3.調用函數double fact(int n),計算result=fact(n)/(fact(m)*fact(n-m))
  • 4.輸出result,控制輸出位數為0

二、函數double fact(int n)

  • 1.定義整型變量i,存放循環次數
  • 2.給fact賦初值 double fact=1.0
  • 3.當i小於等於n時,重復下面步驟
  • 4.fact=fact*i
  • 5.i++
  • 6.返回fact的值

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

技術分享圖片

錯誤:沒有給 fact 賦初值

改正過程:嘗試使用double i,double(fact*i)但是運行還是一樣的錯誤,double型乘以int就是double型,錯誤點不在這。給fact賦值fact=1,運行還是顯示這個錯誤,改為1.0還是不行。錯誤上面解釋是希望輸出double型。所以嘗試改成double fact==1.0就對了

二、同學代碼結對互評

1.同學互評照片。(我、沈夢婷)

技術分享圖片

技術分享圖片

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

題目6-9 驗證哥德巴赫猜想

我的代碼:

技術分享圖片

#include <stdio.h>
#include <math.h>
int prime( int p );
void Goldbach( int n );
int main()
{
    int m, n, i, cnt;
    scanf("%d %d", &m, &n);
    if ( prime(m) != 0 ) printf("%d is a prime number\n", m);
    if ( m < 6 ) m = 6;
    if ( m%2 ) m++;
    cnt = 0;
    for( i=m; i<=n; i+=2 ) {
        Goldbach(i);
        cnt++;
        if ( cnt%5 ) printf(", ");
        else printf("\n");
    }
    return 0;
}
int prime( int p ){
    int k;
    for(k=1;k<=p/2;k++){//如果循環中滿足p%k==0,說明這個數不是素數,結束循環
        if(p%k==0)
        break;
    }
    if(k>p/2&&p!=1)//如果循環正常結束,滿足該條件,就是素數
           return 1;
          else return 0;
}
void Goldbach( int n ){
    int x1,x2;
    for(x1=2;x1<n;x1++)
        for(x2=2;x2<n;x2++)
            if(prime(x1)==1&&prime(x2)==1&&x1<=x2){//調用素數函數判斷是否為素數
                if(x1+x2==n)//判斷是否滿足哥德巴赫猜想
                      printf("%d=%d+%d",n,x1,x2);
                             break;
            }
}

沈夢婷的代碼:

#include <stdio.h>
#include <math.h>
int prime( int p );
void Goldbach( int n );
int main()
{
    int m, n, i, cnt;
    scanf("%d %d", &m, &n);
    if ( prime(m) != 0 ) printf("%d is a prime number\n", m);
    if ( m < 6 ) m = 6;
    if ( m%2 ) m++;
    cnt = 0;
    for( i=m; i<=n; i+=2 ) {
        Goldbach(i);
        cnt++;
        if ( cnt%5 ) printf(", ");
        else printf("\n");
    }
    return 0;
}
int prime( int p )
{
    int i,n;
    if(p==1)//判斷p為1時不是素數 
        return 0;
    n=sqrt(p);
    for(i=2;i<=n;i++){
        if(p%i==0){//判斷p是否為素數 
            return 0;
        }
    }
        return 1;
 } 
 void Goldbach( int n )
 {
    int p,q; 
    for(p=2;p<=n;p++){
        if(prime(p)!=0){//p是素數 
            q=n-p;//p與q的關系 
            if(prime(q)!=0){//q是素數 
                printf("%d=%d+%d",n,p,q);
                break;
             }
         }
     }
 }

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

我預計是通過兩個循環,找到滿足哥德巴赫猜想的輸出,為了找到題目要求的一組就結束,還加了break,但是還是輸出所有情況,改了幾次也不行,覺得這種方法更適用於窮舉。而沈夢婷是通過找到最小的素數後,利用倆個數相加等於n的條件,將另一個數值表示出來,再判斷這個數是不是素數,如果是,則驗證了哥德巴赫猜想.沈夢婷的代碼思路清晰,也簡化了很多。相比較我的代碼中嵌套循環判斷要循環的次數比沈夢婷代碼循環次數多很多。所有我更喜歡她的代碼。

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

技術分享圖片

四、本周學習總結

1.你學會了什麽?

1.1 C語言哪些數據類型?

整型、字符型、實型

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

(1)不僅可以寫成字符常量的形式,也可以用相應的ASSCII碼表示,即可用整數表示。整數變量和字符型變量是可以互換的
(2)字符具有數值特征,可以像整數一樣參加運算
(3)轉義字符只代表一個字符
(4)ASCII字符集中所有字符都能用轉義字符表示

1.3 自增自減運算符?

(1)使變量的值增1或減1
設n是一個整型變量並已賦值
++n和n++都相當於n=n+1
--n和n--都相當於n=n-1

(2)取變量的值作為表達式的值
++n的運算順序是:先執行n=n+1,再將n的值作為表達式++n的值
n++的運算順序是:先將n的值作為表達式n++的值,再執行n=n++

1.4 運算符優先級?

(1)如果操作數兩側的運算符優先級相同,則按結合方向決定計算順序
(2)運算符優先級從高到低排列:邏輯運算符、算術運算符、關系運算符、邏輯運算符、條件表達式、賦值運算符、逗號運算符
(3)優先級不同則按優先級從高到低計算

1.5 C語言哪些表達式?

算術表達式、賦值表達式、關系表達式、邏輯表達式、條件表達式和逗號表達式

課堂派哪裏做錯,做錯的請在這裏分析原因?

(1)int x=1,y=012;
printf("%d",y*x++);

正確答案:10
我的答案:20

分析:++的優先級高於*,x++的值就是x,y是八進制,y=10,所以結果為10

(2)若a為int類型,且其值為3,則執行表達式a+=a-=a*a後,a的值

正確答案:-12
我的答案:-3

分析:a*a優先,所以a-=9.也就是a=a-9.a的值變為-6.所以a+=-6,即a=a-6,所以a=-12

1.6 其他內容?

(1)指定整型數據的輸出寬度:%md,若實際位數小於m,則左端補空格,若大於m,則按實際位數輸出

(2)double類型指定輸出寬度:%m.nf,保留n位小數,輸出寬度為m

(3)ch-‘a‘+‘A‘把小寫字符轉換成數字
ch-‘0‘把數字字符轉為數字
val+‘0‘把數字轉換為數字字符

(4)類型轉換
1.自動類型轉換
2.強制類型轉換

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

二進制的轉換和運算符的優先級順序記憶不清。以及在PTA中忘記全局變量用於整個程序這一顯著特點,導致程序運行中更改了全局變量的值。主要是剛學的知識點不大熟,單拎出來會,放在題目中就忘了,需要一個加深印象的過程吧。

3.循環結構考試總結

1.哪題做錯了,怎麽改?

第四題沒做,第五題錯了。
第四題中的二進制,課本上沒有,導致拿到題目自我暗示我沒學過,肯定不會寫。第五題的話還沒理出算法,不知道如何寫代碼。
第四題的話可以先去了解下二進制,然後再做一遍。第五題要認真再想想。。。

2.考試結果滿意麽,怎麽改進?

不滿意。多多加強課本上一些比如素數判斷這類函數,題目中也挺常見的,太過依賴課本會覺得都懂這些簡單函數,但是自己寫的時候各種小細節問題就暴露出來了,浪費時間去找錯誤

3.其他總結。

1.時間不要浪費在簡單題上,導致占用過多時間,所以一些常見的函數啊,語句啊,要記熟
2.書本上有提到但是沒有詳細介紹的知識點要盡快通過查找資料補齊這部分知識,不能拖延,那就真沒時間看了。二進制對我來說就是血淋淋的例子
3.查錯能力很重要

C語言作業--函數