Подсчет вхождений символов в строке в C ++

199

Как я могу посчитать количество "_"в строке, как "bla_bla_blabla_bla"?

Андре де Бур
источник
17
@jdmichal: «плохо заданный вопрос для начинающих»! = «домашнее задание»
@ Роджер: Конечно, это, возможно, не домашнее задание, но хорошо бы предположить, что домашнее задание хотя бы для ответов, потому что 1) испортить домашнее задание плохо для обучения, 2) вы все еще можете учиться на хороших «домашних заданиях», 3 ) ОП может (и должен) дать отзыв и сказать, что это не домашнее задание
schnaader
3
@schnaader: Что, если ОП говорит, что это не их домашняя работа, разве это не может быть домашней работой для кого-то еще? Должны ли мы "испортить" это для них? И наоборот: кто-то новичок в C ++, но давно не посещающий школу, может задать этот вопрос; Вы бы дали им «полный» ответ? Почему характеристика плаката, присваиваемая им учителем (домашняя работа), должна быть категоризацией содержания вопроса (тегов)? Кажется, что все ответы ниже, включая ваш и мой, были бы одинаковыми, независимо от этого тега.
@ Роджер: Я бы действительно дал другой ответ, если бы был уверен, что это не домашняя работа. В этом случае я ответил бы с полным кодом C вместо псевдокода. И баловать других людей не так уж важно - если они могут искать это здесь, они могут искать и в Google. Кроме того, поиск чего-либо может быть гораздо лучшим (хотя и не лучшим) способом обучения, чем просто опубликовать домашнее задание и получить полный код / ​​решения через несколько минут.
Schnaader
2
@schnaader: там 32 ответа, и порядок сортировки меняется, какой? Как вы думаете, я не должен был дать ответ «полный код» на этот вопрос «домашнее задание» ? Честно говоря, для вопроса здесь полезно поощрять мысль, независимо от того, является ли она домашней работой, и мне нравится ваш ответ намного лучше, чем если бы у него был полный C-код, по этой причине. Вы помогаете, отвечая на вопрос, а не на посторонние намерения автора.

Ответы:

418
#include <algorithm>

std::string s = "a_b_c";
size_t n = std::count(s.begin(), s.end(), '_');
Benoit
источник
15
Третий аргумент - это тип символа, то есть одинарная кавычка, а не двойная кавычка ...
Эмерсон Сюй
1
Это лучший ответ.
Кончог
Небольшая заметка, но тип возврата обычно подписан. По какой - то причине std::countтипа возврата iterator_traits<InputIt>::difference_type, который для большинства стандартных контейнеров std::ptrdiff_t, а не std::size_t.
Даниэль Стивенс
30

псевдокод:

count = 0
For each character c in string s
  Check if c equals '_'
    If yes, increase count

РЕДАКТИРОВАТЬ: C ++ пример кода:

int count_underscores(string s) {
  int count = 0;

  for (int i = 0; i < s.size(); i++)
    if (s[i] == '_') count++;

  return count;
}

Обратите внимание, что это код для использования вместе с std::string, если вы используете char*, заменить s.size()на strlen(s).

Также обратите внимание: я могу понять, что вы хотите что-то «как можно меньше», но я бы посоветовал вам использовать это решение вместо этого. Как видите, вы можете использовать функцию для инкапсуляции кода для вас, чтобы вам не приходилось forкаждый раз записывать цикл, а просто использовать его count_underscores("my_string_")в оставшейся части кода. Использование передовых алгоритмов C ++ здесь, безусловно, возможно, но я думаю, что это излишне.

schnaader
источник
24
Конечно, мы можем придумать полностью нечитаемую шаблонную версию с функциями lamba и вызовом bind2nd ()?
Мартин Беккет
@ Мартин, я действительно думал об этом. К сожалению, мое понимание функционального программирования на C ++ практически отсутствует.
2010 года
8
Я думаю, что вызывать веб-сервис будет гораздо веселее, чем лямбда-выражения, тогда основной алгоритм не просто непостижим, он хранится в другом месте.
Бен Фойгт
Это не домашнее задание. Я новичок в C ++ и не достаточно знаний C ++, чтобы программировать это продвинутым образом. Читайте: как можно меньше. Я могу запрограммировать это простым способом с помощью цикла for и так далее, но я искал сложное решение, что-то вроде решения Диего. В следующий раз я дам больше информации по причине вопроса.
Андре де Бур
Кроме того, вы хотите использовать непрерывные вхождения в случае, если вы не хотите дубликатов. Как, например, подсчет количества фигур, которые вы получите после разбиения строки на нужный символ.
TheRealChx101
24

Старомодное решение с правильно названными переменными. Это дает коду некоторый дух.

#include <cstdio>
int _(char*__){int ___=0;while(*__)___='_'==*__++?___+1:___;return ___;}int main(){char*__="_la_blba_bla__bla___";printf("The string \"%s\" contains %d _ characters\n",__,_(__));}

Редактировать: около 8 лет спустя, глядя на этот ответ, мне стыдно, что я сделал это (хотя я оправдал это для себя как язвительный удар по вопросу с минимальными усилиями). Это токсично и не в порядке. Я не удаляю почту; Я добавляю это извинение, чтобы помочь изменить атмосферу в StackOverflow. Итак, ОП: Я извиняюсь и надеюсь, что вы выполнили свою домашнюю работу правильно, несмотря на мой троллинг, и такие ответы, как мои, не отговаривали вас от участия на сайте.

Тамас Селеи
источник
1
Шутки в сторону? Преднамеренно запутанный ответ - лучшее, что вы можете сделать, и вы думаете, что это когда-нибудь будет уместно здесь?
4
@Tamas: int (true) всегда равно 1 в C ++.
6
по-настоящему старомодное решение объявило бы прототип для sprintf вместо #inclusive целого заголовочного файла !
Джон Диблинг
5
@ Тамас: Конечно нет, но я не получаю удовольствия, отвечая на вопросы начинающих.
11
Любить это. Позор это нарушает правило двойного подчеркивания.
Мартин Йорк,
13
#include <boost/range/algorithm/count.hpp>

std::string str = "a_b_c";
int cnt = boost::count(str, '_');
user1977268
источник
10

Вы называете это ... лямбда-версия ... :)

using namespace boost::lambda;

std::string s = "a_b_c";
std::cout << std::count_if (s.begin(), s.end(), _1 == '_') << std::endl;

Вам нужно несколько включений ... Я оставляю вас в качестве упражнения ...

Диего Севилья
источник
7
Вы действительно думаете, что новичок поймет что-нибудь из этого?
Джош Стодола
2
@Josh: в некоторых комментариях это похоже на дополнительный детский смех .
5
Некоторые из лучших мировых программистов потратили последние 15 лет на развитие C ++ до такой степени, что мы можем написать это - это не по-детски!
Мартин Беккет
Подчеркивая, что те, кто не знает Perl, вынуждены (плохо) изобретать его - теперь это будет по-детски!
Мартин Беккет
8
Нелепо не включать эти списки.
PascalVKooten
5

Использование лямбда-функции для проверки того, что символ равен «_», будет увеличиваться только счетчик, в противном случае это недопустимый символ

std::string s = "a_b_c";
size_t count = std::count_if( s.begin(), s.end(), []( char c ){if(c =='_') return true; });
std::cout << "The count of numbers: " << count << std::endl;
Nagappa
источник
2
Пожалуйста, добавьте объяснение - старайтесь не публиковать только простые блоки кода.
CertainPerformance
1
Как вы думаете, что предлагает ваш ответ, что еще не было рассмотрено в предыдущем ответе? Пожалуйста, отредактируйте и расширьте свой ответ.
hellow
1
Спасибо за этот фрагмент кода, который может предоставить некоторую ограниченную, немедленную помощь. Надлежащее объяснение было бы значительно улучшить свою долгосрочную ценность , показывая , почему это хорошее решение проблемы, и сделает его более полезным для читателей будущих с другими подобными вопросами. Пожалуйста, измените свой ответ, чтобы добавить некоторые объяснения, в том числе предположения, которые вы сделали.
Тим Дикманн
Использовал лямбда-функцию, чтобы проверить, является ли символ «_», тогда будет увеличен только счетчик, иначе он не будет действительным.
Нагаппа
[]( char c ){if(c =='_') return true; }вызывает неопределенное поведение, потому что вы не вернули значение во всех путях кода
phuclv
4

Существует несколько методов поиска в std :: string, но, вероятно, именно то, что вы ищете. Если вы имеете в виду строку в стиле C, то эквивалентом является strchr. Тем не менее, в любом случае вы также можете использовать цикл for и проверять каждый символ - по сути, эти два цикла заключаются в цикле.

Как только вы знаете, как найти следующий символ по заданной позиции, вы постоянно продвигаете свой поиск (т. Е. Используете цикл), считая на ходу.


источник
4

Подсчитать количество появлений символов в строке легко:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    string s="Sakib Hossain";
    int cou=count(s.begin(),s.end(),'a');
    cout<<cou;
}
Md. Сакиб Хоссейн
источник
1
-1 Это так же, как существующий топ-ответ от шести лет назад - что это должно было добавить? Есть одно отличие: в этом ответе используется неправильный заголовочный файл. stdc ++. h специфичен для GCC, и даже с этим компилятором он предназначен только для использования в предварительно скомпилированных заголовках.
Артур Такка
4
Рекомендуемое чтение: почему я не должен #include <bits / stdc ++. H>?
Гонки
2

Вы можете узнать вхождение '_' в исходной строке, используя строковые функции. Функция find () принимает 2 аргумента, первый - строка, вхождения которой мы хотим выяснить, а второй аргумент - начальную позицию. Цикл используется для поиска вхождения до конца строки источника.

пример:

string str2 = "_";
string strData = "bla_bla_blabla_bla_";

size_t pos = 0,pos2;

while ((pos = strData.find(str2, pos)) < strData.length()) 
{
    printf("\n%d", pos);
    pos += str2.length();
} 
Амрута Гёдке
источник
2

Я бы сделал так:

#include <iostream>
#include <string>
using namespace std;
int main()
{

int count = 0;
string s("Hello_world");

for (int i = 0; i < s.size(); i++) 
    {
       if (s.at(i) == '_')    
           count++;
    }
cout << endl << count;
cin.ignore();
return 0;
}
Шивам Джа
источник
Да, конечно, и на самом деле я это сделал, но не знаю, как все испортилось, когда я скопировал его из Visual Studio в форму SO.
Шивам Джа,
0

Я бы сделал что-то подобное :)

const char* str = "bla_bla_blabla_bla";
char* p = str;    
unsigned int count = 0;
while (*p != '\0')
    if (*p++ == '_')
        count++;
FruityFred
источник
-3

Пытаться

#include <iostream>
 #include <string>
 using namespace std;


int WordOccurrenceCount( std::string const & str, std::string const & word )
{
       int count(0);
       std::string::size_type word_pos( 0 );
       while ( word_pos!=std::string::npos )
       {
               word_pos = str.find(word, word_pos );
               if ( word_pos != std::string::npos )
               {
                       ++count;

         // start next search after this word 
                       word_pos += word.length();
               }
       }

       return count;
}


int main()
{

   string sting1="theeee peeeearl is in theeee riveeeer";
   string word1="e";
   cout<<word1<<" occurs "<<WordOccurrenceCount(sting1,word1)<<" times in ["<<sting1 <<"] \n\n";

   return 0;
}
Разработчик программного обеспечения
источник
-4
public static void main(String[] args) {
        char[] array = "aabsbdcbdgratsbdbcfdgs".toCharArray();
        char[][] countArr = new char[array.length][2];
        int lastIndex = 0;
        for (char c : array) {
            int foundIndex = -1;
            for (int i = 0; i < lastIndex; i++) {
                if (countArr[i][0] == c) {
                    foundIndex = i;
                    break;
                }
            }
            if (foundIndex >= 0) {
                int a = countArr[foundIndex][1];
                countArr[foundIndex][1] = (char) ++a;
            } else {
                countArr[lastIndex][0] = c;
                countArr[lastIndex][1] = '1';
                lastIndex++;
            }
        }
        for (int i = 0; i < lastIndex; i++) {
            System.out.println(countArr[i][0] + " " + countArr[i][1]);
        }
    }
Pramod
источник
1
Упс! Неправильный язык.
Гонки