Contare le occorrenze di caratteri in una stringa in C ++


199

Come posso contare il numero di "_"in una stringa come "bla_bla_blabla_bla"?


17
@jdmichal: "domanda per principianti mal fatto"! = "compiti a casa"

@Roger: Certo, forse non è un compito a casa, ma è bene assumersi i compiti almeno per le risposte, perché 1) rovinare una domanda a casa fa male all'apprendimento, 2) puoi ancora imparare da buone "risposte a casa", 3 ) l'OP può (e dovrebbe) dare un feedback e dire che non è un compito da fare
schnaader,

3
@schnaader: E se l'OP dice che non sono i compiti, non è ancora probabile che siano compiti per qualcun altro? Dovremmo "rovinarlo" per loro? E viceversa: qualcuno che non conosce C ++ ma che non frequenta la scuola può porre questa domanda; daresti loro una risposta "completa"? Perché una caratteristica del poster - assegnata da un insegnante (compiti a casa) - dovrebbe essere una categorizzazione del contenuto della domanda (tag)? Sembra che tutte le risposte qui sotto, comprese le tue e le mie, sarebbero state le stesse indipendentemente da quel tag.

@Roger: avrei dato davvero un'altra risposta se fossi sicuro che non si tratta di compiti a casa. In questo caso avevo risposto con il codice C completo anziché pseudocodice. E rovinare le altre persone non è così critico - se possono cercarlo qui, possono anche cercare su Google. Inoltre, cercare qualcosa potrebbe effettivamente essere molto meglio (anche se non il migliore) per imparare piuttosto che pubblicare i compiti e ottenere codice / soluzioni complete qualche minuto dopo.
schnaader,

2
@schnaader: ci sono 32 risposte lì e l'ordinamento varia, quale? Pensi che non avrei dovuto fornire una risposta "completa" per questa domanda "a casa" ? Ad essere sinceri, per la domanda qui, è utile incoraggiare il pensiero indipendentemente dal fatto che si tratti di compiti a casa, e mi piace la tua risposta molto meglio che se avesse un codice C completo, per questo motivo. Stai aiutando rispondendo alla domanda, non allo scopo estraneo del poster.

Risposte:


418
#include <algorithm>

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

15
Il terzo argomento è un tipo di carattere, ovvero una virgoletta singola, non una virgoletta doppia ...
Emerson Xu,

1
Questa è la risposta migliore
Konchog

Piccola nota, ma il tipo restituito è in genere firmato. Per qualche motivo std::countrestituisce il tipo iterator_traits<InputIt>::difference_type, che per la maggior parte dei contenitori standard std::ptrdiff_tnon lo è std::size_t.
Daniel Stevens,

30

pseudocodice:

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

EDIT: codice di esempio C ++:

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

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

  return count;
}

Si noti che questo è il codice da utilizzare insieme a std::string, se lo si utilizza char*, sostituire s.size()con strlen(s).

Nota anche: posso capire che vuoi qualcosa "il più piccolo possibile", ma ti suggerisco di usare questa soluzione. Come vedi puoi usare una funzione per incapsulare il codice per te, così non dovrai scrivere il forciclo ogni volta, ma puoi semplicemente usarlo count_underscores("my_string_")nel resto del codice. L'uso di algoritmi C ++ avanzati è certamente possibile qui, ma penso che sia eccessivo.


24
Sicuramente possiamo inventare una versione templated totalmente illeggibile con funzioni lamba e una chiamata bind2nd ()?
Martin Beckett,

@Martin In realtà ci stavo pensando. Purtroppo la mia conoscenza della programmazione funzionale C ++ è praticamente inesistente.
jdmichal,

8
Penso che chiamare un servizio web sarebbe molto più divertente di lambdas, quindi l'algoritmo core non è solo imperscrutabile, è memorizzato altrove.
Ben Voigt,

Questa non è una domanda a casa. Sono nuovo di c ++ e non ho abbastanza conoscenza di c ++ per programmarlo in modo avanzato. Leggi: il più piccolo possibile. Sono in grado di programmare questo in modo semplice con un ciclo for e così via, ma stavo cercando una soluzione sofisticata, qualcosa come la soluzione di Diego. La prossima volta darò maggiori informazioni per il motivo della domanda.
andre de boer,

Inoltre, vorrai consumare ricorrenze contigue nel caso in cui non volessi duplicati. Come ad esempio, contando quanti pezzi otterrai dopo aver diviso una stringa per il personaggio desiderato.
TheRealChx101,

24

Soluzione vecchio stile con variabili con nome appropriato. Questo dà al codice un po 'di spirito.

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

Modifica: circa 8 anni dopo, guardando questa risposta mi vergogno di averlo fatto (anche se l'ho giustificato a me stesso come uno scherzo accanito a una domanda a basso sforzo). Questo è tossico e non va bene. Non rimuovo il post; Sto aggiungendo queste scuse per aiutare a spostare l'atmosfera su StackOverflow. Quindi OP: mi scuso e spero che tu abbia svolto bene i compiti nonostante la mia pesca a traina e che risposte come la mia non ti abbiano scoraggiato dal partecipare al sito.


1
Sul serio? Una risposta volutamente offuscata è il meglio che puoi fare e pensi che sarebbe mai appropriato qui?

4
@Tamas: int (true) è sempre 1 in C ++.

6
una soluzione davvero vecchia dichiarerebbe un prototipo per sprintf invece di #includere un intero file di intestazione !
John Dibling,

5
@Tamas: Certo che no, ma non mi diverto mentre "rispondo" alle domande dei principianti.

11
Lo adoro. Peccato che violi la doppia regola di sottolineatura.
Martin York,

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

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

10

Lo chiami ... versione Lambda ... :)

using namespace boost::lambda;

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

Hai bisogno di diversi include ... Ti lascio come esercizio ...


7
Pensi davvero che un principiante capirà tutto questo?
Josh Stodola,

2
@Josh: sembra essere uno spin-off della risata infantile in alcuni commenti .

5
Alcuni dei migliori programmatori del mondo hanno trascorso gli ultimi 15 anni a far evolvere il C ++ al punto in cui possiamo scrivere questo: non è infantile!
Martin Beckett,

Sottolineando che coloro che non conoscono il Perl sono costretti a reinventarlo (malamente) - ora sarebbe infantile!
Martin Beckett,

7
È ridicolo lasciare fuori le inclusioni.
PascalVKooten,

5

Utilizzando la funzione lambda per verificare che il carattere sia "_", verrà incrementato solo il conteggio altrimenti non sarà un carattere valido

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
Aggiungi una spiegazione: cerca di non pubblicare solo semplici blocchi di codice.
CertainPerformance

1
Cosa ne pensi, che offre la tua risposta, che una risposta precedente non ha già coperto? Modifica ed espandi la tua risposta.
hellow

1
Grazie per questo frammento di codice, che potrebbe fornire un aiuto limitato e immediato. Una spiegazione adeguata migliorerebbe notevolmente il suo valore a lungo termine mostrando perché questa è una buona soluzione al problema e la renderebbe più utile ai futuri lettori con altre domande simili. Si prega di modificare la risposta di aggiungere qualche spiegazione, tra le ipotesi che hai fatto.
Tim Diekmann,

Utilizzata la funzione lambda per verificare che il carattere sia "_", verrà incrementato solo il conteggio altrimenti non sarà un carattere valido.
Nagappa,

[]( char c ){if(c =='_') return true; }invoca un comportamento indefinito perché non hai restituito un valore in tutti i percorsi del codice
phuclv,

4

Esistono diversi metodi di std :: string per la ricerca, ma find è probabilmente quello che stai cercando. Se intendi una stringa in stile C, l'equivalente è strchr. Tuttavia, in entrambi i casi, puoi anche usare un ciclo for e controllare ogni personaggio: il ciclo è essenzialmente ciò che questi due concludono.

Una volta che sai come trovare il personaggio successivo dato una posizione di partenza, fai avanzare continuamente la tua ricerca (cioè usa un ciclo), contando mentre procedi.


4

Contare le occorrenze di caratteri in una stringa è semplice:

#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 Questa è la stessa della risposta principale esistente di sei anni prima: che cosa doveva aggiungere? C'è una differenza: questa risposta utilizza il file di intestazione errato. stdc ++. h è specifico di GCC e anche con quel compilatore è destinato esclusivamente all'uso in intestazioni precompilate.
Arthur Tacca,


2

È possibile scoprire la presenza di '_' nella stringa di origine utilizzando le funzioni di stringa. La funzione find () accetta 2 argomenti, il primo - stringa di cui vogliamo scoprire le occorrenze e il secondo argomento prende la posizione iniziale. Mentre il ciclo viene usato per scoprire l'occorrenza fino alla fine della stringa di origine.

esempio:

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

Avrei fatto così:

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

Sì, certo, e in effetti l'ho fatto, ma ho capito bene come si è incasinato quando l'ho copiato da Visual Studio in un modulo SO.
Shivam Jha,

0

Avrei fatto qualcosa del genere :)

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

-3

Provare

#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! Linguaggio sbagliato.
Razze di leggerezza in orbita
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.