如果标题有点含糊不清,首先道歉。我是C ++的新手,我仍在努力理解语言的复杂性。
基本上我正在处理一个很大的单词列表(实际上是一个字典),它存储在向量中。
我对此的思考过程是我想找到所有带有'c'的单词。每次有一个带有“c”的单词时,请查看它后面是否有“h”。如果确实如此,则将该单词丢回为假。希望得到像这样的话:
-carbon
-carry
etc etc
到目前为止,我已尝试实现一些代码,这是我到目前为止所做的:
bool hasCWithNoH(string wordName)
{
if (wordName.find('c'))
{
if (wordName.find('ch'))
{
return false;
}
}
}
在主{}源文件中由此调用:
void findCWithNoH()
{
cout << "List of words found with a 'c' but with no following 'h': " << endl;
for (Word word : words)
{
string testWord = word.getName();
if (word.hasCWithNoH(testWord))
{
cout << testWord << endl;
}
}
}
结果是这样的:
czarowitz
czech
czechic
czechoslovakian
czechs
h
ha
haaf
haak
haar
habeas-corpus
habenaria
结果发现每个单词都以'c'和'h'开头(不是我想要的)。
我认为我没有正确使用find()函数和循环,请问如何设置函数以及find()函数是否使用正确的函数?
如果需要更多解释,请发表评论,我可以进一步阐述。
答案 0 :(得分:3)
注意强>:
假设所有出现的'c'都不应该在'h'之后, 这应该有效。
当没有c存在时,您不会返回false 请检查string::find的返回值
返回值 第一场比赛的第一个角色的位置。 如果未找到匹配项,则函数返回string :: npos。
将您的功能更改为
bool hasCWithNoH(string &wordName)
{
if (wordName.find('c')!=string::npos)
{
if (wordName.find("ch")!=string::npos)//Also use double quotes for string "ch"
{
return false;
}
else
{
return true;
}
}
else
{
return false; //Because word does not contain c.
}
}
答案 1 :(得分:2)
有两个问题:
正确的功能应该是:
bool hasCWithNoH(string wordName) {
if (wordName.find("c") != string::npos) {
if (wordName.find("ch") != string::npos) {
return false;
} else {
return true;
}
} else {
return false;
}
}
编辑:由于最好的答案表明几乎相同的代码更改,同时提供更好的解释,我特此更新并提供不同的东西。
我们注意到名为string :: find两次的程序 - 意味着每个字符串被扫描两次。我们可以保存一张票吗?当然。
让我们首先设置测试程序。我们有测试数据和预期结果。如果实际结果有点不同,程序将输出实际结果并说“&#34;失败&#34;。
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
bool hasCWithNoH(const string& wordName) {
return true;
}
int main() {
string words[] = { // test data
"czarowitz",
"czech",
"czechic",
"czechoslovakian",
"czechs",
"h",
"ha",
"haaf",
"haak",
"haar",
"habeas - corpus",
"habenaria"
};
string expect_result[] = {
"czarowitz",
"habeas - corpus"
};
vector<string> actual_result;
for (string word : words) {
if (hasCWithNoH(word)) {
actual_result.push_back(word);
}
}
if (actual_result.size() == 2 &&
equal(expect_result, expect_result + 2, actual_result.begin())) {
cout << "Test passed" << endl;
} else {
cout << "Test failed, the following words are returned:" << endl;
for_each(actual_result.begin(), actual_result.end(), [](const string& e) { std::cout << e << endl; });
}
return 0;
}
当然,使用虚拟函数测试用例失败。
如果我们将函数更改为上面答案中的函数,则测试将通过。
现在让我们实现一次通过功能。根据描述以及提供的测试数据,我们知道只有满足以下条件时函数才应返回true
:
所以功能可以是:
bool hasCWithNoH(const string& wordName) { // use reference type wherever possible
bool match = false; // By default, it doesn't match
for (string::const_iterator it = wordName.begin(); it != wordName.end(); ++it) {
if (*it == 'c') {
match = true; // If we see there's a 'c', it becomes a candidate...
if (it != (wordName.end() - 1) && *(it + 1) == 'h') {
match = false;
break; // But if later we see an 'h' right behind 'c', it's rejected immediately
}
}
}
return match;
}
现在案件再次通过。
为了改进,我们注意到该函数只接受std :: string。嗯,最好不要依赖某种数据类型。例如,如果调用者具有C风格的字符串,我们不应强制他在调用函数之前将其转换为std :: string。所以我们可以使用模板功能:
template <class Iterator>
bool hasCWithNoH(Iterator first, Iterator last) {
bool match = false;
for (Iterator it = first; it != last; ++it) {
if (*it == 'c') {
match = true;
if (it != last - 1 && *(it + 1) == 'h') {
match = false;
break;
}
}
}
return match;
}
请注意,现在需要我们按以下方式调用该函数:
//...
for (string word : words) {
if (hasCWithNoH(word.begin(), word.end())) {
actual_result.push_back(word);
}
}
//...
运行程序,我们再次看到测试用例。
答案 2 :(得分:0)
小优化:不需要再做另一个查找,只需检查下一个字符:
bool hasCWithNoH(const string & wordName)
{
size_t pos = wordName.find('c');
if ( pos == string::npos )
return false;
while ( pos !=string::npos )
{
if ( pos +1 < wordName.size() ) {
if ( wordName[pos+1] == 'h' )
return false;
}
else
return true;
pos = wordName.find('c', pos+1);
}
return true;
}
答案 3 :(得分:0)
假设您需要: 每次有一个带有'c'的单词时,请查看它后面是否有'h'。如果确实如此,则将该单词丢回为假
由于c
完全需要h
,您可以使用:
if( string[ string.find_first_of( 'c' ) + 1 ] == 'h' ){
return false;
} else {
return true;
}
注意:
如果有多个true
,即使其他c
有c
,也会为字符串返回h
。喜欢:"abc_ch"