Thursday, November 08, 2012

C 語言範例程式

範例一 插入排序 include stdio.h stdlib.h time.h conio.h

// 定義排序陣列大小 
#define ASIZE 5

// 主程式 開始 
int main()
{
    // 初始化排序陣列 
	int a[ASIZE];
    // 定義變數 : 已排序位置, 比較大小的位置, 輸出陣列的位置 
	int i, j, k, tmp;
    // 判斷是否繼續使用程式的變數 
    char choice;
    
	// 程式重複執行區塊 開始
	while(1)
	{
        printf("亂數產生陣列元素\n");
		srand(time(NULL));

        // 亂數產生陣列元素
		for(i = 0; i < ASIZE; i++)
		{
			a[i] = rand() % 100;
		}

        // 輸出排序前陣列
        printf("排序前陣列 : ");
        for(k = 0; k < ASIZE; k++)
            printf("%2d ", a[k]);

        printf("\n\n排序\n");
    
        // 排序的外層迴圈 : 已排序
    	for(i = 1; i<=ASIZE; i++)
    	{
            // 輸出目前已完成排序的位置 
    		printf("i:%d, ",i);
    
    		// 輸出排序中陣列
    		for(k = 0; k < ASIZE; k++)
    			printf("%2d ", a[k]);
    		//printf("\n");
    		getchar();
    
            // 由右往左比大小排序 
    		for(j = i; j > 0; j--)
    		{
                // 若比左方大, 代表一定比左方所有已排序的數字大. 不需繼續比較直接跳離此回合排序.
                // 若比左方小, 則需要交換位置. 並繼續向左方比大小, 直到比左方數字大為止. 
    			if(a[j-1] < a[j]){
    				break;
    			}else{
    				tmp = a[j];
    				a[j] = a[j-1];
    				a[j-1] = tmp;
    			}
    		}
    	}
    
        // 輸出排序後陣列
        printf("\n排序後陣列 : ");
        for(k = 0; k < ASIZE; k++)
            printf("%2d ", a[k]);
        printf("\n");

        printf("\n請問是否要繼續排序陣列 ? (按任意鍵繼續, 輸入 N / n 離開) ");
        choice=getche();
        if(choice == 'N' || choice == 'n')
            break;
        printf("\n\n");

    // 程式重複執行區塊 結束 
    }

	printf("\n感謝您的使用.\n");

    // 暫停畫面 (For Windows) 
	system("pause");
	return 0;
// 主程式 結束 
}

範例二 計算 LCM include stdio.h stdlib.h conio.h

// 計算 GCD 函式原型 
int gcd(int,int);
// 計算 LCM 函式原型
int lcm(int,int);

// 主程式 開始
int main()
{
    // 定義存放使用者輸入數字的變數 
	int x, y;
    // 定義是否繼續的變數 
    char choice;

	// 程式重複執行區塊 開始
	while(1)
	{
        // 使用者輸入 
    	printf("請輸入兩個整數 : ");
    	scanf("%d %d", &x, &y);

        // 呼叫 LCM 函式並且 
    	printf("LCM(%d, %d) = %d\n", x, y, lcm(x,y));

        printf("\n請問是否要繼續計算 LCM ? (按任意鍵繼續, 輸入 N / n 離開) ");
        choice=getche();
        if(choice == 'N' || choice == 'n')
            break;
        printf("\n\n");

    // 程式重複執行區塊 結束 
    }

	printf("\n感謝您的使用.\n");

    system("pause");

	return 0;

// 主程式 結束 
}

// 計算 GCD 函式 開始
int gcd(int x, int y)
{
    // 定義暫存數字 
	int z;
	if(x<0)	x=-x;

    // 輾轉相除法 
	while(z=x%y)
	{	x=y;	y=z;	}

	return y;
// 計算 GCD 函式 結束 
}

// 計算 LCM 函式 開始
int lcm(int x, int y)
{
	int rx, ry, gcdnum;

    // 呼叫計算 GCD 函式 
	gcdnum = gcd(x,y);

    // 計算個別數字為 GCD 的倍數 rx ry
	rx = x/gcdnum;
	ry = y/gcdnum;

    // 數學公式 : LCM = GCD * (X/GCD) * (Y/GCD)
	return gcdnum * rx * ry;
// 計算 LCM 函式 結束 
}

範例三 計算費氏級數 include stdio.h stdlib.h

// 計算費氏數列函式原型 - 遞迴 
int rfib(int);

// 計算費氏數列函式原型 - 非遞迴
int fib(int);

// 主程式 開始
int main()
{
    // 定義存放使用者輸入數字的變數 
	int x;
    // 定義是否繼續的變數 
    char choice;

    printf("費伯納數列計算程式 : ");

	// 程式重複執行區塊 開始
	while(1)
	{
        // 使用者輸入 
    	printf("請輸入一個正整數 : ( 輸入 0 離開程式 ) ");
    	scanf("%d", &x);

	if(x == 0)
	{
		printf("結束使用程式.\n");
		break;
	}

        printf("\n  遞迴計算 Fib(%d) = %d\n", x, rfib(x));
        printf("\n非遞迴計算 Fib(%d) = %d\n", x, fib(x));

        //printf("\n請問是否要繼續計算費伯納數列 ? (按任意鍵繼續, 輸入 N / n 離開) ");
        //choice=getche();
        //if(choice == 'N' || choice == 'n')
        //    break;
        printf("\n\n");

    // 程式重複執行區塊 結束 
    }

	printf("\n感謝您的使用.\n");

    //system("pause");

	return 0;

// 主程式 結束 
}

// 計算費氏數列函式原型 - 遞迴 開始 
int rfib(int n)
{
    // fib(0) = 0
    if(n == 0)
        return 0;
    // fib(1) = 1
    else if(n == 1)
        return 1;
    // 數學公式 fib(n) = fib(n-1) + fib(n-2)
    else
        return rfib(n-1)+rfib(n-2);
// 計算費氏數列函式原型 - 遞迴 結束 
}

int fib(int n)
{
    // 定義變數 fib(n-2)  fib(n-1) 
    int x = 0, y = 1, tmp;
    // fib(0) = 0
    if(n == 0)
        return 0;
    if(n == 1)
        return 1;
    else
    {
        for(int i = 2; i <= n; i++)
        {
            tmp = y;
            y+=x;
            x = tmp;
        }
        return y;
    }
}

範例四 尋找質數 include stdio.h stdlib.h stdbool.h

// 定義每發現多少個質數就擴大陣列 
#define PSTEPNUM 100

// 主程式 開始
int main()
{
    // 定義質數陣列指標及暫存用陣列指標 
	int *prime, *tmp;
    // 定義使用者輸入的最大數字, 已找到質數個數, 舊的質數陣列最大數字, 質數陣列最大數字
	int unum, pc, oldpcmax, pcmax;
    // 是否為質數的旗標 
	bool pflag;
    // 判斷是否繼續使用程式的變數 
    char choice;

    printf("找質數程式 : \n\n");

	// 程式重複執行區塊 開始
	while(1)
	{
        // 初始化變數 
        unum = -1;
        pc = 0;
        // 質數陣列最大數字(預設值為 PSTEPNUM)
        pcmax = PSTEPNUM;

		printf("請輸入一個正整數, 找比它小的質數 : (輸入 0 離開程式)");
        scanf("%d", &unum);

        // 使用者輸入數字錯誤處理 
    	if(unum == 0)
    	{
    		printf("正常關閉程式.\n");
    		break;
    	}
    	else if(unum < 0)
    	{
    		printf("輸入數字不合規定.\n");
    		exit(0);
    	}

        // 動態取得質數陣列空間 
    	prime = (int*)malloc(sizeof(int)*pcmax);

        // 從 2 開始找質數 
    	for(int i = 2; i < unum; i++)
    	{
            // 2 就是第一個質數 
    		if(i == 2)
    		{
    			prime[pc] = 2;
    			pc++;
                printf("p");
    		}
    		else
    		{
                // 質數已放滿質數陣列 
    	   		if(pc >= pcmax)
    			{
                    // 動態取得暫存用陣列
    				oldpcmax = pcmax;
    				tmp = (int*)malloc(sizeof(int)*oldpcmax);

                    // 複製質數陣列到暫存用陣列 
    				for(int j = 0; j < oldpcmax; j++)
    				{
    					tmp[j] = prime[j];
    				}

                    // 清除質數陣列 
    	   			free(prime);

                    // 動態取得新的質數陣列 
    				pcmax+=PSTEPNUM;
    				prime = (int*)malloc(sizeof(int)*pcmax);

                    // 複製暫存用陣列到新的質數陣列 
    				for(int j = 0; j < oldpcmax; j++)
    				{
    					prime[j] = tmp[j];
    				}

                    // 清除暫存用陣列
    				free(tmp);
    				printf("+");
    			}
    			else
    			{
                    // 預設數字是質數 
    				pflag = true;

                    // 找質數迴圈 : 逐一檢查是否為已發現質數的倍數 
    				for(int k = 0; k < pc; k++)
    				{
    					if(!(i%prime[k]))
    					{
                            // 發現為質數的倍數, i 就不是質數. 跳出找質數迴圈 
    						pflag = false;
    						break;
    					}
    				}

                    // 若發現質數則記錄質數 
    				if(pflag)
    				{
    					prime[pc] = i;
    					pc++;
    					printf("p");
    				}
    			}
    		}
    	}

    	printf("\n\n發現質數個數 : %d\n", pc);

        // 輸出質數陣列 
    	for(int i = 0; i < pc; i++)
    	{
    		printf("%6d ", prime[i]);
    		if(!((i+1)%10))
    			printf("\n");
    	}

    	printf("\n");

        // 清除質數陣列 
    	free(prime);

        //printf("\n請問是否要繼續找質數 ? (按任意鍵繼續, 輸入 N / n 離開) ");
        //choice=getche();
        //if(choice == 'N' || choice == 'n')
        //    break;
        //printf("\n\n");

    // 程式重複執行區塊 結束 
    }

	printf("\n感謝您的使用.\n");

    system("pause");

   	return 0;

// 主程式 結束 
}

範例五 單字排序 include stdio.h stdlib.h string.h

// 定義單字最長的長度
#define MAXWLEN 512

// 排序單字函式原型
void sortWordCard(char**,int,int);

// 主程式 開始
int main()
{
	// 定義單字個數, 使用者輸入單字個數結果, 排序方式
	int word_count, uin, sort_type;
	// 定義二維單字陣列指標, 暫存用一維單字陣列
	char **wordcard, tmpword[MAXWLEN];

	printf("單字排序程式\n");

	// 程式重複執行區塊 開始
	while(1)
	{
		// 初始化單字個數, 使用者輸入單字個數結果
		word_count = uin = 0;

		// 使用者輸入單字個數
		printf("\n1. 請輸入要排序的單字(長度需小於 %d)個數 ? (輸入 0 離開程式)", MAXWLEN);
		uin = scanf("%d", &word_count);

		// 單字個數錯誤處理, 結束程式
		if(uin == 0 || word_count < 0 )
		{
			printf("輸入個數不合規定.\n");
			break;
		}
		else if( word_count == 0)
		{
			// 結束程式
			break;
		}

		// 輸入排序方式
		printf("   請輸入排序方式\n   1) 按字母大小排序(大寫字母排在最前面).\n   2) 按字母大小反向排序(小寫字母排在最前面). 請選擇 : ");
		uin = scanf("%d", &sort_type);

		// 排序方式錯誤處理
		if(uin == 0)
		{
			printf("輸入排序方式不合規定.使用預設排序:按字母大小排序(大寫字母排在最前面).\n");
			sort_type = 1;
		}

		// 排序方式對應傳遞參數
		switch(sort_type)
		{
			case 1:         sort_type = 1;  break;	// 大寫字母排在最前面且按字母大小排序
			case 2:         sort_type = -1; break;	// 小寫字母排在最前面且按字母大小反向排序
			default:        printf("輸入排序方式不合規定.使用預設排序:按字母大小排序(大寫字母排在最前面).\n");
					sort_type = 1;  break;	// 預設排序方式
		}

		// 動態取得二維單字陣列第一層陣列, 儲存第二層單字陣列第一個元素的位址
		wordcard = (char**)malloc(sizeof(char*)*word_count);

		// 接收使用者輸入的單字
		printf("\n2. 請輸入要排序的單字(使用空白分隔)\n");
		for(int i = 0; i < word_count; i++)
		{
			// 先使用暫存用一維單字陣列
			scanf("%s",tmpword);
			// 動態取得二維單字陣列第二層陣列, 儲存單字
			wordcard[i] = (char*)malloc(sizeof(char)*strlen(tmpword));
			// 複製暫存用一維單字陣列到單字陣列
			strcpy(wordcard[i],tmpword);
			//scanf("%s",wordcard[i]);
		}

		// 清掉所有尚未使用的輸入
		fflush(stdin);

		printf("\n3. 排序單字\n");
		// 呼叫排序程式
		sortWordCard(wordcard, word_count, sort_type);

		// 顯示排序結果
		printf("\n\n4. 依序顯示輸入單字\n");
		for(int i = 0; i < word_count; i++)
		{
			printf("%s\n",wordcard[i]);
		}

	// 程式重複執行區塊 結束
	}

	printf("\n感謝您的使用.\n");

    system("pause");
	return 0;

// 主程式 結束
}

// 排序單字函式實作 開始
void sortWordCard(char** w, int l, int st)
{
	char *tmp;

	// 預設排序 : 依照字母順序
	if(st != 1 && st != -1)
		st = 1;

	/* 除錯使用
	for(int i=0; i0; j--)
		{
			// 使用 strcmp() 比較是否需要交換位置
			if(strcmp(*(w+(j-1)),*(w+j)) == st)
			{
				// 將 w 視為一個儲存字串起點的陣列, 使用一個 tmp 指標交換指向位址
				tmp = w[j];
				w[j] = w[j-1];
				w[j-1] = tmp;
			}
		}
		printf(".");
	}

// 排序單字函式實作 結束
}

範例六 蝸牛方陣 include stdio.h stdlib.h

// 主程式 開始
int main()
{
	// 判斷是否繼續使用程式的變數 
	char choice;
	// 定義陣列指標, 方陣大小, X軸位置, Y軸位置, 順時針/逆時針方向, 起點位置, 由小到大或由大到小, 輸入檢查
	int **snail, size, x, y, clock, dir, start, sob, uin;

	printf("蝸牛矩陣產生程式 : \n\n");

	while(1)
	{
		fflush(stdin);
		printf("請輸入方陣大小 : (輸入 0 離開程式) ");
		uin = scanf("%d", &size);

		// 使用者輸入數字錯誤處理
		if(size == 0)
		{
			printf("正常關閉程式.\n");
			break;
		}
		else if(size < 0 || uin == 0)
		{
			printf("輸入數字不合規定.\n");
			exit(0);
		}

		fflush(stdin);
		printf("請問要 1) 順時針 / 2) 逆時針方向走 : ");
		uin = scanf("%d", &clock);

		if(uin == 0)
		{
			clock = 1;
			printf("輸入方向不合規定. 使用預設值 順時針\n");
		}

		//起點位置
		switch(clock)
		{
			case 1:
			case 2:		x = -1;	y = 0;	dir = 0;	break;
			default:	x = -1;	y = 0;	dir = 0;	clock = 1;
					printf("輸入方向不合規定. 使用預設值 順時針\n");	break;
		}

		fflush(stdin);
		printf("請問起點在 1) 左上 2) 左下 3) 右上 4) 右下 : ");
		uin = scanf("%d", &start);

		if(start < 1 || start > 4 || uin == 0)
		{
			start = 1;
			printf("起點選擇錯誤, 使用預設值 左上起點\n");
		}

		fflush(stdin);
		printf("請問要 1) 由小到大 / 2) 由大到小 : ");
		uin = scanf("%d", &sob);

		if(sob != 1 && sob !=2 || uin == 0)
		{
			sob = 1;
			printf("大小排序選擇錯誤, 使用預設值 由小到大\n");
		}

		/// For Debug ///
		//printf("(%d)(%d)(%d)\n", dir, clock, size);

		// 動態取得質數陣列空間
		snail = (int **)malloc(sizeof(int *)*size);
		for(int i = 0; i < size; i++)
		{
			snail[i] = (int *)malloc(sizeof(int)*size);
		}

		// 初始化方陣
		for(int i = 0; i < size; i++)
		{
			for(int j = 0; j < size; j++)
			{
				snail[i][j] = 0;
			}
		}

		/// For Debug ///
		//printf("(%d)(%d)(%d)\n", dir, clock, size);

		// 使用老鼠走迷宮方式探測方陣
		for(int i = 1; i <= size*size; i++)
		{
			// 順時針 右 0 下 1 左 2 上 3   逆時針 下 3 右 2 上 1 左 0
			// 先按照既定方向走一格
			/// For Debug ///
			//printf("(%d)(x=%d)(y=%d)\n", dir, x, y);
			switch(dir%4)
			{
				case 0:		x++;	break;
				case 1:		y++;	break;
				case 2:		x--;	break;
				case 3:		y--;	break;
			}
			// 檢查 X 軸是否越界, 越界就退回並轉向
			if(x >= size)
			{
				x--;	dir++;	y++;
			}
			else if(x < 0)
			{
				x++;	dir++;	y--;
			}

			// 檢查 Y 軸是否越界, 越界就退回並轉向
			if(y >= size)
			{
				y--;	dir++;	x--;
			}
			else if(y < 0)
			{
				y++;	dir++;	x++;
			}

			// 下一站已經填了數字 : 回頭 -> 轉向 -> 定位
			if(snail[x][y])
			{
				switch(dir%4)
				{
					case 0:         x--;	dir++;	y++;	break;
					case 1:         y--;	dir++;	x--;	break;
					case 2:         x++;	dir++;	y--;	break;
					case 3:         y++;	dir++;	x++;	break;
				}
			}

			snail[x][y] = (sob%2) ? i : size*size-i+1;
		}

		printf("\n");

		// 輸出方陣

		if(start == 1)
		{
			for(int i = 0; i < size; i++)
			{
				for(int j = 0; j < size; j++)
				{
					if(clock == 1)
						printf("%3d ", snail[j][i]);
					else
						printf("%3d ", snail[i][j]);

					if(j == size - 1)
						printf("\n");
				}
			}
		}
		else if(start == 2)
		{
			for(int i = size -1; i >= 0; i--)
			{
				for(int j = 0; j < size; j++)
				{
					if(clock == 1)
						printf("%3d ", snail[i][j]);
					else
						printf("%3d ", snail[j][i]);

					if(j == size - 1)
						printf("\n");
				}
			}
		}
		else if(start == 3)
		{
			for(int i = 0; i < size; i++)
			{
				for(int j = size - 1; j >= 0; j--)
				{
					if(clock == 1)
						printf("%3d ", snail[i][j]);
					else
						printf("%3d ", snail[j][i]);

					if(j == 0)
						printf("\n");
				}
			}
		}
		else if(start == 4)
		{
			for(int i = size-1; i >= 0; i--)
			{
				for(int j = size-1; j >= 0; j--)
				{
					if(clock == 1)
						printf("%3d ", snail[j][i]);
					else
						printf("%3d ", snail[i][j]);

					if(j == 0)
						printf("\n");
				}
			}
		}

		//printf("\n請問是否要繼續產生蝸牛矩陣 ? (按任意鍵繼續, 輸入 N / n 離開) ");
		//choice=getche();
		//if(choice == 'N' || choice == 'n')
		//	break;
		printf("\n");

	// 程式重複執行區塊 結束 
	}


// 主程式 結束
}

範例七 魔方陣 include stdio.h stdlib.h

int main()
{
	int size = 0, uin, x, y, nx, ny;
	int **magicmatrix;

	while(1)
	{
		size = uin = 0;
		printf("請輸入方陣大小, 必須為奇數的正整數 ( 輸入 0 結束程式 ) ");
		uin = scanf("%d", &size);
		if(size == 0)
		{
			printf("結束使用程式.\n");
			break;
		}
		else if(size < 0 || !(size%2))
		{
			continue;
		}
		else if(uin == 0)
		{
			printf("方陣大小不符規定.\n");
			exit(0);
		}

		printf("產生空的方陣\n");
		magicmatrix = (int **)malloc(sizeof(int*)*size);
		for(int i = 0; i < size; i++)
		{
			magicmatrix[i] = (int *)malloc(sizeof(int)*size);
		}
		for(int i = 0; i < size; i++)
		{
			for(int j = 0; j < size; j++)
			{
				magicmatrix[i][j] = 0;
			}
		}

		printf("開始填方陣\n");
		//起點
		x = size/2;
		y = 0;
		magicmatrix[x][y] = 1;
		//
		for(int i = 2; i <= size*size; i++)
		{
			// 先往右上
			nx = (x + 1) % size;
			ny = (y+size-1) % size;

			if(magicmatrix[nx][ny])
			{
				// 碰壁填下方
				nx = x;
				ny = (y+1) % size;
			}

			/// For Debug ///
			//printf("x=%d y=%d nx=%d ny=%d\n", x, y, nx, ny);

			// 開始填方陣
			x = nx;
			y = ny;
			magicmatrix[x][y] = i;
		}

		printf("輸出結果\n");
		for(int i = 0; i < size; i++)
		{
			for(int j = 0; j < size; j++)
			{
				printf("%3d ", magicmatrix[j][i]);
			}

			printf("\n");
		}

		printf("\n");
	}

	printf("感謝使用.\n");

	return 0;
}

No comments: