12天學好C語言——記錄我的C語言學習之路(Day 4)

王中堯發表於2015-07-20
12天學好C語言——記錄我的C語言學習之路

Day 4:

首先來看一段程式:

//輸出下面4*5的矩陣
/*
1  2  3   4   5
2  4  6   8   10
3  6  9   12  15
4  8  12  16  20
*/

//演算法1
/*//program 4.1
#include<stdio.h>
int main()
{
    int i,j,n;
    for(i=1;i<=4;i++)
    {
        n=i;
        for (j=1; j<=5; j++) {
            
            printf("%d “,n);   //可以用之前學過的格式符對齊
            n+=i;//每一行後一個和前一個之間正好差該行的行數
        }
        printf("\n");
    }
    return 0;
}
*/

//演算法2
/*//program 4.2
 #include<stdio.h>
int main()
{
    int i,j;
    for (i=1; i<=4; i++) {
        for (j=1; j<=5; j++) {
            printf("%d ",i*j); //每一個值正好等於該值行列數的乘積
        }
        printf("\n");
    }
    return 0;
}
*/

兩個演算法不同,只是給大家舉例參考,希望讀者能提供更多優質的演算法。

昨天學了break和continue,那麼我們再這個矩陣之中對這兩個語句再次形象的解釋,大家請看 program 4.3


/*program 4.3
//break和continue在迴圈中的效果。
#include<stdio.h>
int main()
{
    int i,j;
    for (i=1; i<=4; i++) {
        for (j=1; j<=5; j++) {
            if(i==3&&j==1)
                continue;//跳出3行1列的數字,3行的每一個數字都向左移動一個位置。如果這裡換成的break的話,3行均不輸出,3行空出來。
            printf("%d ",i*j); //每一個值正好等於該值行列數的乘積
        }
        printf("\n");
    }
    return 0;
}
*/

一道經典的例題(program 4.4)
//用 pi/4 = 1 - 1/3 + 1/5 - 1/7 + ... 公式求pi的近似值,直到發現某一項的絕對值小於(10的6次方分之一)為止。

/*//program 4.4
#include<stdio.h>
#include<math.h>
int main()
{
    int sign=1;
    double pi=0,term=1,i=1;//這個地方不能先定義一個double型別的k,然後把絕對值賦給k,這樣是會出錯的。當然定義一個int型的k,然後再賦給k,也是不行的。遇到絕對值,還是乖乖的用絕對值的原本形式進行判斷吧
    //int k;
    //k=fabs(term);
    while (fabs(term)>=1e-6)
    {
        pi=pi+term;
        sign=-sign;
        i=i+2;
        term=sign/i;   //寫程式碼一定要仔細,這裡是每一項的值,不要寫錯,理解對更要寫對!!!!!!
    }
    pi=pi*4;
    printf("%10.8f\n",pi);
    return 0;
}
*/


之前我們求過最大公約數,現在下面的這個程式(program 4.5)加入了兩個數的最大公倍數的求法,供大家回顧學習。

/*//4.5
//輸入兩個正數,求他們的最大公約數和最小公倍數
#include <stdio.h>
int main()
{
    printf("請輸入兩個數:\n");
    int m,n,temp;
    scanf("%d%d",&m,&n);
    if(m<n)
    {
        temp=m;
        m=n;
        n=temp;
    }
    for(int i=n;i>=1;i--)
    {
        if(n%i==0&&m%i==0){  //  注意這個大括號的位置,要包括break。如果沒有包含break,那麼break需要等著if中的條件都執行完畢才執行break,那樣就會多輸出很多值。而我們是找到符合條件的值就跳出迴圈。
            printf("最大公約數是%d\n",i);
            break;
        }
    }
    for(int j=m;j<=m*n;j++)
    {
        if(j%m==0&&j%n==0){
            printf("最小公倍數是%d\n",j);
            break;
        }
    }
    return 0;
}
 */

再寫一個大家學習過程中一定會遇到的程式。(program 4.6)

//輸入一行字元,分別統計其中英文字母、空格、數字和其他字元的個數
/*//program 4.6
 //在ascii表上,是先大寫字母,再小寫字母,也就是說小寫字母的ascii值較大,但是大寫字母和小寫字母之間還有幾個其他的字元,不是連續的
 #include "stdio.h"
 int main()
 {
 char ch;

 ch=getchar();   //①  將傳入的字元給變數ch
 while(ch!=‘\n')   //②   //這裡可以用這個(ch=getchar())!='\n'來代替①②③,因為getchar函式每一次只判斷一個字元,如果在下面不加③,那麼預設就只讀入一個字元,while語句只執行一次,而無法執行'\n'指令,所以分開寫的話必須在後面加③,這樣才能持續讀一個個字元。
 {
 if((ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z'))
 {
 if((ch>='W'&&ch<='Z')||(ch>='w'&&ch<='z'))
 ch-=22;
 else
 ch+=4;
 }
 printf("%c “,ch);   //不是字母的,直接就輸出了。是字母的要通過變化,就是執行上面的if語句。
 ch=getchar();   //③再輸入下一個變數給ch(這個地方沒有很看懂,明明是同時輸入的China!,為什麼這個地方看起來像是一個一個字元輸入的一樣呢~)————這個地方的原因是getchar一次只接收一個字元。
 }
 
 printf("\n");
 return 0;
 }

 */

下面是我在書中讀到的一個題目,對於一個學了3.6天,哦不,可能是3.7天程式語言的人來說,它足夠吸引人去做了。因為這個程式需要你自己輸入需要計算的一切資料,然後計算機根據演算法得到結果,再反饋回來。很有意思。而更有意思的是,在這個問題上,我發現了一個錯誤。

//Sn=a+aa+aaa+aaaa+aaaaa+...的值,n是最大項的位數,a、n由鍵盤輸入()

這個題當時我看到的時候是用第一種方法(program 4.7)去做的,這個方法和書中提供的答案不一樣,但是也是很接近正確答案的,但是執行結果不對。我希望讀者能用我的這種方法做一做,然後找到第一種答案為什麼是錯誤的,並改正。

/*//program 4.7
//第一種方法(執行時結果不對,為什麼?)
#include<stdio.h>
#include<math.h>
int main()
{
    int a,n,Sn=0,term=0;
    scanf("%d%d",&a,&n);
    int i=n-1;
    while(i<=n&&i>=0)
    {
        term=a*pow(10,i);   //這裡是用的10的n次方的方法去得到每一項
        Sn=Sn+term;
        i=i-1;
    }
    printf("%d",Sn);
    return 0;
}
*/

如果讀者將我的程式碼驗證過,那麼下面的解釋你就會覺得很容易懂了。首先,我說上面 program 4.7
所示的程式碼很接近正確答案了,但是卻是不完整的。因為我求出的只是整個Sn中最大一項的值,比如說:a=2,n=3時。Sn=2+22+222=246,上面的程式只得到了222這一項,所以答案缺少的是其他項的部分,顯然,一個for迴圈就可以解決了(program 4.8)

/*//program 4.8
#include<stdio.h>
#include<math.h>
int main()
{
    int a,n,Sn=0,term=0;
    scanf("%d%d",&a,&n);
    for(int j=n-1;j>=0;j--)
    {
        int i=j;   //這裡很重要,因為j的值每次用完都會改變,所以不能直接使用,要先找一個替代品,也就是i了
        int sum=0;   //這裡也很重要,因為sum的值是每一項的值(Sn的每一項),sum每次使用的時候必須初始化為0
        while(i<=n&&i>=0)
            {
                term=a*pow(10,i);
                sum=sum+term;   //term的值是sum的每一項
                i=i-1;
            }
        Sn=Sn+sum;
    }
    printf("%d",Sn);
    return 0;
}
*/

//第二種方法(program 4.9)和之前的略有不同,還是那個例子:當a=2,n=3時。Sn=2+22+222=246,2*10+2=22,22*10+2=222,依照每兩項之間的規律,可以得出後一項與前一項的倍數關係

/*//program 4.9
 #include <stdio.h>
int main()
{
    int a,n,i,Sn=0;
    scanf("%d%d",&a,&n);
    int term=a; //這裡很有必要,因為下面a的值不變。倍數關係需要一個新的變數的表示。
    if(n!=0) //這裡必須判斷n=0的情況,因為0個a是0。沒有項。
    {
        for(i=1;i<=n-1;i++)
        {
            term=term*10+a;
            Sn=Sn+term;
        }
        printf("%d",Sn+a);//最後記得要加上a,因為上面的for迴圈是從第二項開始的。
    }
    else
        printf("0");
    return 0;
}
*/

再看下面這個題目(program 4.10),異曲同工。

//求1!+2!+3!+...+20!

/*//program 4.10
//求1!+2!+3!+...+20!
#include<stdio.h>
int main()
{
    double i,j,k,sum=0;
    for (i=20; i>=1; i--) { //i控制迴圈的次數,所以下面需要用到這個i的,所以i的值一定要用別的值取代了之後再用,不能改變了原本迴圈i的值
        j=i;
        k=j;
        while(j!=1)   //j控制的是每一項的迴圈次數,也不能變。如20!這一項,就要迴圈直至20*19*18*...*3*2*1
        {
            k=k*(j-1);  //k是每一項的迴圈之後的定值,最終值。
            j--;
        }
        sum+=k; //sum就是累計所有項的和
    }
    printf("%30.2f",sum);
    return 0;
}
*/

這個程式簡直和上面的那道題的解題模式一模一樣,讀者一定要練習一下。

今天的學習到此為止吧,學習的程式並不多,但能活躍你的思維。讀者務必將每個程式都親力親為一遍,做到爛熟於心的程度。如果你真的做了,那麼你肯定就能學到不少東西,超出這些程式以外的。

相關文章