Contar las ocurrencias de caracteres en una cadena en C ++

199

¿Cómo puedo contar el número de "_"en una cadena como "bla_bla_blabla_bla"?

andre de boer
fuente
17
@jdmichal: "pregunta para principiantes mal hecha"! = "tarea"
@Roger: Por supuesto, tal vez no sea tarea, pero es bueno asumir su tarea al menos para las respuestas, porque 1) estropear una pregunta de tarea es malo para aprender, 2) aún puedes aprender de buenas "respuestas de tarea", 3 ) el OP puede (y debe) dar retroalimentación y decir que esto no es tarea
schnaader
3
@schnaader: ¿Qué pasa si el OP dice que esta no es su tarea, no es probable que sea tarea para otra persona? ¿Deberíamos "estropearlo" para ellos? Y viceversa: alguien nuevo en C ++ pero fuera de la escuela puede hacer esta pregunta; ¿les darías una respuesta "completa"? ¿Por qué una característica del póster, que le asigna un maestro (tarea), debe ser una categorización del contenido de la pregunta (etiquetas)? Parece que todas las respuestas a continuación, incluidas las suyas y las mías, habrían sido las mismas independientemente de esa etiqueta.
@Roger: Hubiera dado otra respuesta si estuviera seguro de que esto no es tarea. En este caso, respondí con el código C completo en lugar de pseudocódigo. Y malcriar a otras personas no es tan crítico: si pueden buscarlo aquí, también pueden buscar en Google. Además, buscar algo en realidad podría ser una forma mucho mejor (aunque no la mejor) de aprender que simplemente publicar su tarea y obtener código / soluciones completas unos minutos más tarde.
schnaader
2
@schnaader: Hay 32 respuestas allí y el orden de clasificación varía, ¿cuál? ¿Crees que no debería haber proporcionado una respuesta de "código completo" para esta pregunta "de tarea" ? Para ser completamente honesto, para la pregunta aquí, es útil alentar el pensamiento, independientemente de que sea tarea, y me gusta su respuesta mucho mejor que si tuviera un código C completo, por esa razón. Estás siendo útil respondiendo a la pregunta, no la intención extraña del póster.

Respuestas:

418
#include <algorithm>

std::string s = "a_b_c";
size_t n = std::count(s.begin(), s.end(), '_');
Benoit
fuente
15
El tercer argumento es un tipo char, es decir, comillas simples, no comillas dobles ...
Emerson Xu
1
Esta es la mejor respuesta.
Konchog
Pequeña nota, pero el tipo de retorno suele estar firmado. Por alguna razón, std::countdevuelve el tipo iterator_traits<InputIt>::difference_type, que para la mayoría de los contenedores estándar std::ptrdiff_tno lo es std::size_t.
Daniel Stevens
30

Pseudocódigo:

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

EDITAR: código de ejemplo de C ++:

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

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

  return count;
}

Tenga en cuenta que este es un código para usar junto con std::string, si lo está usando char*, reemplace s.size()con strlen(s).

También tenga en cuenta: puedo entender que quiere algo "lo más pequeño posible", pero le sugiero que utilice esta solución. Como puede ver, puede usar una función para encapsular el código por usted para que no tenga que escribir el forbucle cada vez, sino que puede usarlo count_underscores("my_string_")en el resto de su código. El uso de algoritmos avanzados de C ++ es ciertamente posible aquí, pero creo que es excesivo.

Schnaader
fuente
24
¿Seguramente podemos llegar a una versión con plantilla totalmente ilegible con funciones de lamba y una llamada bind2nd ()?
Martin Beckett
@ Martin En realidad estaba pensando en eso. Desafortunadamente, mi comprensión de la programación funcional de C ++ es prácticamente inexistente.
jdmichal
8
Creo que llamar a un servicio web sería mucho más divertido que lambdas, entonces el algoritmo central no solo es inescrutable, se almacena en otro lugar.
Ben Voigt
Esta no es una pregunta de tarea. Soy nuevo en c ++ y no tengo suficiente conocimiento de c ++ para programar esto de manera avanzada. Leer: lo más pequeño posible. Puedo programar esto de manera simple con un bucle for, etc., pero estaba buscando una solución sofisticada, algo como la solución de Diego. La próxima vez daré más información sobre el motivo de la pregunta.
andre de boer
Además, desea consumir ocurrencias contiguas en caso de que no desee duplicados. Por ejemplo, contar cuántas piezas obtendrías después de dividir una cadena por el carácter deseado.
TheRealChx101
24

Solución pasada de moda con variables apropiadamente nombradas. Esto le da al código algo de espíritu.

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

Editar: unos 8 años después, al ver esta respuesta, me da vergüenza haberlo hecho (aunque lo justifiqué para mí mismo como un golpe sarcástico en una pregunta de bajo esfuerzo). Esto es tóxico y no está bien. No estoy quitando la publicación; Estoy agregando esta disculpa para ayudar a cambiar la atmósfera en StackOverflow. OP: Pido disculpas y espero que hayas hecho bien tu tarea a pesar de mi curricán y que las respuestas como la mía no te desanimaron a participar en el sitio.

Tamás Szelei
fuente
1
¿Seriamente? Una respuesta deliberadamente ofuscada es lo mejor que puede hacer y cree que alguna vez sería apropiado aquí.
44
@Tamas: int (verdadero) siempre es 1 en C ++.
66
¡una solución verdaderamente anticuada declararía un prototipo para sprintf en lugar de # incluyendo un archivo de encabezado completo !
John Dibling
55
@Tamas: Por supuesto que no, pero no me divierto mientras "respondo" las preguntas de los principiantes.
11
Quiéralo. Es una pena que viole la regla del doble guión bajo.
Martin York
13
#include <boost/range/algorithm/count.hpp>

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

Lo que sea ... versión Lambda ... :)

using namespace boost::lambda;

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

Necesitas varios incluye ... Te dejo como ejercicio ...

Diego Sevilla
fuente
77
¿De verdad crees que un novato va a entender algo de esto?
Josh Stodola
2
@ Josh: Parece ser un spin-off de la risa infantil en algunos comentarios .
55
Algunos de los principales programadores del mundo han pasado los últimos 15 años desarrollando C ++ hasta el punto en que podemos escribir esto: ¡no es infantil!
Martin Beckett
Señalando que aquellos que no conocen a Perl se ven obligados a reinventarlo (mal), ¡ahora eso sería infantil!
Martin Beckett
77
Es ridículo dejar de lado los incluye.
PascalVKooten
5

El uso de la función lambda para verificar que el carácter es "_", entonces solo se incrementará el conteo; de lo contrario, no será un carácter 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;
Nagappa
fuente
2
Agregue una explicación: intente no publicar solo bloques simples de código.
CertainPerformance
1
¿Qué crees que ofrece tu respuesta, qué respuesta anterior aún no ha cubierto? Por favor edite y expanda su respuesta.
hola
1
Gracias por este fragmento de código, que puede proporcionar una ayuda limitada e inmediata. Una explicación adecuada mejoraría en gran medida su valor a largo plazo al mostrar por qué esta es una buena solución al problema y lo haría más útil para futuros lectores con otras preguntas similares. Por favor, editar su respuesta a añadir un poco de explicación, incluyendo los supuestos realizados.
Tim Diekmann
Se utilizó la función lambda para verificar que el carácter es "_", entonces solo se incrementará el recuento; de lo contrario, no será un carácter válido.
Nagappa
[]( char c ){if(c =='_') return true; }invoca un comportamiento indefinido porque no devolvió un valor en todas las rutas de código
phuclv
4

Hay varios métodos de std :: string para buscar, pero encontrar es probablemente lo que está buscando. Si te refieres a una cadena de estilo C, entonces el equivalente es strchr. Sin embargo, en cualquier caso, también puede usar un bucle for y verificar cada carácter: el bucle es esencialmente lo que estos dos envuelven.

Una vez que sabe cómo encontrar el siguiente personaje dado una posición inicial, avanza continuamente su búsqueda (es decir, utiliza un bucle), contando a medida que avanza.


fuente
4

Contar las ocurrencias de caracteres en una cadena es 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;
}
MD Sakib Hossain
fuente
1
-1 Esto es lo mismo que la respuesta principal existente de seis años antes: ¿qué significaba agregar esto? Hay una diferencia: esta respuesta usa el archivo de encabezado incorrecto. stdc ++. h es específico de GCC, e incluso con ese compilador solo está diseñado para su uso en encabezados precompilados.
Arthur Tacca
44
Lectura recomendada: ¿Por qué no debería #incluir <bits / stdc ++. H>?
Carreras de ligereza en órbita
2

Puede encontrar la aparición de '_' en la cadena fuente utilizando las funciones de cadena. La función find () toma 2 argumentos, la primera cadena cuyas apariciones queremos averiguar y el segundo argumento toma la posición de inicio.

ejemplo:

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();
} 
Amruta Ghodke
fuente
2

Lo hubiera hecho de esta manera:

#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;
}
Shivam Jha
fuente
Sí, por supuesto, y de hecho lo hice, pero no sé cómo se estropeó cuando lo copié de Visual Studio a SO.
Shivam Jha
0

Hubiera hecho algo así :)

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

Tratar

#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;
}
Diseñador de software
fuente
-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]);
        }
    }
Pramod
fuente
1
Whoops! Lenguaje equivocado.
Carreras de ligereza en órbita