# [C語言] APCS 兼 彥超的優秀網頁
###### 語言:C 語言
###### 新同學可以進來 :)
###### 終極目標參加APCS https://apcs.csie.ntnu.edu.tw/
###### 線上編譯器 repl.it
## **1. 標頭檔**
```c
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
#include <string.h>
```
## **2.函式 主函式**
```c
int main(void) //void可省略 意旨"無"的意思
{
return 0;
}
```
## **3.副函式**
傳參考呼叫
```c
#include<stdio.h>
int sumnumber(int a,int b);//函式宣告
int main(void)
{
int a = 0,b = 1,count;
count = sumnumber(a,b);
return 0;
}
int sumnumber(int a,int b)//函式定義
{
int sum = 0;
sum = a + b;
return sum;
}
```
```c
#include<stdio.h>
int sumnumber(int a,int b)//函式宣告+定義
{
int sum = 0;
sum = a + b;
# return sum;
}
int main(void)
{
int a = 0,b = 1,sum;
sum = sumnumber(a,b);
printf("%d",count)
return 0;
}
```
```c
#include<stdio.h>
void sumnumber(int a,int b)//函式宣告+定義
{
int sum = 0;
sum = a + b;
printf(%d,sum);
}
int main(void)
{
int a = 0,b = 1;
sumnumber(a,b);
return 0;
}
```
想想看a是多少?
```c=
#include<stdio.h>
void printstring(int a);//函式定義
int main(void)
{
int a = 0;
printsting(a);
printf("%d",a);
return 0;
}
void printstring(int a);//函式定義
{
a = 10;
}
```
想想看這段程式哪裡有錯,以及最後他會印出什麼?
```c=
#include<stdio.h>
double printstring(int a,double b,int c);//函式定義
int main(void)
{
int i = 0,k = 0;
double j = 0;
j = printstring(i,j,i);
printf("%lf",j);
return 0;
}
double printsting(int a,double b,int c);//函式定義
{
printf("%d%d",a,c);
return b+3;
}
```
傳地址呼叫
如果副函式用陣列來傳遞值
*副函式無法回傳 陣列 字串 函數*
```c
#include<stdio.h>
void printstring(char a[]);//函式宣告
int main(void)
{
char a[100] = {0};
printstring(a);
return 0;
}
void printstring(char a[])//函式定義
{
printf("%s",a);
}
```
```c
如果副函式用陣列來修改值
因為它是開頭記憶體位置,會直接改到記憶體裡面的值
#include<stdio.h>
void writestring(char a[]);//函式宣告
int main(void)
{
char a[10] = {0};
writestring(a);
return 0;
}
void writestring(char a[])//函式定義
{
a[0] = '0';
}
```
## **3.內建副函式**
https://pydoing.blogspot.com/2010/07/c-strcmp.html
strlen()
回傳字串的長度。
```c
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[] = "You may go farther and fare worse.";
printf("%d\n", strlen(s));
return 0;
}
```
strcpy()
需要兩個字串當作參數,然後把第二個參數的字串複製到第一個參數的字串中,然後回傳第一個參數。
```c
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[] = "Well begun is half done.";
char t[25];
strcpy(t, s);
printf("%s\n", t);
return 0;
}
```
strcmp()
需要兩個字串當作參數,比較兩個字串是否相等,相等就回傳 0,第一個字串大於第二個字串回傳正值,反之回傳負值。
```c
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[] = "Hello, world!";
char t[] = "Hello, my friend!";
int test = strcmp(s, t);
if (test == 0) {
printf("All right!\n");
}
else {
if (test > 0) {
printf("%s\n", s);
}
else {
printf("%s\n", t);
}
}
return 0;
}
```
strcat()
需要兩個字串當作參數,然後把第二個參數字串的接到第一個參數的字串後面,然後回傳第一個參數。
```c
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[30] = "to harp on ";
char t[30] = "the same string";
strcat(s, t);
printf("%s\n", s);
return 0;
}
```
strspn()
需要兩個字串當作參數,計算經過幾個字元會在第一個參數的字串遇到不屬於第二個參數字串中的字元。
```c
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[] = "There is no royal road to learning.";
char t[] = "There is no royal road";
printf("%d\n", strspn(s, t));
return 0;
}
```
strchr()
需要一個字串及一個字元當作參數,然後搜尋字元在字串中第一次出現的位置,回傳該位置的指標。
```c
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[] = "Rome was not built in a day.";
char t = 'a';
char *test;
test = strchr(s, t);
printf("%s\n", test);
return 0;
}
```
strstr()
需要兩個字串參數,回傳在第二個參數字串在第一個參數字串首次出現位置的指標。
```c
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[] = "Self-trust is the first secret of success.";
char t[] = "secret";
char *test;
test = strstr(s, t);
printf("%s\n", test);
return 0;
}
```
## **4.基本語法**
輸出
```c
printf("hello world!");`
```
賦值
```c
int a = 0;`
a = a + 3;
```
輸出變數
```c
int a = 0;
printf("印出加總%d\n",a);
```
鍵盤輸入
```c
int a;
double b;
scanf("%d",&a);
scanf("%lf",&b);
printf("%d%.2lf",a,b);
```
## **4.判斷式**
如果 那麼
```c
if( //條件式 )
{
//執行區域
}
```
如果 那麼 否則
```c
if( //條件式 )
{
//執行區域
}
else
{
//if不成立則執行
}
```
如果裡面接如果
```c
if( //條件式 )
{
else if( //if不成立則判斷 )
{
//執行區域
}
}
```
## **5.迴圈**
for迴圈
```c
a++; //a = a+1的意思
int i;
for(i = 0;i < 10;i++)
{
}
```
雙層for迴圈
```c
for(i = 0;i <22 10;i++)
{
for(j = 0;j < 10;j++)
{
}
}
```
while迴圈
```c
while(1)
{
if(a == 2)
{
a = a+2;
continue;
}
else if(a == 4)
{
break;
}
else
{
a++;
}
printf("%d",a);
}
```
do…while迴圈
會先做一次後才判斷
```c
do
{
;
}while(a==0);
```
## **6.陣列**
陣列宣告
`int a[5]; //a[0],a[1],a[2],a[3],a[4]`
初始化
```c
int a[5]={0}; //a[5] = {1,0,1,0,1};
char s[5]={0}; //char a[5]={"a","b","c","d","e"};
char k[5]={0};
```
' ':單引號,專門給字元使用
" ":雙引號,可以給字元與字串使用
```c
scanf("%d",&a[0]);
printf("%d",a[0]);
scanf("%c",&s[0]);
printf("%c",s[0]);
```
```c
scanf("%s",k);
printf("%s",k);
```
k為陣列名稱,也是開頭記憶體位置。因此在儲存時,不用使用"&"取址符號,陣列會依照記憶體空間自動把連續的格子依序算出來。
陣列的輸入最後面會被塞入一個'\0 ',為空白字元,代表字串已到結尾。
## **7.隨機數**
```c=
#include <time.h>
#include <stdlib.h>
srand(time(NULL));
time(NULL);
```
會輸出從格林威治時間 1970年1月1號 0點0分0秒開始到現在的秒數
```c
rand()%100; //區間0~99
rand()%100+1; //區間1~100
//e.g. rand()%10+6 //6~15
//e.g. rand()%23+9 //9~31
//e.g. 區間50~100 //rand() % 51 + 50
//e.g. 區間36~72 //rand() % 37 + 36
```
```c
char a[5][5] = {0};
char b[10][5] = {0};
scanf("%d",&a[0][0]);
scanf("%s",a[1]);
```
## **8.結構**
```c
int id; //學號為整數型
char name[8]; //姓名為字元陣列
float score; //成績為浮點型
```
```c
struct student //名稱為student的結構
{
int id; //學號為整數型
char name[8]; //姓名為字元陣列
float score; //成績為浮點型
};
typedef struct student a;
int main(void)
{
struct student stu1; //宣告1個student變數stu
a stu2;
scanf("%d",&stu.id);
scanf("%s",stu.name);
scanf("%f",&stu.score);
printf("%d,%s,%.1f",stu.id,stu.name,stu.score);
}
```
## **9.一般的主函式**
```c
#include<stdio.h>
int main(void)
{
return 0;
}
```
## **10.變數型態**
`int` integer
`整數` %d
`float` float浮點數` %f`
`double` double雙精準浮點數 `%lf`
`char` character字元 `%c`
`char s[]` striz `%s`
## **11.基本運算符號**
```/``` 除法
```+``` 加法
```%``` 取餘數
```==``` 比較運算
```!=``` 不等於
```||``` 或
```&&``` 且
```\n``` 跳脫字元
```//``` 單行註解
```/* 彥超老師好帥 :O */``` 區域註解 可跨行
## **12.指標**
指標
int a[10]; //a是陣列名稱,是開頭記憶體位址
int *b;
b = malloc( 10 * sizeof(int) );
free(b);
```C
#include <stdio.h>
#include <stdlib.h>
int main()
{
int *a;
int i;
int length = 10;
a = malloc( length * sizeof(int) );
for (i = 0; i < length; ++i) // 使用動態取得的記憶體空間
{
a[i] = i;
printf("%d ", a[i]);
}
free(a); // 釋放記憶體空間
return 0;
}
```
## **13.程式練習**
###### ▣ [選擇] 試題練習:https://user152885.pse.is/NeverGonnaGiveYouUp
###### ▣ [實作] 試題練習:https://apcs.csie.ntnu.edu.tw/wp-content/uploads/2022/10/%E5%AF%A6%E4%BD%9C%E9%A1%8C_%E9%A1%8C%E5%9E%8B%E7%AF%84%E4%BE%8B.pdf
練習一:找一首詩,透過printf把他印出來,過程中善用換行符號
練習二:宣告兩個數字a,b,透過賦值給他們兩個值,最後透過相加再把它印出來
練習三:宣告兩個數字a,b,透過鍵盤輸入得到數值,最後透過輸出把它印出來
練習四:寫一個猜數字遊戲 假設不為正確答案,印出太大或太(需自行設定變數值)
練習五:寫一個判斷奇數偶數的程式 (使用者輸入)
練習六:寫一個判斷BMI的程式(使用者輸入)
練習七:寫一個程式印出1~10000數字間的為7倍數的數值
練習八:印出九九乘法表
[變化題] 同練習七,但使用者可自行決定 數字區間 和為 哪個數字 的倍數
練習九:寫一個程式印出1~10000間的質數
練習十:寫一個程式能讓使用者決定輸入幾個數字,並且連續輸入這些數字再把它們累加起來,最後把總和印出來。
練習十一:印星星,請使用者輸入三角形的大小並印出指定大小。
```
請輸入要印出正三角形的層數? 3
*
***
*****
```
練習十二:印星星,請使用者輸入菱形的大小並印出指定大小。
練習十二點五:使用者輸入數值,檢測0~9分別用了幾個數。```小提示 : 先%10在/10 觀察其數字間關聯)```
練習十三:請用陣列寫法,連續輸入10個整數,最後將它們累加印出
練習十四:輸入長串字串,並計算這個字串的長度
練習十五:輸入長串英文包含大小寫字串,進行反轉;大寫轉小寫;小寫轉大寫;數字以及標點符號則不動。
練習十六:使用亂數函數rand()產生10整數,並印出最大值
練習十七:跟電腦猜拳,並判斷勝負
練習十八:有100位學生隨機產生100筆分數,並放入陣列中。依照輸入的號碼說出學生的分數
練習十九 : 定義五乘五的二維陣列,隨機取數後每五行換行輸出。
練習二十 : 同上題,以轉置矩陣輸出。```請用一個二維陣列完成```
練習二十一 : 請連續輸入多個字串存入陣列,直到使用者輸入-1代表結束。之後再把剛剛的字串一一換行印出 ```-1不用印出```
練習二十二 : 請用一個副函式,請讓使用者輸入一個數值,請印出從頭至對應數費式數列的值
練習二十三 : 請寫出身分證驗證機
參考一:https://math.ymhs.tyc.edu.tw/chenyan/EltiveMath/HomWk/1051/RePt/1051/3%20%E8%BA%AB%E5%88%86%E8%AD%89%E5%AD%97%E8%99%9F.pdf
參考二:https://wisdom-life.in/article/taiwain-id-explanation
練習二十四 : 請用一個副函式,寫一個自動找零的程式
e.g. 1868 : 1張1000元、1張500元、3張100元、1個50元、1個10元、1個5元、3個1元
e.g. 596 : 1張500元、1個50元、4個10元、1個5元、1個1元
練習二十五 : 寫一個5個功能的程式,使用者輸入字串並存入s,依不同功能輸出(輸入-1結束程式):
* 覆寫字串s。
* 算出陣列s的長度。
* 用戶輸入字串k,把字串直接串再原字串後面。
* 用戶輸入一串字串k,比較兩者字串是否相同。
* 用戶輸入一串字串k,檢查k字串是否出現在s字串當中。印出是或否,如是並印出第一個字元出現的位置。
練習二十六:寫一個餐廳訂位系統。每次訂位時間為1小時,訂位資料需要有姓名、電話、日期、時間
* 第一個功能:新增訂位資料
1. 檢查此人是否已經訂位,如果有列出他訂位的時段
2. 如訂位時段已經沒有空位,列出空的時段供使用者選擇
* 第二個功能:變更訂位資料
1. 檢查此人是否已經訂位,沒有就表示查無,不更改資料
2. 修改訂位時段,如訂位時段已經沒有空位,列出空的時間讓使用者選擇
* 第三個功能:取消訂位資料
1. 檢查此人是否已經訂位,沒有就表示查無,不刪除資料
2. 查有此人,就把此人的訂位刪除,之後此時段為可被定位
* 第四個功能:查詢訂位資料
1. 列出當前所有訂位的資料
練習二十七:判斷三角形:

練習二十八:動態配置記憶體大小
* 預設記憶體最小空間為5個整數,每一次使用功能完畢都需檢查記憶體空間,功能如下:
* 第一個功能:新增數值
依序輸入數字並加在陣列的最後面
* 第二個功能:刪除數值
每次刪除陣列最後一筆數字
* 當已用空間剩下一個空間能儲存時,自動變為兩倍空間。
e.g.新增數值完畢,[已用空間/當前空間]為[4/5]
則會將當前空間從5變為10[已用空間/當前空間]為[4/10]
* 反之當刪除時,已用空間少於當前空間一半時,自動刪除一半當前空間。
e.g.刪除數值完畢,[已用空間/當前空間]為[9/20]
則當前空間從20變為10[已用空間/當前空間]為[9/10]
練習二十九:
* 記憶體計算空間程式
* 寫一個程式,利用動態記憶體配置的函式,找出系統目前可用的記憶體空間(以Kbytes為單位)
練習三十:
* 請寫出一個程式來處理並檢查此數字是否為『完美數』,列出前10個
* 請先觀看影片介紹(https://youtu.be/Bt1q1e7NkBc?si=PuJIU_t5DQgSmzOw)
* 前10個完美數為
6(1位)
28(2位)
496(3位)
8128(4位)
33550336(8位)
8589869056(10位)
137438691328(12位)
2305843008139952128(19位)
2658455991569831744654692615953842176(37位)
191561942608236107294793378084303638130997321548169216(54位)
* 影片中有提到很多完美數的規律,包含阿基米德2^(n-1) * (2^n)-1或二進制
* 整理好自己的邏輯,因需要大量計算,可以透過演算法的設計來減省計算時間
## **[番外1] APCS 邏輯題**
------------------------- 題目一 ♪ ------------------
```
執行下列C語言程式後,total值應為多少?
18
15
9
3
```
------------------------- 題目二 ♪ ---------------
```
For迴圈總共會執行幾次?
> []
> []
8
32
64
128
```
------------------------- 題目三 ♪ ---------------
```
f()函式執行後所回傳的值為何?
1023
1024
2047
2048
```
------------------------- 題目四 ♪ ---------------
```
請問程式,執行完後輸出為何?
2417851639229258349412352 7
68921 43
65537 65539
134217728 6
```
------------------------- 題目五 ♪ ---------------
```
```
------------------------- 題目六 ♪ ---------------
```
```
------------------------- 題目七 ♪ ---------------
```
```
------------------------- 題目八 ♪ ---------------
```