課程:程式設計

出自 陳富國維基館
前往: 導覽搜尋

目錄

課程大綱

電腦被廣泛地應用在各行各業,從科學、商業、個人、學習等都可看到各式各樣的程式(在行動裝置上的程式被稱作App),學習程式撰寫在於學習程式語言工具如何被用來解決各領域的問題,本章列出所有的問題,分析問題,並且告知可用何種程式語言元素來解決,透過連結來存取解決問題所需程式元素的說明,建立起該程式元素的應用技巧與知識。

課程簡介

使學生熟悉結構化之程式語言並學習設計C++程式之過程以建立C++程式設計之能力。

教學目標

  1. 熟悉結構化之程式語言
  2. 學習設計程式之過程
  3. 建立程式設計之能力
  4. 培養學生操作電腦之能力
  5. 利於學生獲得相關證照之取得
  6. 增加學生對程式設計之興趣
  7. 激發學生利用程式設計之能力輔助日後相關課程之學習

指定書目

快速掌握C++程式設計, 文淵閣工作室編著, 文魁行銷股份有限公司, ISBN-13:978-986-620-612-2 。

參考書目/資料

程式設計電腦輔助學習教材(上網學習)

教學進度

第 1 週 1.課程綱要介紹;2.教科書;3.參考書介紹;4.計分標準說明;5.C 語言簡介;6.前測

第 2 週 1.編譯器、連結器功用說明;2.程式開發工作環境介紹

第 3 週 1.基本資料型態;2.變數;3.常數;4.運算式;5.運算元;6.運算子;7.型別轉換

第 4 週 1.基本資料型態;2.變數;3.常數;4.運算式;5.運算元;6.運算子;7.型別轉換

第 5 週 1.格式化輸出函數;2.格式化輸入函數

第 6 週 1.循序式結構;2.單選選擇式結構;3.二選一選擇式結構;4.多選選擇式結構;5.巢狀選擇式結構

第 7 週 1.循序式結構;2.單選選擇式結構;3.二選一選擇式結構;4.多選選擇式結構;5.巢狀選擇式結構

第 8 週 1.循序式結構;2.單選選擇式結構;3.二選一選擇式結構;4.多選選擇式結構;5.巢狀選擇式結構

第 9 週 期中考試(筆試與上機考試)

第10週 迴圈式結構

第11週 巢狀迴圈式結構

第12週 一維陣列及其初始化

第13週 二維陣列及其初始化;多維陣列

第14週 字串

第15週 副程式

第16週 副程式

第17週 副程式傳值呼叫與傳址呼叫

第18週 期末考試

評分方法

  • 平常成績 30% (到課率、作業、小考等)
  • 期中考 30%
  • 期末考 40%

程式問題解決中心 (Problem Solving Center)

基本與數學問題

二數比大小(易)

問題:二個數,要如何找出其中的大值與小值 做法:設max為大值,min為小值

//找大值
  if (a > b) max = a;
  else max = b;
//找小值
  if (a > b) min = b;
  else min = a;

三數比大小(易)

問題:三個數,要如何找出其中的大值與小值 做法:設max為大值,min為小值,先將a指定給max與min…

  max = a;
  min  = b;
  if (b > max) max = b;
  if (c > max) max = c; 

  if (b < min) min = b;
  if (c < min) min = c;

三數由小到大印出(易)

做法:延續上題,設max為大值,min為小值,先將a指定給max與min…,取得max與min值後,中間值=三數相加-(max+min) 註:比較正規的做法是先將數字排序,再依序印出數值。

  max = a;
  min  = b;
  if (b > max) max = b;
  if (c > max) max = c; 

  if (b < min) min = b;
  if (c < min) min = c;

  cout << "數值由小到大為  " << min << ","  << (a+b+c) - (min+max)  << "," << max << endl;

進位的轉換(中)

做法: 進位間的轉換用簡單的除法即可以得出(長除法),將要轉換的數值不斷地除以基底數,
直到最後的商小於基底數,結果就是最後的商+最後的餘數+最後第二次的餘數+…+第一次的餘數,
若是把除的過程中的餘數輸出,結果剛好是相反的,因此,我們將餘數先放到一個陣列中,
整個除完後,最後的商放入陣列,再用一個迴圈將此陣列的值從右到左的方式印出。

#include <iostream>
#include <fstream>
using namespace std;


void main(void){
	char hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};

	int num;
	cout << "請輸入一數:" ; cin >> num;
	int base;
	cout << "請輸入進位數(2, 8, 16):" ; cin >> base;
	int r; 
	int output[100];
	int counter = 0;
	while (num >= base) {
		r = num % base; //取餘數
		output[counter++] = r;
		num = num / base;//取商數
	}
	output[counter] = num;

	while (counter >= 0) cout << hex[  output[counter--]   ]; 
	

	system("pause");
}

因數的判斷(易)

問題:求一數f是否為某數N的因數,也就是說,f是否能整除N。

做法:整除的判斷即檢查N被f除後,餘數是否為0。在C/C++中,求餘數的運算子為%。

程式範例解答

#include <iostream>
using namespace std;
void main(){
  float f, N;
  cout<<"請輸入N(被除數)與f(除數)"
  cin>>f >> n;
  if(N%f == 0){
    cout<< cout << f << "可整除" << N << endl;
  } 
  system("pause");
}

閏年的判斷(易)

問題:公元年哪時候二月會閏月?

做法:判斷y是否被400整除,可以被4整除不被100整除。

程式範例解答

#include <iostream>
using namespace std;
void main(){
  int year;
  cout<<"請輸入年份"
  cin>>year;
  if(year%=400==0)||(year%4==0&&year%100!=0){
    cout<< "西元" << year << "年是閏年" << endl;
  }
  else{
    cout<< "西元" << year << "年是閏年" << endl;
  } 
  system("pause");
}

質數的判斷(中)

問題:一數N若為質數,N的因數僅有1與本身數N,也就是說若2~(N-1)中有N之因數(可整除N),那麼N即不是質數。

做法: 1.使用一個布林變數isPrime,初值為true(此布林變數表示N是否為質數,程式一開始先認定N為質數)

(迴圈開始) 2.使用一迴圈敘述,使用迭代變數i,下限值為2,上限值為N-1,若i可整除N,設定isPrime為false,跳出迴圈 (迴圈結束)

3.判斷isPrime為true輸出N為"質數",否則,輸出輸出N為"不是質數"。

程式範例解答

#include <iostream>
using namespace std;
void main(){
  int N = 11;
  int i = 2;
  bool isPrime = true;
  while (i <= N-1 && isPrime){
    if (N % i == 0) {
    isPrime = false;
    break;
  }
  i++;
  }
  if (isPrime){
    cout << "是質數";
  } else {
    cout << "不是質數";
  }
  system("pause");
}

質因數(中+)

問題:印出一數N的質因數 做法: 判斷2~(N-1)是否為N的因數,並且是否為質數

程式範例解答

#include <iostream>
using namespace std;
void main(void){
  int n;
  cout<<"請輸入";
  cin>>n;
  for(int i=2;i<= n-1;i++ ){
    if(n%i==0){
      bool Isprime=true;
      for(int j=2;j<=i-1&& Isprime;j++){
         if(i%j==0){
           Isprime=false;
           break;
        }
      }
      if (Isprime){
        cout<<i<<endl;
      }
    }
  }
  system("pause");
}

求一數的次方(易/中)

問題:n的p次方 = 將n自乘p次。

迴圈解步驟:

  1. 宣告一浮點數 powerOfn = 1
  2. 使用一個迴圈跑p次,powerOfn = powerOfn*n; (若p為負數,取其絕對值,也就是將p乘-1,可用stdlib裏的abs函式)
  3. 若p是負數,則powerOfn = 1/powerOfn;
  4. 印出powerOfn

遞迴解 ‧ 請看下面程式範例解答,追蹤一次。(請參考用遞迴做到迴圈效果的說明。)

程式範例解答

#include <cstdlib>
#include <iostream>
#include <stdlib.h> //為了使用abs取絕對值函式
using namespace std;
float base_power(float b,int p){
  if(p==0) return 1; 
  else if (p>0) return base_power(b,p-1)*b; 
  else return base_power(b,p+1)/b; 
}
float bp(float b, int p){
  float r=1.0;
  for (int i = 1; i <= abs(p); i++) r *= b;
  if (p < 0) r = 1/r;
  return r;
}
void main(int argc, char *argv[]){
  int base,power,result;
  cout<<"請輸入base值";
  cin>>base;
  cout<<"請輸入power值";
  cin>>power;
  cout << base_power(base, power);
  system("PAUSE");
}

完全數(中)

公因數(中)

公倍數(中)

費式級數(中)

九九乘法表 - 一般迴圈解與遞迴解(中)

#include <iostream>
#include <iomanip>

using namespace std;

/*
注意:下面遞迴用法,若是先遞回後印,則為遞增,若是先印後遞回,則為遞減

*/

void LoopJ1(int j, int i, int min){
	if (j > min) LoopJ1(j-1, i, min);
	cout << i << "*" << j << "=" << setw(2) <<  i*j<< "  ";
}

void LoopI1(int i, int min){
	if (i > min) LoopI1(i-1, min); 
	LoopJ1(9, i, min);
	cout << endl;
}


void LoopJ2(int j, int i, int min){
	cout << i << "*" << j << "=" << setw(2) <<  i*j<< "  ";
	if (j > min) LoopJ2(j-1, i, min);
}

void LoopI2(int i, int min){
	LoopJ2(9, i, min);
	cout << endl;
	if (i > min) LoopI2(i-1, min); 
}

void main(void){
	cout << "迴圈遞增示範:"<< endl;
	for (int i = 1; i <= 9; i++){
		for (int j=1; j <= 9; j++){
			cout << i << "*" << j << "=" << setw(2) <<  i*j<< "  ";
		}
		cout << endl;
	}
	
	cout << "遞迴遞增示範:"<< endl;
	LoopI1(9,1);

	cout << "迴圈遞減示範:"<< endl;
	for (int i = 9; i >= 1; i--){
		for (int j=9; j >= 1; j--){
			cout << i << "*" << j << "=" << setw(2) <<  i*j<< "  ";
		}
		cout << endl;
	}

	cout << "遞迴遞減示範:"<< endl;
	LoopI2(9,1);
	system("pause");
}


  • 練習,將下列進位轉換程式以遞迴方式改寫迴圈敘述。
void main(void){
	char hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};

	int num;
	cout << "請輸入一數:" ; cin >> num;
	int base;
	cout << "請輸入進位數(2, 8, 16):" ; cin >> base;
	int r; 
	int output[100];
	int counter = 0;
	while (num >= base) {
		r = num % base; //取餘數
		output[counter++] = r;
		num = num / base;//取商數
	}
	output[counter] = num;

	while (counter >= 0) cout << hex[  output[counter--]   ]; 
	

	system("pause");
}

魔方陣(中++)

巴斯卡三角形(中++)

void main(void){
	int M[50][100] = {0};
	int r,c;
	cout << "請輸入巴斯卡三角形的列數:"; cin >> r;
	c = 2*r - 1;

	M[0][c/2] = 1;

	for (int rl = 1; rl < r; rl++) {
		for (int cl = 0; cl < c; cl++) {
			M[rl][cl] = M[(rl-1+r)%r][(cl-1+c)%c] + M[(rl-1+r)%r][(cl+1)%c]; //元素的值為其左上角元素與右上角元素的和
		}
	}

	//底下輸出陣列
	for (int rl = 0; rl < r; rl++) {
		for (int cl = 0; cl < c; cl++) {	
			if (M[rl][cl] == 0) cout << " " << " "; 
			else cout << M[rl][cl] << " ";
		}
		cout << endl;
	}
	
	//以上輸出在超過2位數以上的時候,就無法對齊,請使用setw來固定輸出寬度(自己完成)
	system("pause");
}

河內塔(難)

字串操作

長度計算

尋找字元

字串串接

取子字串

字串反轉

#include <iostream>
#include "stdio.h"

using namespace std;

int main()
{
  char input[80];
  cout << "Input a string: ";
  cin >> input;

  int strLength = 0;
  while (input[strLength++] != '\0') ;

  cout << "The reversed input string is : ";

  for (int i = strLength - 2; i >= 0; i--){
	  cout << input[i];
  }
  cout << endl;
}

字元出現次數統計

資料分級

分數分級(易)

問題:將分數依 A:100~90 B:80~89 C:70~79 D:60~69 E:0~59 分等級
做法有以下幾種:
用if
用switch+除以10
用除以10+陣列解(最漂亮,一行的程式就解決問題!)

1.

  //score為分數變數,浮點數,grade為等級變數,字元
  if (score <=  100 && score >= 90) grade = 'A';
  if (score <=   89 && score >= 80) grade = 'B';
  if (score <=   79 && score >= 70) grade = 'C';
  if (score <=   69 && score >= 60) grade = 'D';
  if (score <=   59) grade = 'E';

2.除以10去掉個位數,判斷上就會較簡單

	float score; char grade;
	cout << "請輸入成績:"; cin >> score;

	score = (int)(score / 10); //去掉個位數

	if  (score == 10 ||
		 score ==  9)  
		                 grade = 'A';
	else if (score == 8) grade = 'B';  
	else if (score == 7) grade = 'C';  
	else if (score == 6) grade = 'D';  
	else                 grade = 'E';  

	cout << "你的成績等級是:" << grade << endl;

3.除以10去掉個位數,用switch

	float score; char grade;
	cout << "請輸入成績:"; cin >> score;

	int s = (int)(score / 10); //去掉個位數
	switch (s) {
	case 10:
	case  9: grade = 'A'; break;
	case  8: grade = 'B'; break;
	case  7: grade = 'C'; break;
	case  6: grade = 'D'; break; 
	default: grade = 'E'; 
	}

	cout << "你的成績等級是:" << grade << endl;

溫度

風速

資料排序

氣泡排序法

插入排序法

資料統計

成績總分

成績報表

銷售/生產統計

銷售/生產報表

商業應用

找零程式

各式時刻表

題目一:弘光巴士發車時刻表

h、m:表開始發車的時與分

step:表發車間隔

  • 迴圈解法:
#include <iostream>
#include <iomanip>

using namespace std;
void main(){
    int count=1, h=6, m=20, step=40;
	for(; h < 24; m+= step, count++){		
		if (m >= 60) {
			h ++;
			m -= 60;
		}
		cout << setw(2) << h << ":" << setw(2) << m << " ";
		if (count %4 ==0) cout << endl;
	} 
	system("pause");
}
  • 遞回解法:
#include <iostream>
#include <iomanip>

using namespace std;
void loop(int count, int h, int m, int step){
	cout << setw(2) << h << ":" << setw(2) << m << " ";
	if (count %4 ==0) cout << endl;
	m+=step; count++;
	if (m >= 60) {
		h ++;
		m -= 60;
	}
	if (h < 24) loop(count, h, m, step);
}

void main(){
    int count=1, h=6, m=20, step=40;
	loop(count, h,m, step);	
	cout << endl;
	system("pause");
}

月曆

#include <iostream>
#include "stdio.h"

using namespace std;

int calcWeekDay(int year, int month, int day){ //計算星期幾

	int TempYear, TempMonth, i, j;
	 if (month >= 3)
	 {
		 TempMonth = month - 2;
		 TempYear = year;
	 } else
	 {
		 TempMonth = month + 10;
		 TempYear = year - 1;
	 }

	 j = TempYear + (int)(TempYear / 4) - (int)(TempYear / 100) +
		 (int)(TempYear / 400) + (int)(2.6 * TempMonth - 0.2) + day;

	 i = j - 7*(int)(j / 7) + 1;
	 
	 return i;
}


void printMonth(int year, int month){
	int i = 0;	
	int day = 1;
	//char* weekDayTitle[] = {"禮拜日", "禮拜一", "禮拜二", "禮拜三", "禮拜四", "禮拜五", "禮拜六"};
	char* weekDayTitle[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
	int monthDays[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
	
	if (month == 2 && ((year % 400 == 0) || ((year % 4 == 0) && (year % 100 !=0))))
	{
		monthDays[2] = 29;
	}

	printf(" 西元 %d 年 %d 月\n", year, month);

	for (i = 0; i < 7; i++){ //印出 Sun Mon.........
		printf("%s ", weekDayTitle[i]);
	}
	printf("\n");

	int weekDay = calcWeekDay(year, month, day);
	int nextLine = 0;
	nextLine = weekDay;
	for (i = 1; i < weekDay; i++){
		printf("    ");
	}

	for (i = 1; i <= monthDays[month]; i++) {
		printf("%3d ", i);
		if (nextLine++ % 7 == 0) printf("\n");
	}
	printf("\n");
}



void main(void){
	for (int month = 1; month <= 12; month++){
		printMonth(2010, month);
	}
}

檢查碼的計算與驗證-身份證為例

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

using namespace std;

int main(void){

	                 //A   B   C   D    E   F  G   H   I   J    K  L   M   N    O  P   Q   R    S   T  U   V   W   X    Y  Z
	int letterNum[] = {10, 11, 12, 13, 14, 15, 16, 17, 34, 18, 19, 20, 21, 22, 35, 23, 24, 25, 26, 27, 28, 29, 32, 30, 31, 33};
	char ID[80];
	char* Message;

	cout << "Input an ID to check... ";
	cin >> ID;
    
	int ID_Length = strlen(ID);

	if (ID_Length != 10 || //身份證長度不是10的話…
		!((ID[0] >= 'a' && ID[9] <= 'z') || (ID[0] >= 'A' && ID[9] <= 'X')) || //第1個字元不是英文字母的話
		!(ID[1] == '1' || ID[1] == '2')) //第2個字元不是1或2的話
	{ 
		Message = "身份證輸入錯誤";
		goto Exit;
	}

	for (int i = 2; i <= ID_Length - 1; i++){
		if (ID[i] < '0' || ID[i] > '9'){
			Message = "身份證輸入錯誤";
			goto Exit;
		}
	}

	if (ID[0] >= 'a' && ID[0] <= 'z'){
		ID[0] -= 32;
	}

	int checkIDNum = letterNum[ID[0]-'A']/10 + (letterNum[ID[0]-'A']%10 * 9);
	checkIDNum += (ID[1]-'0') * 8;

	for (int i = 7;  i >= 1; i--){
		checkIDNum += (ID[9-i]-'0') * i;
	}

	checkIDNum %= 10;

	if (checkIDNum == 0) checkIDNum = 0;
	else checkIDNum = 10 - checkIDNum;

	if (checkIDNum == (ID[9]-'0')) Message = "身份證字號正確";
	else Message = "身份證字號錯誤";
		

Exit:
	cout << endl<< Message;


}

成績報表

程式設計概念

電腦與程式

程式語言

程式執行環境

程式整合開發工具

程式基礎

輸出入敘述

cin

cout

變數與資料型態

字元型態

char

整數型態

  • byte(8位元)
  • short(16位元)
  • int(32位元,預設)
  • long(32位元)

浮點數型態

  • float
  • double(預設)

程式敘述與運算子

選擇與判斷敘述

if/if...else

switch

重覆敘述

goto

goto是程式中可以“跳至“任何一個位置的敘述,首先要先設定一個路標,再用goto跳至這個路標。範例:


Repeat:
cout << "這是我的第一支程式" << endl;
goto Repeat;

上面的程式會重複地執行cin與goto,於是,變成了一個“無窮盡“的迴圈。那要如何讓上面的程式停上來?

char r;

Repeat:
cout << "這是我的第一支程式" << endl;
cout << "是否重複?(按Y表重複)" << endl;
cin >> r;
if ( r == 'Y' || r == 'y') goto Repeat;

上面的程式中,依據使用者輸入Y或y來決定是否執行goto。

while

while是程式中用來判斷是要重複執行的程式元素,底下的程式示範了一個從1印到9的迴圈程式:

  int i = 1;

  while ( i <= 9) {
    cout << i << "  ";
    i++;
  }

  cout << endl;

do while

do..while與while不同之處在於,do...while是先做一次,然後再判斷是否重複。例如,生活中,先嚐一下,好吃繼續吃…

  char r;
  do {  
    cout << "這是我的第一支程式" << endl;
  
    cout << "是否重複?(按Y表重複)" << endl;
    cin >> r;
  } while ( r == 'Y' || r == 'y');

for

for 敘述的語法

先前,我們學會 while、do-while 兩種迴圈的用法,接著我們看第三種迴圈, for 的語法:

for (起始敘述; 條件式; 更新敘述) {指令一;

for (起始敘述; 條件式; 更新敘述) {
  指令一;
  指令二;
  指令三;
}

起始值是進入迴圈一開始要執行的動作,條件式是進入迴圈的條件,而更新值則是執行完每次的迴圈要執行的動作,我們舉個例子來看:

for(i=1; i<=10; i++)  cout << i << ",";

上面的語法,程式執行的步驟如下:

1.設定變數 i=1;
2.檢查 i<=10 是否成立,不成立則跳出迴圈 ( 即跳至 6. )
3.執行 cout << i << ",";
4.執行 i++; ( 即 i=i+1; )
5.跳至 2. 的位置
6.迴圈結束

在 for 迴圈中,我們可以使用 break 和 continue 指令來中斷整個迴圈執行或跳至迴圈結尾處。

如果不需要起始值或更新值,則可以空白,若條件式空白,則為無條件進入迴圈。

如果起始值或更新值有兩個以上,可以用逗點 , 隔開,例如:

for(a=1, b=1; a<=100; a++, b++)

範例:使用for來計算1+2+...+N 之總合

1+2+...+N 之總合可以利用 S= (1+N)*N/2 這個公式直接求解,但這邊我們拿來當for的應用實例,用for讓它從 1 加到 100,整個程式如下:


 int sum=0, i;
 for(i=1; i<=100; i++) sum += i;
 cout << "1+2+...+100= " <<  sum;

上面的 sum 代表總合,一開始是 0,接著每次加上 i 當時的值,而 i 的值會從 1 遞增到 100,最後 sum 的值就是 1 加到 100 的總合了。

格式化輸出敘述

陣列

  陣列是一種連續性的資料儲存空間,一陣列裡的資料型態是一樣的,元素與元素在記憶中的位置是相鄰的,通常我們會利用一個陣列變數來代表整體的資料。

陣列分為一維陣列陣列、二維或多維陣列。

表示方法如下:

資料型態 陣列名稱[陣列大小]; //一維陣列

int a[10];

資料型態 陣列名稱[陣列大小][陣列大小]; //二維陣列 int a[10][10];

宣告陣列變數時,也可一併給與初始值:

  int x[5] = {1,2,3,4,5};
  int y[] = {1,2,3};
  int z[3][4] = {{1,2,3,4},{5,6,7,8},{0,1,2,3}};
  int a[];

上面例子裡的y陣列大小,是由後面{}裡元素的個數決定。int a[]並沒有分配儲存陣列內容的空間,因此可視為指標宣告。

陣列元素的引用方式:

陣列名稱[索引值] a[2]

陣列名稱[索引值][索引值] a[1][2]

索引值是指出要檢索陣列中第幾個元素,在C/C++中,索引值一律從0起算。

字元與字串

字元是單一個字元,以單引號框起來的,如:

'A','a'

字串是一個字元以上的字元陣列,而且,陣列會多一個結束字元'\0',表示字串的結束,字串以雙引號框起來,如:

"I like apple."

"I like programming."

字串既然叫字元陣列,那就能夠以索引的方式來存取字串的每一個字元。如:

char str[] = "I like programming.";
cout << str[4] << endl;

上面程式會輸出k

函式與公用函式(一)

程式進階

函式-遞迴呼叫與公用函式(二)

指標與位址

指標與字串

字串的分割

#include <iostream>
using namespace std;

//字串分割函式,不需要改,直接使用,使用方式請看主程式main
char** str_split( char* str, char delim, int* numSplits ) 
{
    char** ret;
    int retLen;
    char* c;

    if ( ( str == NULL ) ||
        ( delim == '\0' ) )
    {
        /* Either of those will cause problems */
        ret = NULL;
        retLen = -1;
    }
    else
    {
        retLen = 0;
        c = str;

        /* Pre-calculate number of elements */
        do
        {
            if ( *c == delim )
            {
                retLen++;
            }

            c++;
        } while ( *c != '\0' );

        ret = (char **)malloc( ( retLen + 1 ) * sizeof( *ret ) );
        ret[retLen] = NULL;

        c = str;
        retLen = 1;
        ret[0] = str;

        do
        {
            if ( *c == delim )
            {
                ret[retLen++] = &c[1];
                *c = '\0';
            }

            c++;
        } while ( *c != '\0' );
    }

    if ( numSplits != NULL )
    {
        *numSplits = retLen;
    }

    return ret;
}

void main()
{
    char* str = "JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DEC"; //要分割的字串

    char* strCpy; //複製的字串指標
    char** split; //分割出來的子字串陣列
    int num; //分割出來的子字串數量
    int i;

    strCpy = (char *)malloc( strlen( str ) * sizeof( *strCpy ) ); //配置記憶體空間,來複製str字串
    strcpy( strCpy, str ); //複製字串str至strCpy

    split = str_split( strCpy, ',', &num );
    //呼叫str_split函式,將strCpy字串以逗點分割,傳出分割好的子字串陣列

    if ( split == NULL ) //如果字子字串陣列為空值(NULL)
    {       
        cout << "字串分割傳回空值" ;
    }
    else
    {
        cout << num << "個結果:" << endl;

        for ( i = 0; i < num; i++ )
        {
            cout <<  split[i] << endl; // 輸出每一個子字串陣列的字串
        }
    }
    system("pause");
}

指標與二維陣列

C++的檔案讀寫

((參考課本第16章))

我們所認知的檔案是放在儲存媒體(硬碟、網路硬碟、磁帶等)上的,可以透過檔案總管對檔案進行open、close、copy、delete等動作;實際上,在我們的作業系統中,“檔案“基本上不單純,檔案這個名詞被抽象化可代表作業系統中所有的裝置,如果是在可讀寫的儲存媒體上,那麼這個檔案是可讀寫的,若是在僅供讀取的裝置上(光碟機),那麼這個檔案就只能被讀取。因此,程式要存取裝置,只要對該裝置的代表檔案進行開啟,對該裝置檔案進行讀或寫的動作,這樣的做法,將裝置的存取動作簡單化成為對檔案的讀寫,不必特別針對每個裝置的特性來處理輸入或輸出的動作。

因此,在C++中,有所謂的輸出輸入的資料流(istream, ostream類別),從這2個類別再向下衍生出2個檔案的輸入輸出類別:ifstream與ofstream。 而fstream就同時衍生自ifstream與ofstrean,同時具備對檔案的讀寫能力。底下是幾個操作檔案需注意的事項:

  • 檔案在操作上一定是先通過open()手段,指定一個欲開啟的檔案,在進行開檔的時候,可以指定要對檔案的操作型式,像是讀取、寫入、附加資料等。
  • 檔案的讀取方式:1.讀取一定數量的字元到一個資料緩衝區(通常是一個字元陣列),2.讀取單一個字元,3,讀取文字檔案中的一整行到一個資料緩衝區。
  • 一個檔案打開後,檔案指標指向檔頭,讀取或寫資料時,此指標會逐一字元往後,在讀檔案時,若讀出來的字元為"EOF"(End Of File),即表示到達檔案結尾,此時讀取檔案動作就應該停止。
  • 檔案打開後,若是有寫資料的動作,可以下flush(方法)將在資料緩衝區的資料寫回檔案,以確保所有的資料都正確地存入檔案。
  • 程式最終,要將打開的檔案以close()方法進行關檔的動作。

檔案的寫入方式最簡單,以前使用過的輸出cout本身就是一個檔案,當我們開啟一個檔案要進行寫入動作的時候,只需要將檔案的物件參考,比方說是file,替換掉cout即可,例如:

cout << "This is a test!\n";

換成:

file << "This is a test!\n";

這樣就可以將字串"This is a test!\n"寫入檔案。

課堂練習

將下列文字放入一個文字檔,再寫一程式將文字檔內容:

  1. 秀在螢幕上
  2. 寫入另一個檔案中

注意:寫完請舉手要求老師或小老師檢查。


問題:印出一數N的質因數 做法: 判斷2~(N-1)是否為N的因數,並且是否為質數

(i迴圈開始)
1.使用一迴圈敘述,使用迭代變數i,下限值為2,上限值為N-1,i若能整除N,則
  (j迴圈開始)
  1.1 使用一個布林變數isPrime,初值為true(此布林變數表示N是否為質數,程式一開始先認定N為質數)
  1.2 使用一迴圈敘述,使用迭代變數j,下限值為2,上限值為i-1,若j可整除i,設定isPrime為false,跳出j迴圈
  (j迴圈結束)
  1.3 若isPrime為tru則輸出j
(i迴圈結束)

2.結束

程式範例解答

#include <iostream>
using namespace std;
void main(void){
  int n;
  cout<<"請輸入";
  cin>>n;
  for(int i=2;i<= n-1;i++ ){
    if(n%i==0){
      bool Isprime=true;
      for(int j=2;j<=i-1&& Isprime;j++){
         if(i%j==0){
           Isprime=false;
           break;
        }
      }
      if (Isprime){
        cout<<i<<endl;
      }
    }
  }
  system("pause");
}

成績檔案讀取並分割欄位範例

有一成績檔score.txt,內容如下:

7525001,83,90,65
7525002,75,63,65
7525003,79,95,50
7525004,95,95,91
7525005,88,60,100
7525006,78,87,55
7525007,86,76,82
7525008,82,60,85
7525009,76,60,70
7525010,66,57,47
7525011,75,75,55
7525012,71,45,68
7525013,89,82,85
7525014,41,35,46
7525015,63,42,51
7525016,65,42,55
7525017,64,35,58
7525018,63,55,42
7525019,32,21,65
7525020,81,55,86
7525021,70,48,65
7525022,64,60,40
7525023,58,65,20
7525024,77,75,60
7525025,71,73,47
7525026,72,60,50
7525027,51,33,27
7525028,72,70,52
7525029,70,90,32
7525030,62,65,30
7525031,59,60,27
7525032,84,80,75
7525033,72,60,55
7525034,69,46,53
7525035,97,90,86
7525036,50,45,17
7525037,58,35,43

底下程式示範如何開啟score.txt,讀入每一行,並將每一行的欄位分開。

#include <iostream>
#include <fstream> 
using namespace std;

//字串分割函式,不需要改,直接使用,使用方式請看主程式main
char** str_split( char* str, char delim, int* numSplits ) 
{
    char** ret;
    int retLen;
    char* c;

    if ( ( str == NULL ) ||
        ( delim == '\0' ) )
    {
        /* Either of those will cause problems */
        ret = NULL;
        retLen = -1;
    }
    else
    {
        retLen = 0;
        c = str;

        /* Pre-calculate number of elements */
        do
        {
            if ( *c == delim )
            {
                retLen++;
            }

            c++;
        } while ( *c != '\0' );

        ret = (char **)malloc( ( retLen + 1 ) * sizeof( *ret ) );
        ret[retLen] = NULL;

        c = str;
        retLen = 1;
        ret[0] = str;

        do
        {
            if ( *c == delim )
            {
                ret[retLen++] = &c[1];
                *c = '\0';
            }

            c++;
        } while ( *c != '\0' );
    }

    if ( numSplits != NULL )
    {
        *numSplits = retLen;
    }

    return ret;
}

 
void main()
{
    char* strCpy; //複製的字串指標
    char** split; //分割出來的子字串陣列
    int num; //分割出來的子字串數量
    int i;
	
    ifstream file;       // 建立檔案輸出、輸入物件 
    char str[80];    // 每一行文字長度 
    file.open("c:\\temp\\score.txt",ios::in);
    while (! file.eof())  
    {  // 每次讀取一行至 buffer 陣列 
        file.getline(str,sizeof(str)); 

	split = str_split( str, ',', &num );
        //呼叫str_split函式,將str字串以逗點分割,傳出分割好的子字串陣列
	if ( split == NULL ) //如果字子字串陣列為空值(NULL)
	{       
	  cout << "字串分割傳回空值" ;
	}
	else
	{			
	  for ( i = 0; i < num; i++ )
  	  {
		cout <<  split[i] << "     "; // 輸出每一個子字串陣列的字串
  	  }
	  cout << endl;
	}
	  free(split);//釋放split所佔的記憶體空間
	}
	file.close();
	system("pause");
}

程式結果如下:

7525001     83     90     65
7525002     75     63     65
7525003     79     95     50
7525004     95     95     91
7525005     88     60     100
7525006     78     87     55
7525007     86     76     82
7525008     82     60     85
7525009     76     60     70
7525010     66     57     47
7525011     75     75     55
7525012     71     45     68
7525013     89     82     85
7525014     41     35     46
7525015     63     42     51
7525016     65     42     55
7525017     64     35     58
7525018     63     55     42
7525019     32     21     65
7525020     81     55     86
7525021     70     48     65
7525022     64     60     40
7525023     58     65     20
7525024     77     75     60
7525025     71     73     47
7525026     72     60     50
7525027     51     33     27
7525028     72     70     52
7525029     70     90     32
7525030     62     65     30
7525031     59     60     27
7525032     84     80     75
7525033     72     60     55
7525034     69     46     53
7525035     97     90     86
7525036     50     45     17
7525037     58     35     43
請按任意鍵繼續 . . .

課堂練習作業

修改上面的程式,輸出底下資料:

註:參考使用cout物件的格式化函式,輸出整齊的表格形式的輸出。

  • 欄位寬設定- cout.width(n); setw( );
  • 精確度設定-cout.precision( ); setprecision( )
  • 指定多餘格數字元-cout.fill( ); setfill( )
  • 小數位數設定-cout.setf( )
學號		國文		數學		英語		總分
7525001		83		90		65		238
7525002		75		63		65		203
7525003		79		95		50		224
7525004		95		95		91		281
7525005		88		60		100		248
7525006		78		87		55		220
7525007		86		76		82		244
7525008		82		60		85		227
7525009		76		60		70		206
7525010		66		57		47		170
7525011		75		75		55		205
7525012		71		45		68		184
7525013		89		82		85		256
7525014		41		35		46		122
7525015		63		42		51		156
7525016		65		42		55		162
7525017		64		35		58		157
7525018		63		55		42		160
7525019		32		21		65		118
7525020		81		55		86		222
7525021		70		48		65		183
7525022		64		60		40		164
7525023		58		65		20		143
7525024		77		75		60		212
7525025		71		73		47		191
7525026		72		60		50		182
7525027		51		33		27		111
7525028		72		70		52		194
7525029		70		90		32		192
7525030		62		65		30		157
7525031		59		60		27		146
7525032		84		80		75		239
7525033		72		60		55		187
7525034		69		46		53		168
7525035		97		90		86		273
7525036		50		45		17		112
7525037		58		35		43		136
班級平均       70.49	     61.76           56.76		189

20130509高手的作業-1

1.將上列成績檔資料讀入,並將每一筆資料存入score結構中:

typedef struct{
	char ID[20]; //學號
	float s1; //國文成績
	float s2; //英文成績
	float s3; //數學成縝
} score;

2.將所有學生的成績資料放入一個scores的score陣列中。

score scores[100];

3.走訪學生的成績資料集合陣列,一一印出如之前輸出的成績形式。
4.找出前三名的學生。

20130509高手的作業-2

將上面的成績表格排序後印出,並印出每個人的名次。

讀檔並擷取當中的整數

由檔案Midtest.txt讀入資料,檔案資料為字串與整數混合,將檔案中的整數讀取出來,計算這些整數的個數與總和,並將結果存入另一個檔案MidTestResult.txt中。 Midtest.txt資料檔內容如下:

7525001aaaaa83a90a657525002a75a63a657525003a7

9a95a507525004a95a95a917525005a88a60a10075250

06a78a87a557525007a86a76a827525008a82a60a8575

25009a76a60a707525010a66a57a477525011a75a75a5

5
7525012a71a45a68
7525013a89aaaaa82a85
7525014a41a35a46
7525015a63a42a51
7525016a65a42a55
7525017a64a35a58
7525018a63a55a42
7525019a32a21a65
7525020a81a55a86
7525021a70a48a65
7525022a64a60a40
7525023a58a65a20
7525024a77a75a60
7525025a71a73a47
7525026a72a60a50
7525027a51a33a27
7525028a72a70a52
7525029a70a90a32
7525030a62a65a30
7525031a59a60a27
7525032a84a80a75
7525033a72a60a55
7525034a69a46a53
7525035a97a90a86
7525036a50a45a17
7525037a58a35a43

參考示範(只抓出上面資料檔中的整數值,個數與總和程式碼請自行加入)

#include <iostream>
#include <fstream>
using namespace std;

void main(void){

    ifstream file;       // 建立檔案輸出、輸入物件 
    char ch;
    int num=0;
    file.open("c:\\temp\\MidTest.txt",ios::in);
    if (!file){
      cout << "檔案開啟錯誤\n";
    } else{
      do{
	file.get(ch);
	if (ch >= '0' && ch <= '9')	{//若字元為'0'~'9'的話
	  num = num *10 + (ch-'0');
	  file.get(ch); //讀下一個字元
	  while (ch >= '0' && ch <= '9'){
	    num = num *10 + (ch-'0');
	    file.get(ch); //讀下一個字元
	    if (file.eof()) break;
	  }
	  cout << num << endl;
	  num = 0;
	}
     } while(!file.eof());
     file.close();
   }
   system("pause");
}

結構

物件導向程式設計基礎

物件與類別

方法多載

繼承與覆寫

程式觀念考題破解中心

程式觀念考題
基本程式語言 決策程式語法 迴圈/重複敘述 副程式呼叫與遞迴 物件導向-類別與物件 其他

01 . 02 . 03 . 04 . 05
06 . 07 . 08 . 09 . 10
11 . 12 . 13 . 14 . 15

01 . 02 . 03 . 04 . 05
06 . 07 . 08 . 09 . 10
11 . 12 . 13 . 14 . 15

01 . 02 . 03 . 04 . 05
06 . 07 . 08 . 09 . 10
11 . 12 . 13 . 14 . 15

01 . 02 . 03 . 04 . 05
06 . 07 . 08 . 09 . 10
11 . 12 . 13 . 14 . 15

01 . 02 . 03 . 04 . 05
06 . 07 . 08 . 09 . 10
11 . 12 . 13 . 14 . 15

01 . 02 . 03 . 04 . 05
06 . 07 . 08 . 09 . 10
11 . 12 . 13 . 14 . 15