本文我們將學習如何去驗證一個字符串是否是另一個字符串的子串。
一、小試牛刀:
題目描述
輸入兩個字符串,驗證其中一個串是否為另一個串的子串。輸入格式
兩行,每行一個字符串。輸出格式
若第一個串 s 1 是第二個串 s 2 的子串,則輸出(s1) is substring of (s2);
否則,若第二個串 s 2是第一個串 s 1的子串,輸出(s2) is substring of (s1);
否則,輸出 No substring。
輸入輸出樣例:
輸入 1
abc
dddncabca
輸出 1
abc is substring of dddncabca
輸入2
aaa
bbb
輸出 2
No substring
說明/提示:
對于 100%的數據,字符串長度在 20 以內。
方法一:
直接按照題目的思路來實現
- 此方法雖然代碼量大,但并不難想,完全是按照題目的要求來實現,所以不做過多解釋。
#include<iostream>
#include<string>
using namespace std;void substring(string s1, string s2,int len1,int len2,int min)
{int flag = 0;if (min == len1){int k = 0;for (int i = 0; i < len2; i++){int cnt = 0;for (int j = 0; j < min; j++){if (s1[j] == s2[k]){cnt++;k++;}else break;}if (cnt == min) { flag = 1; break; }else flag = -1; k = i;}}else{int k = 0;for (int i = 0; i < len1; i++){int cnt = 0;for (int j = 0; j < min; j++){if (s2[j] == s1[k]){cnt++;k++;}else break;}if (cnt == min){ flag = 0; break; }else flag = -1; k = i;}}if (flag == -1) cout << "No substring" << endl;else if(flag==0) cout << s2 << " is substring of " << s1 << endl;else cout << s1 << " is substring of " << s2 << endl;}int main(void)
{string s1,s2;cin >> s1 >> s2;int len1 = s1.length();int len2 = s2.length(); int min= len1 <= len2 ? len1 : len2;substring(s1, s2,len1,len2,min);return 0;
}
方法二:
利用cstring 庫中的 strstr 函數查找:
可以先用字符數組存字符串,然后查找子串可以使用
cstring
庫中的strstr
函數,未找到時返回NULL
。 先查找b
是否是a
的子串,再查找a
是否是b
的子串。如果都不是,輸出"No substring"
。
- 代碼如下:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{char a[25],b[25];cin>>a>>b;if(strstr(a,b)!=NULL)cout<<b<<" is substring of "<<a;else if(strstr(b,a)!=NULL)cout<<a<<" is substring of "<<b;elsecout<<"No substring";return 0;
}
方法三:
利用 string 庫里的函數來實現。
比如此時我們有一個
string
類型的變量str
:string str="hello world"
;
然后我們可以調用find
函數來在str
中尋找是否含有子串"hello"
:str.find("hello")
如果該函數的返回值為str.npos
(表示無效),則表示在str
中不存在該子串,否則存在。
- 代碼如下:
#include <iostream>
#include <string>
using namespace std;
string a,b;
int main()
{cin>>a>>b;if(a.find(b)!=a.npos) //如果b是a的子串 {cout<<b<<" is substring of "<<a<<endl;}else if(b.find(a)!=b.npos) //如果a是b的子串 {cout<<a<<" is substring of "<<b<<endl;}else //如果沒有子串關系 {cout<<"No substring"<<endl;}return 0;
}
方法四:
使用C++string庫中的std::find()函數也可以實現字符串的查找操作
(此方法和方法三有點類似)
std::find()
函數可以在一個字符串中查找另一個字符串的第一次出現的位置
- 注意
find
函數若未找到的返回值為string::npos
代碼如下:
#include<bits/stdc++.h>//萬能頭
using namespace std;
string a,b;
int main(){cin>>a>>b;if(b.find(a)!=string::npos) cout<<a<<" is substring of "<<b;//a是b的子串else if(a.find(b)!=string::npos) cout<<b<<" is substring of "<<a;//b是a的子串else cout<<"No substring";return 0;
}
二、拓展講解:
1. strstr()函數:
strstr
函數是C語言中的字符串處理函數,用于在一個字符串中查找另一個字符串的第一次出現的位置。它的原型如下:char *strstr(const char *haystack, const char *needle);
其中,參數haystack
是源字符串,參數needle
是要查找的目標字符串。
- 函數的返回值是一個指向找到的目標字符串在原字符串中的首個字符的指針。如果未找到目標字符串,則返回NULL。
以下是一個使用strstr
函數的例子:
#include <stdio.h>
#include <string.h>int main() {char str1[] = "Hello, world!";char str2[] = "world";char *result;result = strstr(str1, str2);if (result != NULL) {printf("'%s' found in '%s' at position %ld\n", str2, str1, result - str1);} else {printf("'%s' not found in '%s'\n", str2, str1);}return 0;
}
輸出結果為:
'world' found in 'Hello, world!' at position 7
- 這個例子中,
strstr
函數找到了字符串"world"在字符串"Hello, world!"中的位置,并返回了指向該位置的指針。
2. std::find()函數:
C++中的string庫中的
std::find()
函數也可以在一個字符串中查找另一個字符串的第一次出現的位置。并且std::string::find()
函數會返回一個位置索引,如果找不到子串,則返回std::string::npos
。
- 在C++中,
std::string::npos
是一個特殊的靜態成員變量,它表示字符串中不存在指定的子串。
#include <iostream>
#include <string>
#include <algorithm>int main() {std::string str1 = "Hello, world!";std::string str2 = "world";std::size_t found = str1.find(str2);if (found != std::string::npos) {std::cout << "'" << str2 << "' found in '" << str1 << "' at position " << found << std::endl;} else {std::cout << "'" << str2 << "' not found in '" << str1 << "'" << std::endl;}return 0;
}
輸出結果為:
'world' found in 'Hello, world!' at position 7
- 這個例子中,
std::find()
函數找到了字符串"world"在字符串"Hello, world!"中的位置,并返回了該位置的索引。如果未找到目標字符串,則返回std::string::npos
。
3. 域解析符:
- 聰明的你可能已經發現了,上面的方法三和方法四其實是一樣的,而這將關系到作用域的問題。
域解析符(Scope resolution operator)是
C++
中的一個運算符,用于訪問命名空間、類、結構體、枚舉等作用域內的成員。
- 域解析符使用兩個冒號
::
表示,語法形式為命名空間名::成員名或類名::成員名。
以下是一些使用域解析符的示例:
- 訪問命名空間的成員:
namespace MyNamespace {int value = 10;
}int main() {std::cout << MyNamespace::value << std::endl;return 0;
}
- 訪問類的靜態成員:
class MyClass {
public:static int value;
};int MyClass::value = 20;int main() {std::cout << MyClass::value << std::endl;return 0;
}
- 訪問類的成員函數:
class MyClass {
public:void printHello() {std::cout << "Hello" << std::endl;}
};int main() {MyClass obj;obj.printHello();return 0;
}
- 在上述示例中,域解析符用于訪問命名空間的成員、類的靜態成員和類的成員函數。它可以幫助我們在不同的作用域中訪問到所需的成員。
因此,a.find(b) != a.npos
的判斷條件也是正確的(a.npos
其實就等同于string::npos
),它用于判斷字符串a中是否存在子串b。如果子串b存在于字符串a中,a.find(b)
的返回值不等于std::string::npos
,條件成立;否則,條件不成立。
- 好了,今天的講解就到這里了。我們今天主要學習了如何驗證一個字符串是否是另一個字符串的子串,并對
strstr()
,std::find()
函數等進行了一定的學習。如果你有任何關于本篇文章的疑問,都可以在評論區提出來,我會一一解答。明天繼續加油!