题目描述
一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数。
现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给定的文章中出现的次数和第一次出现的位置。注意:匹配单词时,不区分大小写,但要求完全匹配,即给定单词必须与文章中的某一独立单词在不区分大小写的情况下完全相同,如果给定单词仅是文章中某一单词的一部分则不算匹配。
输入格式
共 2 行。
第 1行为一个字符串,其中只含字母,表示给定单词;
第 2 行为一个字符串,其中只可能包含字母和空格,表示给定的文章。
输出格式
一行,如果在文章中找到给定单词则输出两个整数,两个整数之间用一个空格隔开,分别是单词在文章中出现的次数和第一次出现的位置(即在文章中第一次出现时,单词首字母在文章中的位置,位置从 0 开始);如果单词在文章中没有出现,则直接输出一个整数 -1。
输入输出样例
输入: To to be or not to be is a question
输出: 2 0
解题思路
(1)分割出单词。利用istringstream
输入字符串流,可以将字符串分割为单词
(2)确定单词位置。确定每一个单词的在给定文章中的位置
(3)进行匹配,输出结果。
注意:单词之间可能存在多个空格,并且给定文章可能以空格开头
代码实现:
#include <bits/stdc++.h>
using namespace std;
typedef struct {
string s;
int pos;
} Vect;
int main() {
string a;
string sentence;
getline(cin, a);
getline(cin, sentence);
//全部转换为小写
for (int i = 0; i < a.length(); i++) {
a[i] = tolower(a[i]);
}
for (int i = 0; i < sentence.length(); i++) {
sentence[i] = tolower(sentence[i]);
}
//统计每一个单词前的空格数
vector<int> k;
int count = 0;
bool flag = false;
for (int i = 0; i < sentence.length(); i++) {
if (sentence[i] == ' ') {
count++;
flag = false;
} else {
if (flag == false) {
k.push_back(count);
count = 0;
flag = true;
}
}
}
//提取每一个单词以及对应的位置
vector<Vect> v;
istringstream iss(sentence);
string word;
int p = k[0];
int j = 0;
while (iss >> word) {
Vect vect;
vect.s = word;
vect.pos = p;
v.push_back(vect);
j++;
p = p + k[j] + word.size() ;
}
//统计单词出现的次数、首次出现的位置索引
int num = 0, index;
for (int i = 0; i < v.size(); i++) {
if (v[i].s == a) {
num++;
if (num == 1) {
index = v[i].pos;
}
}
}
//输出结果
if (num == 0) {
cout << "-1";
} else {
cout << num << " " << index;
}
return 0;
}
如果熟悉find()函数的话,可以更为方便确定单词位置,但是需要注意本题要求单词之间的匹配,而find()函数是字符串匹配。例如:在句子yes is todo. 中查找to这个单词,其实找不到,但是由于todo中含有to,所以find()函数显示可以找到匹配的字符串,并返回位置。因此通过使用find()函数来确定单词位置,需要进行添加空格处理。
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using namespace std;
int main() {
//在所找单词前后加上一个空格
string str;
getline(cin, str);
str.insert(0, 1, ' ');
str += ' ';
//在所给语句前后加上一个空格
string sentence;
getline(cin, sentence);
sentence.insert(0, 1, ' ');
sentence += ' ';
//不考虑大小写,都转换为小写
for (int i = 0; i < str.length(); i++) {
str[i] = tolower(str[i]);
}
for (int i = 0; i < sentence.length(); i++) {
sentence[i] = tolower(sentence[i]);
}
//提取语句的每一个单词和对应位置
vector<string> word;
istringstream iss(sentence);
string w;
while (iss >> w) {
w.insert(0, 1, ' ');
w += ' ';
word.push_back(w);
}
int num = 0;
for (int i = 0; i < word.size(); i++) {
if (word[i] == str) {
num++;
}
}
int pos;
if (num != 0) {
pos = sentence.find(str);
cout << num << ' ' << pos << endl;
} else {
cout << "-1" << endl;
}
return 0;
}
知识点小结:
(1)vector
是C++标准库中的一个容器类,它提供了动态数组的功能。它可以在运行时根据需要自动调整大小,存储连续的元素,并提供许多与数组相关的操作。
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main() {
//1、创建vector对象
vector<int> v1;
vector<char> v2;
vector<string> v3;
//2、添加元素
//push_back:为新元素开辟空间、将新元素存入新空间里
int n;
for (int i = 0; i < 5; i++) {
cin >> n;
v1.push_back(n);
}
char c;
for (int i = 0; i < 5; i++) {
cin >> c;
v2.push_back(c);
}
string s;
for (int i = 0; i < 5; i++) {
cin >> s;
v3.push_back(s);
}
//3、访问vector中的元素
for (int i = 0; i < v1.size(); i++) {
cout << v1[i] << " ";
v1[i] = 100;//只能对已存在的元素进行赋值或者修改操作
cout << v1[i] << " ";
}
cout << endl;
//4、遍历vector中的元素
for (const auto &ele : v2) {//auto关键字,编译器会自动推导出迭代器的类型
cout << ele << " ";
}
cout << endl;
//5.使用迭代器对vector进行遍历
for (vector<string>::iterator it1 = v3.begin(); it1 != v3.end(); it1++) {
cout << *it1 << " ";
}
cout << endl;
for (vector<string>::reverse_iterator it2 = v3.rbegin(); it2 != v3.rend(); it2++) {
cout << *it2 << " ";
}
cout << endl;
return 0;
}
(2)istringstream
是 C++ 标准库中的输入字符串流类,它提供了一种方便的方式来从字符串中提取数据。通过istringstream
,你可以将字符串分割为单词或其他数据类型,并进行相应的处理。
#include <string>
#include <sstream>//1.头文件
using namespace std;
int main() {
string s1, s2;
getline(cin, s1);
getline(cin, s2);
istringstream iss1(s1);//2.将字符串与流对象绑定起来
istringstream iss2(s2);
//3.从流中提取一个单词(按照空格分割字符串)
string word;
iss1 >> word;
cout << word << endl;
//4.循环读取多个单词
int num;
while (iss2 >> num) {
cout << num << " " << endl;
}
return 0;
}