Поиск всех вхождений символа в строке - PullRequest
4 голосов
/ 11 октября 2011

У меня есть строки с разделителями-запятыми, из которых мне нужно получить значения.Проблема в том, что эти строки никогда не будут фиксированного размера.Поэтому я решил перебрать группы запятых и прочитать, что между ними.Для этого я создал функцию, которая возвращает позицию каждого вхождения в строке образца.

Это умный способ сделать это?Это считается плохим кодом?

#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;
}

Ответы [ 5 ]

12 голосов
/ 11 октября 2011
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);

И это должно дать вам нужный вам вектор.

6 голосов
/ 11 октября 2011

Если бы я проверял это, я бы увидел это и предположил, что то, что вы действительно пытаетесь сделать, - это токенизация строки, и уже есть хорошие способы сделать это.

Лучший способ сделать это - 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

Редактировать Если вам не нужна зависимость от повышения, вы также можете использовать getline с istringstream, как в в этом ответе . Чтобы скопировать несколько из этого ответа:

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

Возможно, это не напрямую , что вы просите, но я думаю, что это решает общую проблему, которую вы пытаетесь решить.

0 голосов
/ 11 октября 2011

Насколько это умно, зависит от того, что вы делаете с этими подстроками, разделенными запятыми. В некоторых случаях может быть лучше (например, быстрее, с меньшими требованиями к памяти) избегать поиска и разделения и просто анализировать и обрабатывать строку одновременно, возможно, используя конечный автомат.

0 голосов
/ 11 октября 2011

Хорошо, если ваша цель - найти индексы вхождений, следующий код будет более эффективным, так как в 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);
        }
    }
}
0 голосов
/ 11 октября 2011

Мне тоже хорошо, один комментарий с именами ваших переменных и типов. Вы называете вектор, который собираетесь вернуть characterLocations, который имеет тип int, когда действительно вы толкаете обратно сам символ (тип char), а не его местоположение. Я не уверен, для чего предназначено большее приложение, но я думаю, что было бы более разумно передать назад местоположения. Или сделайте еще один токенизатор для печенья.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...