Đếm số lần xuất hiện của ký tự trong một chuỗi trong C ++


199

Làm thế nào tôi có thể đếm số lượng "_"trong một chuỗi như thế "bla_bla_blabla_bla"nào?


17
@jdmichal: "câu hỏi dành cho người mới bắt đầu kém"! = "bài tập về nhà"

@Roger: Tất nhiên có lẽ nó không phải là bài tập về nhà, nhưng tốt nhất là giả sử bài tập về nhà của nó ít nhất là cho câu trả lời, bởi vì 1) làm hỏng câu hỏi bài tập về nhà là không tốt cho việc học, 2) bạn vẫn có thể học từ "câu trả lời bài tập về nhà" tốt, 3 ) OP có thể (và nên) đưa ra phản hồi và nói rằng đây không phải là bài tập về nhà
schnaader

3
@schnaader: Điều gì sẽ xảy ra nếu OP nói đây không phải là bài tập về nhà của họ, không phải nó vẫn có khả năng là bài tập về nhà cho người khác sao? Chúng ta có nên "làm hỏng" nó cho họ? Và ngược lại: một người mới biết đến C ++ nhưng lâu năm mới ra trường có thể hỏi câu hỏi này; bạn sẽ cho họ một câu trả lời "hoàn chỉnh" chứ? Tại sao một đặc điểm của poster poster được giáo viên (bài tập về nhà) chỉ định là một phân loại nội dung của câu hỏi (thẻ)? Có vẻ như tất cả các câu trả lời dưới đây, bao gồm cả của bạn và của tôi, sẽ giống nhau bất kể thẻ đó.

@Roger: Tôi thực sự đã đưa ra một câu trả lời khác nếu tôi chắc chắn đây không phải là bài tập về nhà. Trong trường hợp này, tôi đã trả lời với mã C hoàn chỉnh thay vì mã giả. Và làm hỏng người khác không phải là điều quan trọng - nếu họ có thể tìm kiếm ở đây, họ cũng có thể tìm kiếm Google. Ngoài ra, tìm kiếm một cái gì đó thực sự có thể tốt hơn nhiều (mặc dù không phải là cách tốt nhất) để học hơn là chỉ đăng bài tập về nhà của bạn và nhận mã / giải pháp hoàn chỉnh vài phút sau đó.
schnaader

2
@schnaader: Có 32 câu trả lời ở đó và thứ tự sắp xếp khác nhau, câu nào? Bạn có nghĩ rằng tôi không nên cung cấp câu trả lời "mã hoàn chỉnh" cho câu hỏi "bài tập về nhà" này không? Thành thật mà nói, đối với câu hỏi ở đây, thật hữu ích để khuyến khích suy nghĩ bất kể đó là bài tập về nhà và tôi thích câu trả lời của bạn tốt hơn nhiều so với việc nó có mã C hoàn chỉnh hay không, vì lý do đó. Bạn đang có ích bằng cách trả lời câu hỏi, không phải ý định xa lạ của người đăng.

Câu trả lời:


418
#include <algorithm>

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

15
Đối số thứ ba là loại char, nghĩa là trích dẫn đơn, không phải trích dẫn kép ...
Emerson Xu

1
Đây là câu trả lời tốt nhất.
Konchog

Lưu ý nhỏ, nhưng loại trả lại thường được ký. Đối với một số lý do std::counttrả về loại iterator_traits<InputIt>::difference_type, mà đối với hầu hết các container tiêu chuẩn std::ptrdiff_t, thì không std::size_t.
Daniel Stevens

30

Mã giả:

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

EDIT: mã ví dụ C ++:

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

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

  return count;
}

Lưu ý rằng đây là mã để sử dụng cùng với std::string, nếu bạn đang sử dụng char*, thay thế s.size()bằngstrlen(s) .

Cũng lưu ý: Tôi có thể hiểu bạn muốn một cái gì đó "nhỏ nhất có thể", nhưng tôi khuyên bạn nên sử dụng giải pháp này thay thế. Như bạn thấy, bạn có thể sử dụng một hàm để đóng gói mã cho bạn để bạn sẽ không phải viết ra forvòng lặp mọi lúc, nhưng chỉ có thể sử dụng count_underscores("my_string_")trong phần còn lại của mã. Sử dụng các thuật toán C ++ nâng cao chắc chắn là có thể ở đây, nhưng tôi nghĩ nó quá mức cần thiết.


24
Chắc chắn chúng ta có thể đưa ra một phiên bản templated hoàn toàn không thể đọc được với các hàm lamba và một lệnh gọi bind2nd ()?
Martin Beckett

@Martin Tôi đã thực sự nghĩ về điều đó. Thật không may, sự hiểu biết của tôi về lập trình chức năng C ++ thực tế là không tồn tại.
jdmichal

8
Tôi nghĩ rằng việc gọi một dịch vụ web sẽ thú vị hơn nhiều so với lambdas, sau đó thuật toán cốt lõi không chỉ là khó hiểu, nó được lưu trữ ở nơi khác.
Ben Voigt

Đây không phải là câu hỏi bài tập về nhà. Tôi chưa quen với c ++ và không có đủ kiến ​​thức về c ++ để lập trình điều này theo cách nâng cao. Đọc: càng nhỏ càng tốt. Tôi có thể lập trình điều này một cách đơn giản với một vòng lặp for, v.v., nhưng tôi đang tìm kiếm một giải pháp tinh vi, giống như giải pháp của Diego. Lần sau tôi sẽ cung cấp thêm thông tin cho lý do của câu hỏi.
andre de boer

Ngoài ra, bạn muốn sử dụng các lần xuất hiện liên tục trong trường hợp bạn không muốn trùng lặp. Ví dụ như, đếm số lượng phần bạn nhận được sau khi tách một chuỗi theo ký tự mong muốn.
TheRealChx101

24

Giải pháp lỗi thời với các biến được đặt tên thích hợp. Điều này cung cấp cho mã một số tinh thần.

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

Chỉnh sửa: khoảng 8 năm sau, nhìn vào câu trả lời này, tôi cảm thấy xấu hổ vì tôi đã làm điều này (mặc dù tôi tự biện minh nó là một câu châm chọc vào một câu hỏi nỗ lực thấp). Điều này là độc hại và không ổn. Tôi không xóa bài viết; Tôi đang thêm lời xin lỗi này để giúp thay đổi không khí trên StackOverflow. Vì vậy, OP: Tôi xin lỗi và tôi hy vọng bạn có bài tập về nhà ngay cả khi tôi troll và câu trả lời như của tôi không khiến bạn nản lòng khi tham gia trang web.


1
Nghiêm túc? Một câu trả lời có chủ đích là câu trả lời tốt nhất bạn có thể làm và bạn nghĩ nó sẽ phù hợp ở đây?

4
@Tamas: int (true) luôn là 1 trong C ++.

6
một giải pháp lỗi thời thực sự sẽ tuyên bố một nguyên mẫu cho sprintf thay vì # bao gồm toàn bộ tệp tiêu đề !
John Dibling

5
@Tamas: Tất nhiên là không, nhưng tôi không có niềm vui trong khi "trả lời" câu hỏi của người mới bắt đầu.

11
Yêu nó. Xấu hổ vì nó vi phạm quy tắc gạch dưới kép.
Martin York


10

Bạn đặt tên cho nó ... phiên bản Lambda ... :)

using namespace boost::lambda;

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

Bạn cần một số bao gồm ... Tôi để lại cho bạn như một bài tập ...


7
Bạn có thực sự nghĩ rằng một người mới sẽ hiểu bất kỳ điều này?
Josh Stodola

2
@Josh: Nó dường như là một spinoff của tiếng cười trẻ con trong một số ý kiến .

5
Một số lập trình viên hàng đầu thế giới đã dành 15 năm qua để phát triển C ++ đến mức chúng ta có thể viết điều này - nó không trẻ con!
Martin Beckett

Đưa ra quan điểm rằng những người không biết Perl buộc phải phát minh lại (thật tệ) - bây giờ điều đó thật trẻ con!
Martin Beckett

7
Nó là vô lý để bỏ đi bao gồm.
PascalVKooten

5

Sử dụng hàm lambda để kiểm tra ký tự là "_" thì chỉ tính sẽ được tăng lên nếu không phải là ký tự hợp lệ

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
Vui lòng thêm một lời giải thích - cố gắng không chỉ đăng các khối mã đơn thuần.
SurePerformance

1
Bạn nghĩ gì, câu trả lời của bạn đưa ra, câu trả lời trước chưa được đề cập đến là gì? Vui lòng chỉnh sửa và mở rộng câu trả lời của bạn.
hellow

1
Cảm ơn bạn vì đoạn mã này, có thể cung cấp một số trợ giúp hạn chế, ngay lập tức. Một lời giải thích phù hợp sẽ cải thiện đáng kể giá trị lâu dài của nó bằng cách chỉ ra lý do tại sao đây là một giải pháp tốt cho vấn đề và sẽ giúp nó hữu ích hơn cho những người đọc tương lai với những câu hỏi tương tự khác. Vui lòng chỉnh sửa câu trả lời của bạn để thêm một số giải thích, bao gồm các giả định bạn đã thực hiện.
Tim Diekmann

Đã sử dụng hàm lambda để kiểm tra ký tự là "_" thì chỉ tính sẽ được tăng lên nếu không phải là ký tự hợp lệ.
Nagappa

[]( char c ){if(c =='_') return true; }gọi hành vi không xác định vì bạn đã không trả về giá trị trong tất cả các đường dẫn mã
phuclv

4

Có một số phương pháp của std :: string để tìm kiếm, nhưng find có lẽ là thứ bạn đang tìm kiếm. Nếu bạn có nghĩa là một chuỗi kiểu C, thì tương đương là strchr. Tuy nhiên, trong cả hai trường hợp, bạn cũng có thể sử dụng vòng lặp for và kiểm tra từng ký tự. Vòng lặp về cơ bản là những gì hai cái này kết thúc.

Khi bạn biết cách tìm nhân vật tiếp theo được cung cấp vị trí bắt đầu, bạn liên tục tiến hành tìm kiếm (nghĩa là sử dụng vòng lặp), tính khi bạn đi.


4

Đếm số lần xuất hiện của ký tự trong một chuỗi rất dễ dàng:

#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 Điều này giống như câu trả lời hàng đầu hiện có từ sáu năm trước - điều này có nghĩa là gì? Có một điểm khác biệt: câu trả lời này sử dụng tệp tiêu đề sai. stdc ++. h đặc trưng cho GCC và ngay cả với trình biên dịch đó, nó chỉ dành cho sử dụng trong các tiêu đề được biên dịch trước.
Arthur Tacca


2

Bạn có thể tìm ra sự xuất hiện của '_' trong chuỗi nguồn bằng cách sử dụng các hàm chuỗi. Hàm find () có 2 đối số, chuỗi thứ nhất có lần xuất hiện mà chúng ta muốn tìm hiểu và đối số thứ hai có vị trí bắt đầu. Vòng lặp được sử dụng để tìm ra sự xuất hiện cho đến khi kết thúc chuỗi nguồn.

thí dụ:

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

Tôi đã làm theo cách này:

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

Vâng tất nhiên, và trên thực tế tôi đã làm điều đó, nhưng idk làm thế nào nó rối tung lên khi tôi sao chép nó từ Visual Studio sang dạng SO.
Shivam Jha

0

Tôi đã làm một cái gì đó như thế :)

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

-3

Thử

#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
Rất tiếc! Sai ngôn ngữ.
Các cuộc đua nhẹ nhàng trong quỹ đạo
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.