owned this note
owned this note
Published
Linked with GitHub
# C++基礎語法
`第5週社課`
部分內容可以參考新竹實驗中學的講義:
https://hackmd.io/@CLKO/B18yT_i5Z?type=view
## 目錄
* <a href="##輸入/輸出/變數" style="color: black; ">輸入/輸出/變數</a>
* <a href="##運算子" style="color: black; ">運算子</a>
* <a href="##邏輯判斷式" style="color: black; ">邏輯判斷式(if/else)</a>
* <a href="##迴圈" style="color: black; ">迴圈(for/while)</a>
* <a href="##陣列" style="color: black; ">陣列</a>
* <a href="##字串處理" style="color: black; ">字串處理</a>
## 輸入/輸出/變數
### 補充:輸入直到EOF
```cpp
#include <iostream>
using namespace std;
int main(){
int a;
while(cin >> a){
// do something
}
return 0;
}
```
### 例題
[例1]
> 在一行內輸入多個正整數,請輸出把它們全部加起來的和。
:::spoiler 解答
```cpp
#include <iostream>
using namespace std;
int main(){
int a, sum = 0;
while(cin >> a){
sum += a;
}
cout << sum << endl;
return 0;
}
```
:::
----
## 運算子
### 例題
[例1]
>輸入正整數$a,b$,輸出$a\div b$的商和餘數,用空格隔開並換行。
:::spoiler 解答
```cpp
#include<iostream>
using namespace std;
int main(){
int a,b;
cin >> a >> b;
cout << a/b << " " << a%b << endl;
return 0;
}
```
:::
<br>
[例2]
>輸入整數$a,b,c$,輸出$\frac{a}{b\times c}$的整數部分。
:::spoiler 解答
```cpp
#include<iostream>
using namespace std;
int main(){
int a,b,c;
cin >> a >> b >> c;
cout << a/(b*c) << endl;
return 0;
}
```
:::
<br>
[例3]
>輸入整數$a,b,c$,輸出$\frac{a}{b\times c}$無條件進位到整數位之後的值。(禁用浮點數)
:::spoiler 解答
```cpp
#include<iostream>
using namespace std;
int main(){
int a,b,c;
cin >> a >> b >> c;
cout << (a-1)/(b*c)+1 << endl;
return 0;
}
```
:::
----
## 邏輯判斷式
### 例題
[例1]
> 輸入一個正整數,判斷他是不是$3$的倍數,
若是$3$的倍數,則輸出"Yes"(不包含引號)並換行,
不是則輸出"No"(不包含引號)並換行。
:::spoiler 解答
```cpp
#include <iostream>
using namespace std;
int main(){
int a;
cin >> a;
if(a%3 == 0){
cout << "Yes" << endl;
}else{
cout << "No" << endl;
}
return 0;
}
```
:::
<br>
[例2]
> 在一行內輸入多個正整數,判斷它是屬於以下四種數的哪一種(m是整數)。
$[4m,4m+1,4m+2,4m+3]$
如果它屬於$4m$,就輸出"4m"(不含引號)並換行,
如果它屬於$4m+1$,就輸出"4m+1"(不含引號)並換行,依此類推。
:::spoiler 解答
```cpp
#include <iostream>
using namespace std;
int main(){
int a;
while(cin >> a){
if(a%4 == 0){
cout << "4m" << endl;
}else if(a%4 == 1){
cout << "4m+1" << endl;
}else if(a%4 == 2){
cout << "4m+2" << endl;
}else if(a%4 == 3){
cout << "4m+3" << endl;
}
}
return 0;
}
```
:::
----
## 迴圈
### for 迴圈
#### 補充:雙迴圈技巧
觀察以下程式的輸出:
```cpp
#include<iostream>
using namespace std;
int main(){
int n;
cin >> n;
for(int i = 1; i <= n;i++){
for(int j = 1; j <= n; j++){
cout << "(" << i << "," << j << ") ";
}
cout << endl;
}
return 0;
}
```
```cpp
#include<iostream>
using namespace std;
int main(){
int n;
cin >> n;
for(int i = 1; i <= n;i++){
for(int j = 1; j <= i; j++){
cout << j << " ";
}
cout << endl;
}
return 0;
}
```
#### 例題
[例1]
> 輸入1個$n$ ($n\geq 1$)
請輸出序列[1,3,5,7,.....,2n+1],每個數用空格隔開,最後換行。
:::spoiler 解答
```cpp
#include<iostream>
using namespace std;
int main(){
int n;
cin >> n;
for(int i = 0 ; i <= n ;i++){
cout << 2*i+1 << " ";
}
cout << endl;
return 0;
}
```
:::
<br>
[例2]
> 輸入1個$n$,請依照以下的規律輸出$n$行。
>
$n=1:$
<pre>
*
</pre>
$n=2:$
<pre>
*
**
</pre>
$n=5:$
<pre>
*
**
***
****
*****
</pre>
:::spoiler 解答
```cpp
#include<iostream>
using namespace std;
int main(){
int n;
cin >> n;
for(int i = 1; i <= n;i++){
for(int j = 1; j <= i; j++){
cout << "*";
}
cout << endl;
}
return 0;
}
```
:::
<br>
[例3]
> 輸入1個$n$,請依照以下的規律輸出$n$行。
n=1:
<pre>
*
</pre>
n=2:
<pre>
*
**
</pre>
n=5:
<pre>
*
**
***
****
*****
</pre>
:::spoiler 解答
```cpp
#include<iostream>
using namespace std;
int main(){
int n;
cin >> n;
for(int i = 1; i <= n;i++){
for(int j = 1; j <= n-i; j++){
cout << " ";
}
for(int j = 1; j <= i; j++){
cout << "*";
}
cout << endl;
}
return 0;
}
```
:::
<br>
[例4]
> 輸入1個$n$,請依照以下的規律輸出$n$行(限用2個for迴圈)。
>
$n=1:$
<pre>
*
</pre>
$n=2:$
<pre>
*
**
*
</pre>
$n=5:$
<pre>
*
**
***
****
*****
****
***
**
*
</pre>
:::spoiler 解答
```cpp
#include<iostream>
using namespace std;
int main(){
int n;
cin >> n;
for(int i = 1; i <= n*2-1;i++){
for(int j = 1; j <= n-abs(n-i); j++){
cout << "*";
}
cout << endl;
}
return 0;
}
```
:::
### while 迴圈
<!-- https://www.cmor-faculty.rice.edu/~heinken/latex/symbols.pdf -->
#### 例題
[例1]
> 輸入有多行,對於每行的一個整數$n$,請輸出$2\times n$並換行,當輸入為$0$時停止程式。
:::spoiler 解答
```cpp
#include<iostream>
using namespace std;
int main(){
int n;
while(cin >> n){
if(n == 0) break;
cout << 2*n << endl;
}
return 0;
}
```
:::
<br>
[例2]
> 輸入正整數$a、b$ $(a \geq b)$,輸出$[a-b,a-2b,a-3b...]$直到$a-kb$小於0,
所有的數請以空格間隔,並請在輸出完成後換行。
:::spoiler 解答
```cpp
#include<iostream>
using namespace std;
int main(){
int a,b;
cin >> a >> b;
a = a - b;
while(a >= 0){
cout << a << " ";
a = a - b;
}
cout << endl;
return 0;
}
```
:::
----
## 陣列
### 最大值
輸入一個正整數n,接下來有n個數字,求n個數字的最大值
```cpp
#include<iostream>
using namespace std;
int main(){
int n,a[100005],ans;
cin>>n;
for(int i=0;i<n;i++){
cin>>a[i];
}
ans=-1000000000;
for(int i=0;i<n;i++){
if(a[i]>ans){
ans=a[i];
}
}
cout<<ans<<endl;
return 0;
}
```
STL寫法
```cpp
#include<bits/stdc++.h>
using namespace std;
int main(){
int n,ans;
cin>>n;
vector <int> a(n);
for(int i=0;i<n;i++){
cin>>a[i];
}
ans=*max_element(a.begin(),a.end());
cout<<ans<<endl;
return 0;
}
```
----
### 建表
給予一個陣列,求有幾個不同的數字$(-1000 \leq n \leq 1000)$
```cpp
#include <iostream>
using namespace std;
int main(){
bool na[1005] = {0}, a[1005] = {0};//負數,正數
int n,num[100005],ans;
cin>>n;
for(int i=0;i<n;i++){
cin>>num[i];
}
ans=0;
for(int i=0;i<n;i++){
if(num[i]>=0){//正數
if(a[num[i]]==false){//判斷是否已出現過
ans++;
a[num[i]]=true;//標記已出現過
}
}
else{//負數
if(na[-1*num[i]]==false){//判斷是否已出現過
ans++;
na[-1*num[i]]=true;//標記已出現過
}
}
}
cout<<ans<<endl;
return 0;
}
```
----
給予一個陣列,列出所有任兩個數字總和等於k的對
----
### 判斷質數
列出小於n的所有質數
```cpp
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
int num[100005],numsize=0;;
bool b;
num[0]=2;
numsize++;
for(int i=3;i<=n;i++){
b=true;
for(int j=0;j<numsize;j++){
if((int)sqrt(i)<num[j]){//提前終止條件
break;
}
if(i%num[j]==0){
b=false;
break;
}
}
if(b==true){
num[numsize]=i;
numsize++;
}
}
for(int i=0;i<numsize;i++){
cout<<num[i]<<" ";
}
return 0;
}
```
----
### 質因數分解
對正整數n進行質因數分解
```cpp
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
int num[100005],numsize=0;;
bool b,is_1=false;
if(n==1){
is_1=true;
}
num[0]=2;
numsize++;
for(int i=3;i<=n;i++){
b=true;
for(int j=0;j<numsize;j++){
if((int)sqrt(i)<num[j]){//提前終止條件
break;
}
if(i%num[j]==0){
b=false;
break;
}
}
if(b){
num[numsize]=i;
numsize++;
}
}
int anscount[100005]={0};//計算質數的數量
int i=0;
while(n!=1){
if(n%num[i]==0){
n/=num[i];
anscount[i]++;
}
else{
i++;
}
}
for(int i=0;i<numsize;i++){
if(anscount[i]>0){
cout<<num[i]<<"^"<<anscount[i]<<" * ";;
}
}
if(is_1){
cout<<"1\n";
}
return 0;
}
```
----
### 二進位轉換
將十進位數字轉成二進位
```cpp
#include <iostream>
using namespace std;
int main(){
int n,temp;
cin>>n;
int num[100],numsize=0;
while(n!=1){
if(n==0){//特判
break;
}
temp=n%2;
num[numsize]=temp;
numsize++;
n/=2;
}
cout<<n;
for(int i=numsize-1;i>=0;i--){
cout<<num[i];
}
return 0;
}
```
----
### 二維陣列
陣列可以開到二維以上,不過二維的特別常用
```cpp
int a[10][10];
```
### 初始化
當你想要初始化一個陣列,你有以下這些方法:
(1)直接給值
```cpp
char a[5]{'a','b','c','d','e'};
int b[3][3]{
{1,2,3},
{6,0,4},
{8,7,9},
};
```
如果不知道陣列長度也可以讓程式自己判斷
```cpp
int b[]{1,3,-1,0,111};
```
(2)用for迴圈
```cpp
int a[10000];
for(int i = 0 ; i < 10000 ; i++){
a[i] = i;
}
int b[100][100];
for(int i = 0 ; i < 100 ; i++){
for(int j = 0 ; j < 100 ; j++){
b[i][j] = 1;
}
}
```
(3)memset函數(記得使用cstring標頭檔)
```cpp
char a[100];
memset(a,'s',sizeof(a));
```
這個方法大多用在初始化字串,如果用在整數的陣列除了初始化值為$0,-1$是正常的之外的其他的都會發生錯誤,這是因為char和int所佔的記憶體空間大小不同。
```cpp
int main(){
int a[100],b[100],c[100];
memset(a,0,sizeof(a));
memset(b,-1,sizeof(b));
memset(c,5,sizeof(c));
cout << "a[0] = " << a[0] << endl;
cout << "b[0] = " << b[0] << endl;
cout << "c[0] = " << c[0] << endl;
// 00000101000001010000010100000101
return 0;
}
```
輸出結果:
```
a[0] = 0
b[0] = -1
c[0] = 84215045
```
### 字串
string 可以當作一個char陣列
```cpp
string str = "Hellow, world";
cout << str[0] << endl << str[7] << str[6];
```
輸出結果:
```
H
,
```
也可以用char陣列存一個字串
```cpp
char c[] = "Welcome to KSPGC";
```
### 例題
[例1]
>第一行輸入一個正整數$n$ $(n\leq10000)$,第二行後一行輸入一個長度為$n$的陣列,第三行輸入一個整數$k$ $(0 \leq k<n)$,請輸出索引值為$k$的項並換行。
:::spoiler 解答
```cpp
#include<iostream>
using namespace std;
int main(){
int n,tar;
int a[10005];
cin >> n;
for(int i = 0 ; i < n ; i++){
cin >> a[i];
}
cin >> tar;
cout << a[tar] << endl;
return 0;
}
```
:::
<br>
[例2]
>第一行輸入一正整數$n$ $(n \leq 1000)$,之後的一行輸入$n$個整數$a_1,a_2,\ldots,a_n$,請輸出序列$[a_1,a_1+a_2,\ldots,a_1+a_2+\cdots+a_n]$,每個數用空格隔開,最後換行。
(這叫做前綴和,就是把它前面的數字加在一起)
:::spoiler 解答
```cpp
#inclide<iostream>
using namespace std;
int main(){
int n;
int a[1005];
a[0] = 0;
cin >> n;
for(int i = 1 ; i <= n ; i++){
int num;
cin >> num;
a[i] = a[i-1] + num;
cout << a[i] << " ";
}
cout << endl;
return 0 ;
}
```
:::
<br>
[例3]
> 第一行輸入一個字串$S$,第二行輸入一個字元$c$,
> 請輸出在$S$中,共出現了幾次$c$,最後換行。
:::spoiler 解答
```cpp
#include<iostream>
using namespace std;
int main(){
string S;
cin >> S;
char c;
cin >> c;
int ans = 0;
for(int i = 0; i < S.length(); i++){
if(S[i] == c){
ans++;
}
}
cout << ans << endl;
}
```
:::
----
## 字串處理
### 整行輸入
因為getline函數和cin,cout所使用的輸入輸出方式不太一樣,所以我們要用一些方法避免我們讀到不該讀的東西
例如這題:
>第一行輸入一個數字$n$,第二行輸數一串字串(包含空格),以enter作為字串結尾。請輸出此字串的前$n$個字元所形成的字串。
範例輸入:
```
5
te ach m eFF t
```
錯誤寫法:
```cpp
#include<iostream>
using namespace std;
int main(){
int n;
cin >> n;
string str;
getline(cin,str);
for(int i = 0 ; i < n; i++){
cout << str[i];
}
cout << endl;
}
```
你會發現你輸入5的時候程式就結束了,而且輸出只會給你一個換行。這是因為getline()偵測到了前面cin最後所留下來的enter鍵然後就跑完了,所以你無法再輸入後面給的字串。
(註:用getline()不會殘留enter鍵)
這時候就需要把那個多出來的enter洗掉,可以使用:
(1) **cin.get()**:偵測下個字元,可以用來忽略不要的字元或enter
(2) **cin.ignore()**:跳過直到enter(包含enter)之前的字元
其實這些函數都有參數可以設定,但這裡用不到那麼多,有興趣的可以自己上網找找看。
正確寫法:
```cpp
#include<iostream>
using namespace std;
int main(){
int n;
cin >> n;
string str;
cin.get();//或者用cin.ignore();
getline(cin,str);
for(int i = 0 ; i < n; i++){
cout << str[i];
}
cout << endl;
}
```
輸出:
```
te ac
```
**如果還想練習的可以去zerojudge上找標籤 #板橋高中 #教學題**