C ++で文字列内の文字の出現をカウントする


199

どの"_"ように文字列内の数を数えることができ"bla_bla_blabla_bla"ますか?


17
@jdmichal:「初心者向けのよくない質問」!=「宿題」

@ロジャー:もちろんそれはおそらく宿題ではないかもしれませんが、1)宿題の質問を台無しにすることは学習に悪いので、2)良い「宿題の答え」から学ぶことができるので、少なくとも宿題を仮定することは良いです3 )OPはフィードバックを提供し、これは宿題ではないと言うことができます(そうすべきです)
schnaader

3
@schnaader:OPがこれが彼らの宿題ではないと言った場合、それはまだ他の誰かの宿題である可能性が高いですか?彼らのためにそれを「台無しにする」べきでしょうか?逆もまた同様です。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(), '_');

15
3番目の引数はchar型、すなわち、単一引用符、二重引用符ではないです...
エマーソン徐

1
これが最良の答えです。
Konchog

小さなメモですが、戻り値の型は通常署名されています。なんらかの理由で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 ++アルゴリズムを使用することは確かに可能ですが、それはやり過ぎだと思います。


24
確かに、ランバ関数とbind2nd()呼び出しを備えた完全に読み取り不可能なテンプレートバージョンを思い付くことができますか?
Martin Beckett

@マーティン私は実際にそれを考えていました。残念ながら、C ++関数型プログラミングについての私の理解は事実上存在しません。
jdmichal

8
Webサービスを呼び出す方がラムダよりもはるかに楽しいと思います。その場合、コアアルゴリズムは不可解なだけでなく、他の場所に格納されます。
Ben Voigt

これは宿題ではありません。私はc ++を使い始めたばかりで、これを高度な方法でプログラミングするためのc ++の知識が不足しています。読む:できるだけ小さい。これをforループなどを使用して簡単にプログラムできますが、Diegoのソリューションのような洗練されたソリューションを探していました。次回は質問の理由について詳しく説明します。
andre de boer

また、重複したくない場合は、連続した発生を消費する必要があります。たとえば、文字列を目的の文字で分割した後に得られる個数を数えます。
TheRealChx101 2016年

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年後、この回答を見て私はこれを行ったことを恥ずかしく思います(たとえ私が低努力の質問で卑劣な口先としてそれを正当化したとしても)。これは有毒であり、OKではありません。私は投稿を削除していません。StackOverflowの雰囲気を変えるのを助けるためにこの謝罪を追加します。OP:申し訳ありません。私のトローリングにもかかわらず、宿題が正しく行われたことを願っています。私のような回答で、サイトへの参加を妨げることはありませんでした。


1
マジ?意図的に難読化された答えが最善であり、ここでこれが適切だと思いますか?

4
@Tamas:C ++では、int(true)は常に1です。

6
本当に昔ながらのソリューションでは、ヘッダーファイル全体を#includeする代わりに、sprintfのプロトタイプを宣言します
John Dibling 2010年

5
@Tamas:もちろんそうではありませんが、初心者の質問に「答える」間、私は楽しくありません。

11
大好きです。恥ずかしいですが、二重下線ルールに違反しています。
マーティンヨーク


10

名前を付けます... Lambdaバージョン... :)

using namespace boost::lambda;

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

あなたはいくつかのインクルードが必要です...私はあなたにそれを演習として残します...


7
初心者がこれを理解できると本当に思いますか?
Josh Stodola、

2
@ジョシュ:それはいくつかのコメントで幼稚な笑いのスピンオフであるように見えます

5
世界のトッププログラマーの一部は、過去15年間、C ++の進化に費やして、これを記述できるようになりました。
マーティンベケット

Perlを知らない人はそれを(ひどく)再発明することを余儀なくされることを指摘します-今ではそれは子供じみているでしょう!
マーティンベケット

7
インクルードを省略するのはばかげています。
PascalVKooten 2013年

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;

2
説明を追加してください-単純なコードブロックだけを投稿しないようにしてください。
特定のパフォーマンス2018

1
あなたの回答は何を提供していると思いますか、以前の回答はまだカバーしていません 回答を編集して展開してください。
2018

1
このコードスニペットをありがとうございます。このコードスニペットは、限られた、即時の助けを提供する可能性があります。適切な説明が大幅に長期的な価値を向上させるだろう示すことによって、なぜこれが問題に良い解決策であり、他の、同様の質問を将来の読者にそれがより便利になるだろう。答えを編集して、仮定を含めて説明を追加してください。
Tim Diekmann、2018

ラムダ関数を使用して文字が「_」であることを確認した後、カウントのみがインクリメントされ、それ以外の場合は有効な文字ではありません。
Nagappa 2018

[]( char c ){if(c =='_') return true; }すべてのコードパスで値を返さなかったため、未定義の動作を呼び出します
phuclv

4

検索にはstd :: stringのメソッドがいくつかありますが、おそらくfindが探しているものです。Cスタイルの文字列を意味する場合、同等のものはstrchrです。ただし、どちらの場合でも、forループを使用して各文字を確認することもできます。基本的に、ループはこれら2つをまとめたものです。

開始位置を指定して次の文字を見つける方法がわかったら、続けて検索を進めます(つまり、ループを使用します)。


4

文字列内の文字の出現を数えるのは簡単です:

#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これは、6年前の既存の上位回答と同じです–これは何を追加することを意味していましたか?違いが1つあります。この回答では間違ったヘッダーファイルを使用しています。stdc ++。hはGCCに固有であり、そのコンパイラーであっても、プリコンパイル済みヘッダーでの使用のみを目的としています。
Arthur Tacca


2

文字列関数を使用して、ソース文字列内の '_'の出現を確認できます。find()関数は2つの引数を受け取ります。最初の文字列は、その出現を調べたい文字列で、2番目の引数は開始位置をとります。Whileループは、ソース文字列の終わりまでの出現を見つけるために使用されます。

例:

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

はい、もちろん、実際にそれを行いましたが、idkをVisual StudioからSOフォームにコピーしたときに、どのように混乱したかを確認します。
Shivam Jha

0

私はそのようなことをしたでしょう:)

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

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

1
おっと!言語が間違っています。
2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.