演算法小社語法II

Lecturer: Yeedrag

今日內容:

  • For & While 迴圈
  • Array 陣列
  • String 字串

迴圈

loops

好麻煩喔.........

#include<iostream>
using namespace std;
int main(){
    cout<<"I MUST NOT WRITE ALL OVER THE WALLS"<<endl;
    cout<<"I MUST NOT WRITE ALL OVER THE WALLS"<<endl;
    cout<<"I MUST NOT WRITE ALL OVER THE WALLS"<<endl;
    cout<<"I MUST NOT WRITE ALL OVER THE WALLS"<<endl;
    cout<<"I MUST NOT WRITE ALL OVER THE WALLS"<<endl;
    cout<<"I MUST NOT WRITE ALL OVER THE WALLS"<<endl;
    cout<<"I MUST NOT WRITE ALL OVER THE WALLS"<<endl;
    cout<<"I MUST NOT WRITE ALL OVER THE WALLS"<<endl;
    cout<<"I MUST NOT WRITE ALL OVER THE WALLS"<<endl;
    cout<<"I MUST NOT WRITE ALL OVER THE WALLS"<<endl;
    cout<<"I MUST NOT WRITE ALL OVER THE WALLS"<<endl;
    cout<<"I MUST NOT WRITE ALL OVER THE WALLS"<<endl;
    cout<<"I MUST NOT WRITE ALL OVER THE WALLS"<<endl;
    cout<<"I MUST NOT WRITE ALL OVER THE WALLS"<<endl;
    cout<<"I MUST NOT WRITE ALL OVER THE WALLS"<<endl;
    cout<<"I MUST NOT WRITE ALL OVER THE WALLS"<<endl;
    //.................................
}

缺點?

  • 萬一抄寫的次數是上千次甚至上萬次?
  • 要抄的東西萬一要改要改好幾萬個?
  • 一直複製貼上,手會很酸?
  • 東西的可讀性很低?
  • 霸子的手會很酸

Introducing.....

LOOPS!

 

#include<iostream>
using namespace std;
int main(){
    for(int i=1;i<=500;i++){
        cout<<"I MUST NOT WRITE ALL OVER THE WALLS"<<endl;
    }
}
#include<iostream>
using namespace std;
int main(){
    int i = 1;
    while(i<=500){
        cout<<"I MUST NOT WRITE ALL OVER THE WALLS"<<endl;
        i++;
    }
}
while(/*condition*/){
/*do something*/
}
當(/*條件為真*/){
/*執行括號內程式*/
}

While-Loops

*條件裡的其實傳出來的是布林值喔!

飯粒一

印出1~10的數字

#include<iostream>
using namespace std;
int main(){
    int i = 1;
    while(i<=10){
        cout<<i<<endl;
        i++;
    }
}

Output:

Code:

飯粒二

印出1~100的偶數和(with while loop)

#include<iostream>
using namespace std;
int main(){
    int i = 2;
    int sum = 0;
    while(i<=100){
        sum += i;
        i += 2;
    }
    cout<<sum<<endl;
}

Output: 2550

Code:

無限的迴圈?

#include<iostream>
using namespace std;
int main(){
    while(true){
        cout<<"Infinite Power"<<endl;
    }
}
#include<iostream>
using namespace std;
int main(){
    while(1){
        cout<<"Never gonna give you up"<<endl;
    }
}
#include<iostream>
using namespace std;
int main(){
    int kirito = 48763;
    while(kirito>1){
        cout<<"スターバースト・ストリーム!"<<endl;
        kirito += 1016;
    }
}

離開迴圈

while(/*condition 1*/){
    if(/*condition 2*/){
        break;
    }
}

如果第二個條件為True的話,跳離整個迴圈

當(/*第一條件為真*/){
    如果(/*第二條件為真*/){
        跳離迴圈;
    }
}

飯粒(Break)

文字猜數字遊戲

#include<iostream>
using namespace std;
int main(){
    int number = 64;
    int guess;
    while(true){
        cout<<"Enter a number:"<<endl;
        cin>>guess;
        if(guess==number){
            //如果猜的數字跟答案一樣的話
            cout<<"You are correct!"<<endl;
            break;//脫離整個迴圈
        } else {
            cout<<"Incorrect!"<<endl;
        }
    }
}

繼續迴圈

while(/*condition 1*/){
	/*body 1*/
    if(/*condition 2*/){
        continue;
    }
    /* body 2*/
}

當第二個條件為True的話,

忽略body2直接跳回去繼續迴圈

當(/*第一條件為真*/){
   /*第一段程式*/
    如果(/*第二條件為真*/){
        繼續迴圈(從頭);
    }
    /*第二段程式*/
}

飯粒(Continue)

#include<iostream>
using namespace std;
int main(){
    int a,b;
    while(true){
        cin>>a>>b;
        if(b==0){
            //除數不可為0
            continue;
        }
        cout<<"a/b = "<<a/b<<endl;
    }
}

除法計算器

Do-While loops

先做了再說的精神

do {
  /*body*/
} while (/*condition*/);

body會先執行,再來判斷條件

就算條件不符合,body至少會被執行一次

要分號!

飯粒(Do-While)

文字猜數字again!

#include<iostream>
using namespace std;
int main(){
    int number = 64;
    int guess;
    do{
        cout<<"Enter a number:"<<endl;
        cin>>guess;
    }while(guess!=number);
    cout<<"You are correct!"<<endl;
}

實作Time!

小龍非常討厭4這個數字,討厭到他連4的倍數的數字

都不想要看到,但是他又很想要知道從1加到1000會是多

少,於是他決定如果遇到4的倍數的數字就跳過他,請問

你有辦法幫助小龍得到在1000以內,4的倍數

以外的數字總和嗎?

 

 

解答點我

#include<iostream>
using namespace std;
int main(){
    int sum = 0;
    int i = 1;
    while(i<=1000){
        if(i%4==0){
            i += 1;
            continue;
        }
        sum += i;
        i += 1;
    }
    cout<<sum<<endl;
}

Ans = 375000

小龍雖然討厭4的倍數,但他更討厭數字\(n\),於是他決定放下

跟4的仇,毅然決定一樣想從1加到1000,但是當遇到\(n\)時,

  小龍會因為看到\(n\)太過憤怒而決定不想繼續計算了。

請你輸入一個數字代表\(n\),輸出小龍在暴怒前

最後總和的值是多少?

(\(n\)不一定小於等於1000喔)

答案點我

#include<iostream>
using namespace std;
int main(){
    int sum = 0;
    int i = 1;
    int n;
    cin>>n;
    while(i<=1000){
        if(i==n){
            break;
        }
        sum += i;
        i += 1;
    }
    cout<<sum<<endl;
}

\(n\) = 530時,ans = 140185

\(n\) = 1001時,ans = 500500

\(n\) = 486時,ans = 117855

\(n\) = 10時,ans = 45

For-Loops

for(/*Initialization*/;/*Condition*/;/*Adjustment*/){
    /*Code*/
}

順序:

初始化(只會在進入迴圈第一次時跑)

判斷條件是否符合

執行迴圈裡的程式

對值進行調整

int main(){
    for(int i=1;i<=100;i+=1){
        cout<<i<<endl;
    }
}
int main(){
    int i = 1;
    while(i<=100){
        cout<<i<<endl;
        i += 1;
    }
}

省略變數宣告(改成使用迴圈時一起宣告)(只能在裡面使用此變數!)

省略變數值的更動

 

 

再度同樣ㄉ飯粒

印出1~100的偶數和(with for loop)

#include<iostream>
using namespace std;
int main(){
    int i = 2;
    int sum = 0;
    while(i<=100){
        sum += i;
        i += 2;
    }
    cout<<sum<<endl;
}
#include<iostream>
using namespace std;
int main(){
    int sum = 0;
    for(int i=2;i<=100;i+=2){
        sum += i;
    }
    cout<<i<<endl;
}

巢狀迴圈

多倍迴圈,多倍滿足!

#include<iostream>
using namespace std;
int main(){
    for(int i=1;i<=9;i++){
        for(int j=1;j<=9;j++){
            cout<<i<<" * "<<j<<" = "<<i*j<<" ";
        }
        cout<<endl;
    }
}

Output:

btw while也可以巢狀ㄛ

for也可以用break & continue .w.

#include<iostream>
using namespace std;
int main(){
    for(int i=1;i<=9;i++){
        for(int j=1;j<=9;j++){
            if(i+j!=10){
                continue;
            }
            cout<<i<<" + "<<j<<" = 10"<<endl;
        }
    }
}
#include<iostream>
using namespace std;
int main(){
    int i = 1;
    while(i<=9){
        int j = 1;
        while(j<=9){
            cout<<i<<" * "<<j<<" = "<<i*j<<" ";
            j++;
        }
        i++;
        cout<<endl;
    }
}

實作Time!

馬力歐經過前面關卡的種種挑戰後,終於要抵達旗桿了,

但沒想到,旗桿前的樓梯竟然被邪惡的庫巴拆掉了!請你

想辦法幫助馬力歐蓋一個高度為\(n\)的樓梯,讓他能順利

得到One up! ( * 符號為蓋樓梯的磚頭)

 

範例: \(n\) = 5

解答 

#include<iostream>
using namespace std;
int main(){
    int n;
    cin>>n;
    for(int i=n-1;i>=0;i--){
        for(int j=0;j<i;j++){
            cout<<" ";
        }
        for(int j=0;j<n-i;j++){
            cout<<"*";
        }
        cout<<endl;
    }
}

每行空白數量+磚頭的數量等於\(n\)

故題目可以看成

輸出一個由空白組成的倒三角

和磚頭組成的三角!

陣列

Array

存值好幫手!

#include<iostream>
using namespace std;
int main(){
    string student_1;
    string student_2;
    string student_3;
    string student_4;
    cin>>student_1>>student_2>>student_3>>student_4;
    /*..................................*/
}

100個學生? 1000個學生?

#include<iostream>
using namespace std;
int main(){
    string Class[32];
    for(int i=1;i<=31;i++){
        cin>>Class[i];
    }
}

一個陣列解決問題!

一維陣列宣告

 

int Array[10000];
/*(陣列型態) 陣列名字[陣列大小]*/
int Array[5] = {1,2,3,4,5};
/*a[0]=1,a[1]=2.....*/

常見初始化方式

memset(陣列、值、陣列大小) 

跟bit有關,有很多限制,除了0不要使用

fill(陣列頭、陣列尾、值)

迴圈

{0} ,除了0不要使用,用變數當大小時也不行

int main(){   
    int arr1[100];
    memset(arr1,0,sizeof(arr1));
    int arr2[100];
    fill(arr2,arr2+100,0);
    int arr3[100];
    for(int i=0;i<100;i++){
        arr3[i] = 0;
    }
    int arr4[100] = {0};
}

陣列宣告假設大小\(n\)的話,

Index是從\(0\)到\(n-1\)喔!

從零原因? 指標!(日後會談)

陣列的應用

*宣告:
int array[n];
memset(array,0,n);
1.指派:
/*陣列名稱[第幾格] = 數值*/
for(int i=0;i<n;i++){
    array[i] = i;
}
2.輸入:
/*cin>>陣列名稱[第幾格]*/
for(int i=0;i<n;i++){
    cin>>array[i];
}
    
3.輸出:
/*cout<<陣列名稱[第幾格]*/
for(int i=0;i<n;i++){
    cout<<array[i];
}

多維的陣列?

Index一樣從0開始!

宣告二維陣列

int a[3][4];
/*(陣列型態)陣列名字[陣列列數][陣列行數]*/

二維陣列的應用

宣告: 
int array[n][m] = {0};//{0}可以把陣列裡所有格子都初始化!

1.指派:
//陣列名稱[第幾行][第幾列] = 數值
for(int i=0;i<n;i++){
	for(int j=0;j<m;j++){
    	array[i][j] = (value);
    }
}
2.輸入:
//cin>>陣列名稱[第幾行][第幾列]
for(int i=0;i<n;i++){
	for(int j=0;j<m;j++){
    	cin>>array[i][j];
    }
}
3.輸出:
//cout<<陣列名稱[第幾行][第幾列]
for(int i=0;i<n;i++){
	for(int j=0;j<m;j++){
    	cout<<array[i][j];
    }
}

實作Time!

野比大雄最喜歡考零分了! 每次看到自己沒有成功考到零分就失望無比,於是他決定將自己超過0分的考卷全部改成0分,但大雄實在太厲害了,甚至可以考到負分!所以他不希望負分的成績被更改。此外,他還想要惡作劇一下,把所有的成績順序顛倒過來,你能夠幫助大雄完成他的目標嗎?

輸入\(n\)個數字代表大雄成績,請輸出指定答案。

範例輸入:

3 (\(n\)值)

-15

33

90

 

範例輸出:

0

0

-15

範例說明:

 -15 -> -15(無須更改)

33 -> 0

90 -> 0

最後順序顛倒即可

 

題目來源:NEOJ294

實作Time!

給你一個地雷盤面,請問每格周圍有多少地雷?

 

範例輸入:

3 3

0 0 1

1 0 1

1 0 1

 

範例輸出:

1 3 1

1 5 2

1 4 1

題目來源:NEOJ214

第1行有兩個正整數\(n\)和\(m\),代表著盤面的長和寬

第2行到第\(n+1\)行,每行會有\(m\)個數字,

0表示沒有地雷,1表示有地雷。

\( (1\le n,m \le 100)\)


解答1

 

#include<iostream>
using namespace std;
int main(){
    int n;
    cin>>n;
    int arr[n];
    for(int i=0;i<n;i++){
    	//輸入
        cin>>arr[i];
        if(arr[i]>0){
        	//如果數字為正的將他改成0
            arr[i] = 0;
        }
    }
    for(int i=n-1;i>=0;i--){
    	//倒著輸出
        cout<<arr[i]<<endl;
    }
}

解答2

 

#include<iostream>
using namespace std;
int main(){
    int h,w;
    cin>>h>>w;
    int m[105][105] = {0};
    int ans[105][105] = {0};
    //陣列開比要求多5~10可以防止一些意外錯誤
    for(int i=1;i<=h;i++){
        for(int j=1;j<=w;j++){
            cin>>m[i][j];
        }
    }
    for(int i=1;i<=h;i++){
        for(int j=1;j<=w;j++){
            ans[i][j]=m[i-1][j-1]+m[i-1][j]+m[i-1][j+1];
            ans[i][j]+=m[i][j-1]+m[i][j+1]+m[i+1][j]+m[i+1][j-1]+m[i+1][j+1];
            //加上周圍8格;
        }
    }
    for(int i=1;i<=h;i++){
        for(int j=1;j<=w-1;j++){
            cout<<ans[i][j]<<" ";
        }
        cout<<ans[i][w]<<endl;
    }
}
 0  0  0  0  0
 0  0  0  1  0
 0  1  0  1  0
 0  1  0  1  0
 0  0  0  0  0

String

字串

友情提示:本章節都需要#include<string>喔!

甚麼是String?

聽聽電神的想法吧!

快速補充時間

Vector是甚麼?

甚麼是char?

 

除了String,其實還有C-string(C-style String)喔,但沒有string好用今天就不提了

owo

字元型態,背後其實是數字(Ascii),組成字串的基本單位。

可以伸縮的動態陣列,日後stl會教。

字串就是可以

伸縮的字元陣列!

string s = "Geeks"

Ascii的跳脫字元,String後面都會

有一個,可以暫時不用理會

字串的宣告

#include<iostream>
using namespace std;
int main(){
    string s;
    cin>>s;// getline(cin,s)
    string str = "I am weak...";// or string str("I am weak...")
    string str2 = str; //str2 = "I am weak..."
    //註: getline遇到空格不會斷掉 會讀整行!
}

1. cin(getline)進一個字串

2.使用"="賦值string

3.使用string的建構子 

讀寫字串字元

#include<iostream>
using namespace std;
int main(){
    string str = "abcde";
    str[3] = '7';//要改字元!
    cout<<str<<endl;
    cout<<str[2]<<endl;
}

Output:

 

String常用ㄉ東西們

.length()

.size()

.find()

.insert()

.erase()

比大小

.stoi()/.stoll() (轉數字)

.......

String長度

#include<iostream>
using namespace std;
int main(){
    string s = "lemonsooooodian";
    cout<<s.size()<<endl;
    cout<<s.length()<<endl;
}

使用.length() or .size()

回傳size_t(unsigned int)

Output:

String連接

#include<iostream>
using namespace std;
int main(){
    string s1 = "abcd";
    string s2 = "1234";
    string s3 = s1 + s2;
    cout<<s3<<endl;
}

Output:

直接用+連接,也有+=

String比大小

#include<iostream>
using namespace std;
int main(){
    string s1 = "abcd";
    string s2 = "1234";
    if(s1>s2){
        cout<<"s1 > s2 la"<<endl;
    } else if(s1<s2){
        cout<<"s1 < s2 la"<<endl;
    } else {
        cout<<"the same la"<<endl;
    }
}

Output:

直接用>、<、==、!=.....

照字典序比較

*字典序:指按照字在字典出現的順序進行排列的方法

String找子字串

.find(想找的字串,起點)

回傳第一個出現子字串的起始位置

沒有找到回傳string::npos

#include<iostream>
using namespace std;
int main(){
    string str = "Why is math so hard la ;-;";
    cout<<str.find("hard")<<endl;//15
    string str2 = "I am the bone of my sword.";
    if(str.find("Archer")==string::npos){
        cout<<"No Archer in this string ;-;";
    } else {
        cout<<"Real Archer don't use bow"<<endl;
    }
    //No Archer in this string ;-;
}

String插入/刪除

使用.insert(位置,想插入的字串)

#include<iostream>
using namespace std;
int main(){
    string str = "Wow is so diannnn";
    cout<<str.insert(4,"Yungyao ")<<endl;
    //Output: Wow Yungyao is so diannnn
}

使用.erase(起點,長度)

#include<iostream>
using namespace std;
int main(){
    string str = "ab1234cd";
    cout<<str.erase(2,4)<<endl;
    //Output: abcd
}

上述跟Index有關

的都是0開始喔!!!!

(詳情往回看陣列)

Stringの實作 Time!

 

Yeedrag很討厭別人說話的時候講到電("dian"),因為他本人太弱了很忌妒別人很強,決定暗自把別人所有講的電("dian")都改成弱("weak"),你能夠幫Yeedrag做到這件事嗎?

輸入一個字串 \(s\),請將裡面所有的"dian"改成"weak"。

btw要用getline()才能完整讀到整行喔喔喔

範例輸入: Yeediandrag is so dian orz

範例輸出: Yeeweakdrag is so weak orz

解答owo

#include<iostream>
using namespace std;
int main(){
    string str;
    getline(cin,str);
    while(str.find("dian")!=string::npos){
        int pos = str.find("dian");//找到dian的位置
        str.erase(pos,4);//先刪除掉 dian長度為4
        str.insert(pos,"weak");//插入進去weak
    }
    cout<<str<<endl;
}

Python毒瘤解btw ><

 

題單owo

簡單題:

題單owo

普通題:

題單owo

困難題:

大家嘎油!!!

送上電神的勵志名言

語法2

By yeedrag

語法2

  • 1,034