1. 程式人生 > 其它 >C++語法入門刷題筆記(三)

C++語法入門刷題筆記(三)

1.scanf()函式

scanf()函式接收輸入資料時,遇以下情況結束一個數據的輸入:

① 遇空格、“回車”、“跳格”鍵。
② 遇寬度結束。
③ 遇非法輸入。

cin遇到空格或者回車也會結束讀取!!!

scanf接收包含空格的字串

#include <stdio.h> 
int main() 
{ 
    char str[80]; 
    scanf("%s",str); 
    printf("%s",str);
    return 0; 
}

輸入:I love you!
輸出:I
原因:scanf遇空格結束讀取。

2.ASCII碼

每個常用字元都對應一個-128~127的數字,二者之間可以相互轉化。

ASCII碼 字元
48 ‘0’
65 ‘A’
97 ‘a’

3.字元陣列

3.1

字串就是字元陣列加上結束符’\0’。沒有’\0’不算字串,只是普通的字元陣列。

可以使用字串來初始化字元陣列,但此時要注意,每個字串結尾會暗含一個’\0’字元,因此字元陣列的長度至少要比字串的長度多1!

這裡第二、三種初始化方式是等價的。

3.2

char s[100];
cin >> s + 1;
cout << s + 1 << endl;
cout << s[1] << endl;
// 輸入:abc
/*
    輸出:
    abc
    a 
*/
// 這樣就可以讓讀取的字串的陣列從1開始
// 使用scanf函式有同樣的效果,scanf("%s",s + 1)

3.3

3.3.1

讀入一行字串(包括空格),可以使用gets函式,但由於它不安全,已經被淘汰。

3.3.2

現在使用fgets函式

char s[100];
fgets(s,100,stdin);

原型 char * fgets(char * s, int n,FILE *stream);

引數:

​ s: 字元型指標,指向儲存讀入資料的緩衝區的地址。

​ n: 從流中讀入n-1個字元

​ stream : 指向讀取的流。

返回值:

  1. ​ 當n<=0 時返回NULL,即空指標。
  2. ​ 當n=1 時,返回空串””。
  3. ​ 如果讀入成功,則返回緩衝區的地址。
  4. ​ 如果讀入錯誤或遇到檔案結尾(EOF),則返回NULL。

3.3.3

在用fgets(..)讀入資料時,先定義一個字元陣列或字元指標,如果定義了字元指標 ,那麼一定要初始化。

​ example:

​ char s[100]; //可以。

​ char *s; //不可以,因為只是聲明瞭一個指標。但並沒有為它分配記憶體緩衝區。

​ 所以,如果要用指標,則 char *s=(char*)malloc(100*sizeof(char)); 為其分配記憶體空間,c++中用char *s=new char [100]; 如果未分配記憶體空間,編譯時不會檢查出問題,但執行時會出現未知錯誤。。

3.3.4

fgets(…)讀入文字行時的兩種情況。

​ 1. 如果n大於一行的字串長度,那麼當讀到字串末尾的換行符時,fgets(..)會返回。並且在s的最後插入字串結束標誌’\0’。 而s緩衝區剩餘的位置不會再填充。

​ example:

​ 123abc

​ fgets(s,10,fp);

​ 此時,讀入七個字元,123abc\n,實際上還有最後的’\0’,所以,strlen(s)=7; 如果要去除末尾的\n,s[strlen(s)-1]=’\0’;便可。

​ 2. 如果n小於等於一行的字串的長度,那麼讀入n-1個字元,此時並沒有讀入\n因為並沒有到行尾 ,同樣在最後會插入’\0’.

​ example:

​ 123abc

​ char s[5];

​ fgets(s,5,fp);

​ 這時讀入4個字元,123a,並沒有換行符,所以strlen(s)=4.

3.4

用getline函式來讀取字串中的空格。(定義在標頭檔案中)

getline 函式如下所示:

getline(cin, inputLine);

其中 cin 是正在讀取的輸入流,而 inputLine 是接收輸入字串的 string 變數的名稱。

注意:第二個引數不能是字元陣列,必須是string變數!!它將繼續讀取,直到它讀取至最大指定的字元數,或直到按下了回車鍵。

string name;
string city;
cout << "Please enter your name: ";
getline(cin, name);
cout << "Enter the city you live in: ";
getline(cin, city);// 上一次使用者輸入的'\n'被去除了,沒有讀入city
cout << "Hello, " << name << endl;
cout << "You live in " << city << endl;

// 輸出如下
Please enter your name: John Doe
Enter the city you live in: Chicago
Hello, John Doe
You live in Chicago

補充:getline()中讀入結束的回車後,結束符不放入快取區,會將讀入的\n直接去除,下一個輸入前,緩衝區為空,並不會因為回車留下\n。而cin的結束後,以及getchar()此類的讀入結束後,按下回車或者使用空格讀入下一個,此時按下的回車或空格會還在快取區,繼續用getline()就會出現前面所提到的情況。

scanf函式並不會清空緩衝區回車!!

// 用scanf過濾空格
char str[30],c;
scanf("%s",s);
scanf("\n%c",&c);

3.5

cin.getline函式。

與 getline 一樣,cin.getline 允許讀取包含空格的字串。它將繼續讀取,直到它讀取至最大指定的字元數,或直到按下了回車鍵。

char s[100];
cin.getline(s,100);// 最多讀取99個字元,最後一個位置放'\0'

3.6

puts函式。(引入)

char name[] = "asaf";
printf("%s\n",name);
puts(name);// 兩者是完全等價的

4.字元陣列常用操作

下面幾個函式需要引入標頭檔案:

#include <string.h> 或者也可以

(1) strlen(str),求字串的長度,注意:不包括最後的’\0’

// 自己實現程式碼
char s[100];
scanf("%s",s);
int len = 0;
for (int i = 0;s[i];i++) len++;// 用s[i]作為判斷條件,因為'\0'代表停止
cout << len << endl;

(2) strcmp(a, b),比較兩個字串的大小,a < b 返回-1,a == b 返回0,a > b返回1。這裡的比較方式是字典序!

(3) strcpy(a, b),將字串b複製給從a開始的字元陣列。

5.acwing772.只出現一次的字元

#include <iostream>
// 巧妙的做法
using namespace std;
int main()
{
    string str;cin >> str;
    int s[300] = {0};
    for (char &c : str) s[c]++;// 遍歷string
    char p = -1;
    for (char &c: str)// 注意這裡還是遍歷str,不是s
        // 因為題目要求第一個出現的滿足要求的字元
    {
        if (s[c] == 1) {p = c;break;}
    }
    if (p == -1) cout << "no";
    else
    {
        cout << p;
    }
    return 0;
}

6.acwing763.迴圈相剋令

// 原解法,太過低效,直接暴力列舉
// y總題解
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;// 這行程式碼最後緊跟著include
int get(string s)
{
    if (s == "Hunter") return 0;
    if (s == "Bear") return 1;
    else return 2;
}

int main()
{
    int n;cin >> n;
    while (n--)
    {
        string a,b;
        cin >> a >> b;
        int x = get(a),y = get(b);
        if (x == y) puts("Tie");
        else if ((y+1)%3 == x) puts("Player1");
        else puts("Player2");
    }
	return 0;
}

// 巧妙的解題思路,利用字母的長度之差,讀題能力實在佩服
#include <iostream>

using namespace std;

int main()
{
    int n;
    cin >> n;

    string x, y;
    while (n --)
    {
        cin >> x >> y;
        int a = x.size(), b = y.size();
        if (a - b == -1 || a - b == -2 || a - b == 3)
            cout << "Player1" << endl;
        else if (a == b)
            cout << "Tie" << endl;
        else cout << "Player2" << endl;
    }

    return 0;
}

7.acwing765.字串加空格

給定一個字串,在字串的每個字元之間都加一個空格。

輸出修改後的新字串。

輸入格式
共一行,包含一個字串。注意字串中可能包含空格。

輸出格式
輸出增加空格後的字串。

資料範圍
1≤字串長度≤100

樣例
輸入樣例:
test case
輸出樣例:
t e s t c a s e

// 遍歷字串的非常巧妙的做法
#include<iostream>
using namespace std;
int main()
{
    string a;
    getline(cin, a);
    for(char &c : a) cout << c << ' '; // 遍歷字串
}

8.acwing773.字串插入

有兩個不包含空白字元的字串str和substr,str的字元個數不超過10,substr的字元個數為3(字元個數不包括字串結尾處的’\0’。)

將substr插入到str中ASCII碼最大的那個字元後面,若有多個最大則只考慮第一個。

輸入格式

輸入包括若干行,每一行為一組測試資料,格式為

str substr

輸出格式

對於每一組測試資料,輸出插入之後的字串。

輸入樣例:

abcab eee
12343 555

輸出樣例:

abceeeab
12345553

關於substr的說明:

  1. 用途:一種構造string的方法

  2. 形式:s.substr(pos, n)

  3. 解釋:返回一個string,包含s中從pos開始的n個字元的拷貝(pos的預設值是0,n的預設值是s.size() - pos,即不加引數會預設拷貝整個s)
    當只有一個數字pos表示從下標為pos開始一直到結尾

  4. 補充:若pos的值超過了string的大小,則substr函式會丟擲一個out_of_range異常;若pos+n的值超過了string的大小,則substr會調整n的值,只拷貝到string的末尾

 string s = "0123456789";
    cout << s.substr(0,3) << endl << s.substr(3) << endl;
	// 第一個引數代表下標,第二個引數代表長度(可以不加)
/*    輸出如下
 012
3456789
*/
// 原解法TLE了,超時,寫錯了
// y總題解
#include <iostream>

using namespace std;

int main()
{
	string a,b;
	
	while (cin >> a >> b)
	{
		int p = 0;
        for (int i = 1;i < a.size();i++)
        {
            if (a[i] > a[p]) p = i;
        }
        cout << a.substr(0,p + 1) + b + a.substr(p + 1) << endl;
	}
	return 0;
}
// 題解2
#include <bits/stdc++.h>

using namespace std;

int main()
{
    char str[11], substr[4];

    int n = 2;
    while(scanf("%s %s", str, substr) != EOF){
        int cnt = str[0], res = 0;
        for(int i = 0; i < strlen(str); i++){
            if(str[i] > cnt) cnt = str[i], res = i;
            else if(str[i] == cnt) continue;
        }
        for(int i = 0; i <= res; i ++){
            cout<< str[i];
        }
        for(int i = 0; i < strlen(substr); i++){
            cout<< substr[i];
        }
        for(int i = res + 1; i < strlen(str); i++){
            cout<< str[i];
        }
        puts("");
    }
    return 0;
}