Contar ocorrências de caracteres em uma cadeia de caracteres em C ++


199

Como posso contar o número de "_"em uma string como "bla_bla_blabla_bla"?


17
@jdmichal: "pergunta iniciante mal perguntou" = "dever de casa"!

@ Roger: Claro que talvez não seja tarefa de casa, mas é bom assumir a lição de casa pelo menos pelas respostas, porque 1) estragar uma pergunta de lição de casa é ruim para o aprendizado; 2) você ainda pode aprender com boas "respostas de lição de casa", 3 ), o OP pode (e deve) dar feedback e dizer que isso não é lição de casa
schnaader

3
@schnaader: E se o OP disser que esse não é o dever de casa, ainda não é provável que seja dever de casa para outra pessoa? Devemos "estragá-lo" para eles? E vice-versa: alguém novo em C ++, mas muito tempo fora da escola, pode fazer esta pergunta; você daria a eles uma resposta "completa"? Por que uma característica do pôster - atribuída por um professor (lição de casa) - deve ser uma categorização do conteúdo da pergunta (tags)? Parece que todas as respostas abaixo, incluindo a sua e a minha, teriam sido as mesmas, independentemente dessa tag.

@ Roger: Eu teria dado outra resposta, de fato, se eu tivesse certeza de que isso não é lição de casa. Nesse caso, eu respondi com código C completo em vez de pseudocódigo. Estragar outras pessoas não é tão crítico - se eles podem pesquisar aqui, também podem pesquisar no Google. Além disso, procurar por algo pode realmente ser uma maneira muito melhor (embora não a melhor) de aprender do que apenas postar sua lição de casa e obter código / soluções completos alguns minutos depois.
schnaader

2
@schnaader: Existem 32 respostas e a ordem de classificação varia, qual? Você acha que eu não deveria ter fornecido uma resposta "código completo" para essa pergunta "estilo de lição de casa" ? Para ser completamente honesto, para a pergunta aqui, é útil incentivar o pensamento, independentemente de ser dever de casa, e eu gosto muito mais da sua resposta do que se tivesse código C completo, por esse motivo. Você está sendo útil ao responder à pergunta, não à intenção estranha do pôster.

Respostas:


418
#include <algorithm>

std::string s = "a_b_c";
size_t n = std::count(s.begin(), s.end(), '_');

15
O terceiro argumento é um tipo char, ou seja, aspas simples, aspas duplas não ...
Emerson Xu

1
Esta é a melhor resposta.
Konchog 11/02

Nota pequena, mas o tipo de retorno normalmente é assinado. Por alguma razão, std::countretorna o tipo iterator_traits<InputIt>::difference_type, que para a maioria dos contêineres padrão std::ptrdiff_tnão é std::size_t.
Daniel Stevens

30

Pseudo-código:

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

EDIT: código de exemplo C ++:

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

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

  return count;
}

Observe que este é um código a ser usado junto std::string, se você estiver usando char*, substitua s.size()por strlen(s).

Observe também: entendo que você deseja algo "o menor possível", mas sugiro que você use esta solução. Como você vê, você pode usar uma função para encapsular o código para você, para que não precise escrever o forloop todas as vezes, mas pode usar apenas count_underscores("my_string_")no restante do seu código. O uso de algoritmos avançados em C ++ é certamente possível aqui, mas acho que é um exagero.


24
Certamente, podemos criar uma versão totalmente ilegível do modelo, com funções lamba e uma chamada bind2nd ()?
Martin Beckett

@ Martin Eu estava realmente pensando nisso. Infelizmente, minha compreensão da programação funcional C ++ é praticamente inexistente.
Jdmichal 5/10

8
Eu acho que chamar um serviço da Web seria muito mais divertido do que lambdas, então o algoritmo principal não é apenas inescrutável, é armazenado em outro lugar.
Ben Voigt

Esta não é uma questão de lição de casa. Eu sou novo em c ++ e não tenho conhecimento suficiente de c ++ para programar isso de maneira avançada. Leia: o menor possível. Sou capaz de programar isso de uma maneira simples com um loop for e assim por diante, mas estava procurando uma solução sofisticada, algo como a solução de Diego. Na próxima vez, darei mais informações sobre o motivo da pergunta.
andre de boer

Além disso, você deseja consumir ocorrências contíguas, caso não queira duplicatas. Por exemplo, contando quantas peças você conseguiria depois de dividir uma string pelo caractere desejado.
TheRealChx101

24

Solução antiquada com variáveis ​​nomeadas apropriadamente. Isso dá ao código algum espírito.

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

Edit: cerca de 8 anos depois, olhando para esta resposta, eu tenho vergonha de ter feito isso (mesmo que eu tenha justificado isso para mim mesma como uma piada sarcástica em uma pergunta de baixo esforço). Isso é tóxico e não está bem. Não estou removendo a postagem; Estou adicionando esse pedido de desculpas para ajudar a mudar a atmosfera no StackOverflow. Então, OP: peço desculpas e espero que você tenha acertado sua lição de casa, apesar dos meus truques e que respostas como a minha não o desencorajaram a participar do site.


1
Seriamente? Uma resposta propositadamente ofuscada é o melhor que você pode fazer e acha que alguma vez seria apropriado aqui?

4
@ Tamas: int (true) é sempre 1 em C ++.

6
uma solução verdadeiramente antiquada declararia um protótipo para o sprintf em vez de # incluir um arquivo de cabeçalho inteiro !
John Dibling 5/10/10

5
@Tamas: Claro que não, mas não me divirto enquanto "respondo" às perguntas dos iniciantes.

11
Adoro. Pena que viola a regra de sublinhado duplo.
Martin York

13
#include <boost/range/algorithm/count.hpp>

std::string str = "a_b_c";
int cnt = boost::count(str, '_');

10

Você escolhe ... Versão Lambda ... :)

using namespace boost::lambda;

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

Você precisa de vários inclui ... Deixo isso como um exercício ...


7
Você realmente acha que um novato vai entender isso?
Josh Stodola

2
@ Josh: Parece ser um spinoff do riso infantil em alguns comentários .

5
Alguns dos principais programadores do mundo passaram os últimos 15 anos desenvolvendo C ++ ao ponto em que podemos escrever isso - não é infantil!
Martin Beckett

Assinalando que aqueles que não conhecem Perl são forçados a reinventá-lo (mal) - agora isso seria infantil!
Martin Beckett

7
É ridículo deixar de fora as inclusões.
PascalVKooten

5

Usando a função lambda para verificar se o caractere é "_", apenas a contagem será incrementada, caso contrário, não será um caractere válido

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;

2
Por favor, adicione uma explicação - tente não publicar apenas blocos simples de código.
CertainPerformance 07/08/19

1
O que você acha que sua resposta oferece, que resposta anterior ainda não abordou? Edite e expanda sua resposta.
hellow

1
Obrigado por este trecho de código, que pode fornecer ajuda imediata e limitada. Uma explicação adequada melhoraria bastante seu valor a longo prazo , mostrando por que essa é uma boa solução para o problema e a tornaria mais útil para futuros leitores com outras perguntas semelhantes. Por favor edite sua resposta para adicionar alguma explicação, incluindo as suposições que você fez.
precisa saber é o seguinte

Utilizou a função lambda para verificar se o caractere é "_"; somente a contagem será incrementada, caso contrário, não será um caractere válido.
Nagappa 5/09

[]( char c ){if(c =='_') return true; }chama comportamento indefinido porque você não retornou um valor em todos os caminhos de código
phuclv

4

Existem vários métodos de pesquisa para std :: string, mas encontrar é provavelmente o que você está procurando. Se você quer dizer uma string no estilo C, o equivalente é strchr. No entanto, em ambos os casos, você também pode usar um loop for e verificar cada caractere - o loop é essencialmente o que esses dois agrupam.

Depois de saber como encontrar o próximo caractere, dada uma posição inicial, você avança continuamente sua pesquisa (ou seja, usa um loop), contando à medida que avança.


4

Contar ocorrências de caracteres em uma sequência é fácil:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    string s="Sakib Hossain";
    int cou=count(s.begin(),s.end(),'a');
    cout<<cou;
}

1
-1 É o mesmo que a resposta principal existente de seis anos antes - o que isso significava adicionar? Há uma diferença: esta resposta usa o arquivo de cabeçalho errado. O stdc ++. h é específico ao GCC e, mesmo com esse compilador, ele é destinado apenas para uso em cabeçalhos pré-compilados.
Arthur Tacca


2

Você pode descobrir a ocorrência de '_' na string de origem usando funções de string. A função find () recebe 2 argumentos, primeiro - string cujas ocorrências queremos descobrir e o segundo argumento toma posição inicial. Enquanto o loop é usado para descobrir a ocorrência até o final da string de origem.

exemplo:

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

Eu teria feito assim:

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

Sim, é claro, e na verdade eu fiz isso, mas, idk, como tudo estragou quando copiei do Visual Studio para o SO.
Shivam Jha 31/10

0

Eu teria feito algo assim :)

const char* str = "bla_bla_blabla_bla";
char* p = str;    
unsigned int count = 0;
while (*p != '\0')
    if (*p++ == '_')
        count++;

-3

Experimentar

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

1
Ops! Linguagem errada.
Lightness Races em órbita
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.