Policz wystąpienia znaków w ciągu w C ++


199

Jak mogę policzyć liczbę "_"w ciągu takich jak "bla_bla_blabla_bla"?


17
@jdmichal: „źle zadane pytanie dla początkujących”! = „zadanie domowe”

@Roger: Oczywiście, być może nie jest to praca domowa, ale dobrze jest założyć pracę domową przynajmniej dla odpowiedzi, ponieważ 1) zepsucie pytania pracy domowej jest złe dla nauki, 2) nadal możesz uczyć się na podstawie dobrych „odpowiedzi na pracę domową”, 3 ) OP może (i powinien) wyrazić opinię i powiedzieć, że to nie zadanie domowe
schnaader

3
@schnaader: Co jeśli PO twierdzi, że to nie jest praca domowa, czy nadal nie będzie to praca domowa dla kogoś innego? Czy powinniśmy to dla nich „zepsuć”? I odwrotnie: ktoś nowy w C ++, ale dawno po szkole, może zadać to pytanie; czy dałbyś im „kompletną” odpowiedź? Dlaczego cechą charakterystyczną plakatu - przypisaną przez nauczyciela (zadanie domowe) - powinna być kategoryzacja treści pytania (tagi)? Wygląda na to, że wszystkie poniższe odpowiedzi, w tym twoje i moje, byłyby takie same bez względu na ten tag.

@Roger: Naprawdę dałbym inną odpowiedź, gdybym był pewien, że to nie zadanie domowe. W tym przypadku odpowiedziałem pełnym kodem C zamiast pseudokodu. A rozpieszczanie innych ludzi nie jest tak ważne - jeśli mogą to tutaj wyszukiwać, mogą również wyszukiwać w Google. Poszukiwanie czegoś może być o wiele lepszym (choć nie najlepszym) sposobem na naukę niż publikowanie prac domowych i uzyskanie pełnego kodu / rozwiązań kilka minut później.
schnaader

2
@schnaader: Jest tam 32 odpowiedzi i kolejność sortowania jest różna, która? Czy uważasz, że nie powinienem udzielić odpowiedzi „kompletny kod” na to pytanie „domowe” ? Szczerze mówiąc, w przypadku tego pytania pomocne jest zachęcenie do myślenia, niezależnie od tego, że jest to praca domowa, i dlatego podoba mi się twoja odpowiedź znacznie lepiej niż gdyby miał pełny kod C. Z tego powodu. Jesteś pomocny, odpowiadając na pytanie, a nie na zewnętrzne zamiary plakatu.

Odpowiedzi:


418
#include <algorithm>

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

15
Trzeci argument to znak typu char, tzn. Pojedynczy cytat, a nie podwójny cytat ...
Emerson Xu

1
To najlepsza odpowiedź.
Konchog

Mała notatka, ale typ zwrotu jest zwykle podpisany. Z jakiegoś powodu std::countrodzaju zwrotów iterator_traits<InputIt>::difference_type, które dla większości standardowych pojemników std::ptrdiff_t, nie std::size_t.
Daniel Stevens

30

Pseudo kod:

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

EDYCJA: przykładowy kod C ++:

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

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

  return count;
}

Należy pamiętać, że jest to kod używać wraz z std::string, jeśli używasz char*, wymienić s.size()z strlen(s).

Uwaga: rozumiem, że chcesz czegoś „tak małego, jak to możliwe”, ale sugeruję skorzystanie z tego rozwiązania. Jak widać, możesz użyć funkcji do enkapsulacji kodu, abyś nie musiał forza każdym razem wypisywać pętli, ale możesz po prostu użyć jej count_underscores("my_string_")w pozostałej części kodu. Korzystanie z zaawansowanych algorytmów C ++ jest tutaj z pewnością możliwe, ale myślę, że to przesada.


24
Z pewnością możemy wymyślić całkowicie nieczytelną wersję szablonową z funkcjami lamba i wywołaniem bind2nd ()?
Martin Beckett,

@Martin Tak naprawdę o tym myślałem. Niestety, moja znajomość programowania funkcjonalnego C ++ praktycznie nie istnieje.
jdmichal

8
Myślę, że wywołanie usługi sieciowej byłoby znacznie przyjemniejsze niż lambdas, wtedy podstawowy algorytm nie jest po prostu nieprzenikniony, jest przechowywany gdzie indziej.
Ben Voigt,

To nie jest zadanie domowe. Jestem nowy w c ++ i nie mam wystarczającej wiedzy na temat c ++, aby programować to w zaawansowany sposób. Przeczytaj: tak mały, jak to możliwe. Jestem w stanie zaprogramować to w prosty sposób za pomocą pętli for i tak dalej, ale szukałem wyrafinowanego rozwiązania, czegoś takiego jak rozwiązanie Diego. Następnym razem dam więcej informacji z powodu pytania.
Andre de Boer

Ponadto chcesz zużywać ciągłe wystąpienia, jeśli nie chcesz duplikatów. Na przykład, licząc, ile kawałków dostaniesz po podzieleniu łańcucha przez żądany znak.
TheRealChx101

24

Staromodne rozwiązanie z odpowiednio nazwanymi zmiennymi. Daje to kodowi odrobinę ducha.

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

Edycja: około 8 lat później, patrząc na tę odpowiedź, wstydzę się, że to zrobiłem (mimo że usprawiedliwiałem to jako snarky szturchanie na pytanie o niskim wysiłku). To jest toksyczne i nie jest OK. Nie usuwam posta; Dodam te przeprosiny, aby pomóc zmienić atmosferę w StackOverflow. Więc OP: przepraszam i mam nadzieję, że dobrze odrabiłeś pracę domową pomimo mojego trollingu i że takie odpowiedzi, jak moje, nie zniechęciły Cię do uczestnictwa w witrynie.


1
Poważnie? Celowo zaciemniona odpowiedź jest najlepsza, co możesz zrobić i myślisz, że kiedykolwiek byłaby odpowiednia tutaj?

4
@Tamas: int (true) ma zawsze 1 w C ++.

6
naprawdę staromodne rozwiązanie zadeklaruje prototyp dla sprintf zamiast #include całego pliku nagłówka !
John Dibling,

5
@Tamas: Oczywiście, że nie, ale nie bawię się dobrze, „odpowiadając” na pytania początkujących.

11
Kocham to. Szkoda, że ​​narusza zasadę podwójnego podkreślenia.
Martin York,


10

Nazywasz to ... Wersja Lambda ... :)

using namespace boost::lambda;

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

Potrzebujesz kilku załączników ... Zostawiam to jako ćwiczenie ...


7
Czy naprawdę uważasz, że nowicjusz zrozumie cokolwiek z tego?
Josh Stodola

2
@Josh: W niektórych komentarzach wydaje się to efektem dziecięcego śmiechu .

5
Niektórzy z najlepszych programistów na świecie spędzili ostatnie 15 lat rozwijając C ++ do tego stopnia, że ​​możemy to napisać - to nie jest dziecinne!
Martin Beckett,

Zwracając uwagę na to, że ci, którzy nie znają Perla, są zmuszeni go odkryć (źle) - teraz byłoby to dziecinne!
Martin Beckett,

7
Niedorzeczne jest pominięcie załączników.
PascalVKooten

5

Użycie funkcji lambda do sprawdzenia, czy znak jest „_”, spowoduje tylko zwiększenie liczby, w przeciwnym razie znak nie będzie prawidłowy

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
Dodaj wyjaśnienie - postaraj się nie publikować samych bloków kodu.
CertainPerformance,

1
Jak myślisz, co oferuje twoja odpowiedź, czego poprzednia odpowiedź jeszcze nie obejmowała? Edytuj i rozszerz swoją odpowiedź.
cześć

1
Dziękujemy za ten fragment kodu, który może zapewnić ograniczoną, natychmiastową pomoc. Właściwe wyjaśnienie byłoby znacznie poprawić swoją długoterminową wartość pokazując dlaczego jest to dobre rozwiązanie problemu, a byłoby bardziej użyteczne dla czytelników przyszłości z innymi, podobnymi pytaniami. Proszę edytować swoją odpowiedź dodać kilka wyjaśnień, w tym założeń już wykonanych.
Tim Diekmann,

Użyliśmy funkcji lambda, aby sprawdzić, czy znak to „_”, wtedy tylko liczba będzie zwiększana, w przeciwnym razie znak nie będzie prawidłowy.
Nagappa,

[]( char c ){if(c =='_') return true; }wywołuje niezdefiniowane zachowanie, ponieważ nie
zwrócono

4

Istnieje kilka metod wyszukiwania std :: string, ale find jest prawdopodobnie tym, czego szukasz. Jeśli masz na myśli ciąg w stylu C, to odpowiednikiem jest strchr. Jednak w obu przypadkach można również użyć pętli for i sprawdzić każdy znak - pętla jest zasadniczo tym, co te dwa kończą.

Kiedy już wiesz, jak znaleźć następną postać z pozycją początkową, nieustannie przyspieszasz wyszukiwanie (tzn. Korzystasz z pętli), licząc od razu.


4

Liczenie wystąpień znaków w ciągu jest łatwe:

#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 To jest to samo, co dotychczasowa najlepsza odpowiedź sprzed sześciu lat - co to miało dodać? Jest jedna różnica: w tej odpowiedzi użyto niewłaściwego pliku nagłówka. stdc ++. h jest specyficzny dla GCC i nawet z tym kompilatorem jest przeznaczony tylko do użycia we wstępnie skompilowanych nagłówkach.
Arthur Tacca


2

Występowanie „_” w łańcuchu źródłowym można znaleźć, korzystając z funkcji łańcucha. Funkcja find () przyjmuje 2 argumenty, pierwszy - ciąg, którego wystąpienia chcemy znaleźć, a drugi argument przyjmuje pozycję początkową. Pętla służy do wyszukiwania wystąpienia do końca łańcucha źródłowego.

przykład:

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

Zrobiłbym w ten sposób:

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

Tak, oczywiście i faktycznie to zrobiłem, ale nie wiem, jak to popsuło, gdy skopiowałem go z Visual Studio do formularza SO.
Shivam Jha

0

Zrobiłbym coś takiego :)

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

-3

Próbować

#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
Ups! Zły język
Wyścigi lekkości na orbicie
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.