C primer plus 第六版 第十一章 第十一題題 程式設計練習答案

Aeron-A發表於2019-01-05

Github地址:φ(>ω<*)這裡這裡。

/*
    編寫一個程式,讀入10個字串或者讀到EOF時停止。該程式為使用者提供一個有5個選項的選單
    1、列印源字串列表; 
    2、以ASCII中的順序列印字串;
    3、按長度遞增順序列印字串;
    4、按字串中第一個單詞的長度列印字串
    5、退出。
    選單可以迴圈顯示,除非使用者選擇退出選項。
    (T▽T)我想要今晚寫完練吉他 --2018.December.28
    德瑪西亞————今天剛開工。。--2018.December.30
    今天外面走了四公里,感覺自己老了,感覺要猝死了啊。。還有程式碼沒寫完(T ^ T) --2018.December.31
    今天要完成它!!!! --2019.January.2nd
    一天一個函式,總有一天可以完成它。 -- 2019.January.3rd
    哈哈,今天完工了!!!!!! -- 2019.January.5th
*/
/*
    解題思路:首先,你們開啟音樂播放器,搜尋並播放 “朗格里格朗浪” 。(`・ω・´)
    我先建立基本的迴圈,先獲取使用者輸入;然後switch來響應使用者輸入。
    具體請看各函式的定義部分,裡面有講解。函式原型這邊如果寫講解,開頭會很長,不好review程式碼。
*/
 

#include<stdio.h>
#include<string.h>

#define o 10
#define p 100

void del_n(char *p1[o]);	// 刪除fgets()函式儲存的換行符。

char menu(void);			// 選單函式。

void print1(char *p1[o]);	// 選單操作1:原樣輸出。

void print2(char *p1[o]);	// 選單操作2:據ASCII碼字母表順序排序字串。

void print3(char *p1[o]);	// 選單操作3:順序遞增排序字串。

void print4(char *p1[o]);   // 選單操作4:按字串中第一個單詞的長度列印字串。

int main(void)
{
	int i = 0;
	char chose = 0;
	char name[o][p] = {};
	char *p1[o];

	printf("Please input 10 string(Press Enter to continue):\n");

	// 獲取輸入操作,並把輸入儲存到 十個指向 char的指標。
	// 這麼做參考書上 P359 的 stsrt()函式定義部分。 char *p[] 操作。
	// 使用該操作的好處:對於函式定義部分來說,構建的程式碼更清晰易懂,也更簡潔優美。
	for(i = 0; i < o; i++)
	{
		fgets(name[i], p, stdin);

		p1[i] = name[i];  // 沒問題。
	}

	putchar('\n');
	del_n(p1);

	// 選單部分,呼叫函式響應使用者輸入。
	while(chose != 'q')
	{
		chose = menu();
		switch(chose)
		{
			case 'a':
				print1(p1);
				break;
			case 'b':
				print2(p1);
				break;
			case 'c':
				print3(p1);
				break;
			case 'd':
				print4(p1);
			case 'q':
				break;
			default:
				printf("\nError with code(Line 86)\n");
				break;
		}

		if(chose == 'q')
		{
			break;
		}

	}

	printf("Bye~\n");
	getchar();

	return 0;
}

char menu(void)
{
	// 本函式為選單輸出與return使用者選項函式。
	int i = 0;
	char chose;

	while(i < 100)
	{
		putchar('*');
		i++;
	}

	i = 0;

	printf("\nThere are 5 features you can use:\n");

	printf("	a、列印源字串列表;               "                          
	"b、以ASCII中的順序列印字串.\n");

	printf("	c、按長度遞增順序列印字串;           "
	"d、按字串中第一個單詞的長度列印字串.\n");

	printf("	q、退出。\n");
	
	while(i < 100)
	{
		putchar('*');
		i++;
	}

	i = 0;

	printf("\nNow, Please input your chose:\n");
	chose = getchar();
	fflush(stdin);

	return chose;
}

void print1(char *p1[o])
{
	// 本函式原樣輸出,這個就不多說了。。 
	printf("\n列印效果如下:\n");

	for(int i = 0; i < o; i++)
	{
		printf("%s\n", p1[i]);
	}

	printf("\nOver ~\n\n");

	return;
}

void print2(char *p1[o])
{
	// 本函式的核心部分--排序 參考了書 P359 的 stsrt()函式,使用了 char *p[10] 操作方式。
	// 該操作使程式碼的整體構建 簡潔優美,清晰易懂。 這比我之前用 char(*p)[10] 的好多了。
	// char (*P)[10]的意思是宣告一個指向陣列的指標,該指標內含[10]個char元素值。
	// char *p[10]的意思是宣告 一個內含10個元素的陣列p, *表示p陣列內含10個指標。 最後char讓p陣列內的指標都指向char。
	// *p[10]就像一個陣列 p[10][],操作起來比 (*p)[10]方便多了。。。
	int i = 0;
	int j = 0;
	char * temp;

	// 建立副本。為了儲存原始資料。
	char *p21[o];
	for(int i = 0; i < o; i++)
	{
		p21[i] = p1[i];
	}

	printf("\n列印效果如下:\n");

	for(i = 0; i < o-1; i++)
	{
		for(j = i + 1; j < o; j++)
		{
			if( strncmp(p21[j], p21[i], 1) < 0)
			{
				temp = p21[i];
				p21[i] = p21[j];
				p21[j] = temp;
			}
		}

		printf("%s\n", p21[i]);
	}

	// 根據外層for的表示式,在最後一次就退出迴圈,故而補一個輸出語句。
	printf("%s\n", p21[i]);

	return;
}

void print3(char *p1[o])
{
	// 本函式構建思路:
	// 我打算建立一個 一維陣列[o] , 然後for迴圈strlen出每個 p3[i]的長度,並儲存到一位陣列[i]中。
	// 然後再用巢狀for迴圈比較 一位陣列[o]的各個值,再用巢狀迴圈的變數 i 和 j 來操作 p3[i] , p3[j]。
	// Tips: 根據自創的Debug集合,使用fgets()函式儲存字串的話,\n不處理掉,strlen會計算它。。請注意上下文。
	int i = 0;
	int j = 0;
	int temp1 = 0;
	char * temp;
	char length[o] = {};

	// 建立副本。為了儲存原始資料。
	char *p31[o];
	for(int i = 0; i < o; i++)
	{
		p31[i] = p1[i];
	}

	// 儲存10個字串各自的長度。
	for(int i = 0; i < o; i++)
	{
		// 沒問題。
		length[i] = strlen(p31[i]);
	}

	// 輸出 操作3 結果。
	printf("\n列印結果如下:\n");
	for( i = 0; i < o-1; i++)
	{
		for( j = i + 1; j < o; j++)
		{
			if(length[i] > length[j])
			{	
				temp1 = length[i];
				length[i] = length[j];
				length[j] = temp1;

				temp = p31[i];
				p31[i] = p31[j];
				p31[j] = temp;
			}
			//printf("Line 227, %s, \n", p31[i]);
		}
		printf("%s\n", p31[i] );
	}

	// 根據外層for的表示式,在最後一次就退出迴圈,故而補一個輸出語句。
	printf("%s\n", p31[i]);	

	return;
}

void print4(char *p1[o])
{
	// 思路:
	// 遍歷這個陣列,然後if判斷空字元,再建立一個一位陣列儲存長度。
	// 再copy print3的程式碼,比較長度排序字串後在輸出。
	int length[o] = {};

	int i = 0;
	int j = 0;
	int leng = 0;		// 儲存長度。

	int temp1 = 0;		
	char * temp;

	// 建立副本。
	char *p41[o];
	for(int i = 0; i < o; i++)
	{
		p41[i] = p1[i];
	}

	// 儲存每個字串第一個單詞的長度。
	for(i = 0; i < o; i++)
	{
		for(leng = 0, j = 0; p41[i][j] != ' '; j++) 
		{
			leng++;
		}

		length[i] = leng;

		printf("\n測試:長度為 %d .\n", length[i] );
	}

	// 輸出 操作4 結果。
	printf("\n列印結果如下:\n");
	for( i = 0; i < o-1; i++)
	{
		for( j = i + 1; j < o; j++)
		{
			if(length[i] > length[j])
			{	
				temp1 = length[i];
				length[i] = length[j];
				length[j] = temp1;

				temp = p41[i];
				p41[i] = p41[j];
				p41[j] = temp;
			}
		}
		printf("%s\n", p41[i] );
	}
	// 根據外層for的表示式,在最後一次就退出迴圈,故而補一個輸出語句。
	printf("%s\n", p41[i]);	

	return;
}

void del_n(char *p1[o])
{
	// 本函式只為刪除 fgets()函式儲存的換行符。
	int i = 0;
	int j = 0;

	// 測試完畢~
	for(i = 0; i < o; i++)
	{
		for(j = 0; j < p; j++)
		{
			if(p1[i][j] == '\n')
			{
				p1[i][j] = '\0';
				break;
			}
		}
	}

	return;
}

 

相關文章