查找字符串中某个字符的所有出现情况

Finding all occurrences of a character in a string

本文关键字:情况 字符 字符串 查找      更新时间:2023-10-16

我有逗号分隔的字符串,我需要从中提取值。问题是这些字符串永远不会是固定大小的。因此,我决定遍历逗号组并读取中间的内容。为了做到这一点,我做了一个函数,返回每个事件的位置在一个示例字符串。

这是一个聪明的方法吗?这被认为是糟糕的代码吗?

#include <string>
#include <iostream>
#include <vector>
#include <Windows.h>
using namespace std;
vector<int> findLocation(string sample, char findIt);
int main()
{
    string test = "19,,112456.0,a,34656";
    char findIt = ',';
    vector<int> results = findLocation(test,findIt);
    return 0;
}
vector<int> findLocation(string sample, char findIt)
{
    vector<int> characterLocations;
    for(int i =0; i < sample.size(); i++)
        if(sample[i] == findIt)
            characterLocations.push_back(sample[i]);
    return characterLocations;
}
vector<int> findLocation(string sample, char findIt)
{
    vector<int> characterLocations;
    for(int i =0; i < sample.size(); i++)
        if(sample[i] == findIt)
            characterLocations.push_back(sample[i]);
    return characterLocations;
}

正如目前所写的,这将简单地返回一个包含字符本身的int表示的向量,而不是它们的位置,这是你真正想要的,如果我没看错你的问题的话。

替换这一行:

characterLocations.push_back(sample[i]);
characterLocations.push_back(i);

这就得到了你想要的向量。

如果我在回顾这个,我会看到这个,并假设你真正想做的是标记一个字符串,已经有很好的方法来做到这一点。

我所见过的最好的方法是使用boost::tokenizer。它允许您指定字符串的分隔方式,然后为您提供一个很好的迭代器接口来遍历每个值。

using namespace boost;
string sample = "Hello,My,Name,Is,Doug";
escaped_list_seperator<char> sep("" /*escape char*/, ","/*seperator*/, "" /*quotes*/)
tokenizer<escaped_list_seperator<char> > myTokens(sample, sep)
//iterate through the contents
for (tokenizer<escaped_list_seperator<char>>::iterator iter = myTokens.begin();
     iter != myTokens.end();
     ++iter)
{
    std::cout << *iter << std::endl;
}
输出:

Hello
My
Name
Is
Doug

Edit如果你不想依赖boost,你也可以像这个答案一样使用getlineistringstream。从这个答案中复制一些内容:

std::string str = "Hello,My,Name,Is,Doug";
std::istringstream stream(str);
std::string tok1;
while (stream)
{
    std::getline(stream, tok1, ',');
    std::cout << tok1 << std::endl;
}
输出:

 Hello
 My
 Name
 Is
 Doug

这可能不是直接你要问的问题,但我认为这是你想要解决的整体问题。

对我来说也很好,一个注释是变量和类型的命名。你调用向量,你将返回int类型的characterLocations,当你真正推回字符本身(char类型)而不是它的位置时。我不确定更大的应用程序是什么,但我认为将位置传递回去会更有意义。或者使用更简单的字符串标记。

如果你的目的是找到出现的索引,下面的代码将更有效,因为在c++中,将对象作为参数会导致对象被复制,这是不安全的,而且效率较低。特别是在这种情况下,返回一个向量是最糟糕的做法,这就是为什么把它作为参数引用会好得多。

#include <string>
#include <iostream>
#include <vector>
#include <Windows.h>
using namespace std;
vector<int> findLocation(string sample, char findIt);
int main()
{
    string test = "19,,112456.0,a,34656";
    char findIt = ',';
    vector<int> results;
    findLocation(test,findIt, results);
    return 0;
}
void findLocation(const string& sample, const char findIt, vector<int>& resultList)
{
    const int sz = sample.size();
    for(int i =0; i < sz; i++)
    {
        if(sample[i] == findIt)
        {
            resultList.push_back(i);
        }
    }
}

它有多聪明也取决于你如何处理那些用逗号分隔的子字符串。在某些情况下,避免搜索和分割,同时解析和处理字符串可能会更好(例如,更快,内存需求更小),可能使用状态机。

相关文章: