Contando el número de ocurrencias de un carácter en una cadena en C

5 minutos de lectura

avatar de usuario
Miguel

tengo la cuerda str

char *str = "100.10b.100.100";

Quiero contar las ocurrencias de '.' en str, preferiblemente de una sola línea. (Si es posible sin bucles)

Mi enfoque sería el estándar. strchr:

  int i = 0;
  char *pch=strchr(str,'.');
  while (pch!=NULL) {
    i++;
    pch=strchr(pch+1,'.');
  }

  • A la bolsa de mantra: ¿qué has probado? que tal si no funciona …….

    – KevinDTimm

    20 de noviembre de 2010 a las 23:14

  • @KevinDTimm: Publiqué mi enfoque.

    – Miguel

    20 de noviembre de 2010 a las 23:15

  • Como señaló tvanfosson, puedes hacerlo con recursividad, y tal vez eso es lo que tu maestro quería que hicieras, pero es una forma completamente idiota de hacerlo. resultará en desbordamiento de pila para cadenas lo suficientemente grandes… y no el tipo bueno de SO que hace la tarea por usted, ¡el tipo malo! 😉

    – R.. GitHub DEJA DE AYUDAR A ICE

    21 de noviembre de 2010 a las 1:00

avatar de usuario
R.. GitHub DEJAR DE AYUDAR A ICE

Así es como lo haría (se necesita un número mínimo de variables):

for (i=0; s[i]; s[i]=='.' ? i++ : *s++);

  • No, estoy incrementando cualquiera s o i dependiendo de si s[i] es un '.' O no. La expresion s+i siempre aumenta exactamente en 1 en cada iteración, pero podría ser el contador (i) o el puntero base (s) que causa s+i aumentar

    – R.. GitHub DEJA DE AYUDAR A ICE

    21 de noviembre de 2010 a las 14:15

  • yo llamaría eso inteligente. En codigo, inteligente no siempre es algo bueno. normalmente prefiero obvio.

    – tvanfosson

    21 de noviembre de 2010 a las 14:17

  • Si ya está incrementando s, ¿por qué no usar i por completo para contar las ocurrencias de ‘.’? para (; *s; i += *s == ‘.’, s++)

    – jake

    29 de noviembre de 2013 a las 1:16


  • Me pregunto cuántas personas como yo pasaron todo el día tratando de resolver esto.

    – razz

    13 dic 2015 a las 0:30

  • una solución inteligente, pero esto moverá el puntero a otra ubicación para que no pueda usar la cadena s nuevamente

    – smihael

    13 de enero de 2017 a las 2:45

avatar de usuario
miguel j

OK, una implementación sin bucle (y sí, es una broma).

size_t CountChars(const char *s, char c)
{
  size_t nCount=0;
  if (s[0])
  {
    nCount += ( s[0]==c);
    if (s[1])
    {
      nCount += ( s[1]==c);
      if (s[2])
      {
        nCount += ( s[2]==c);
        if (s[3])
        {
          nCount += ( s[3]==c);
          if (s[4])
          {
            nCount += ( s[4]==c);
            if (s[5])
            {
              nCount += ( s[5]==c);
              if (s[6])
              {
                nCount += ( s[6]==c);
                if (s[7])
                {
                  nCount += ( s[7]==c);
                  if (s[8])
                  {
                    nCount += ( s[8]==c);
                    if (s[9])
                    {
                      nCount += ( s[9]==c);
                      if (s[10])
                      {
                        /* too long */
                        assert(0);
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
  return nCount;
}

  • Creo que has duplicado tu 8 aquí: nCount += ( s[88]==c);. Debería haber escrito un generador de código C que llamara cc vía system para producir el resultado final. O mejor aún, un generador de código recursivo para evitar bucles en el generador de código.

    – mu es demasiado corto

    21 de noviembre de 2010 a las 0:20

  • Siete años después, alguien votó en contra de esto sin siquiera comentar por qué. Este fue un código cómico y lo dice en la parte superior. Ilustra la impracticabilidad de la pregunta. A alguien le preocupa que sea de mal estilo???

    – Michael J.

    22 de noviembre de 2016 a las 2:42

avatar de usuario
tvanfosson

Mira, mamá, sin bucles.

int c = countChars( s, '.' );

int countChars( char* s, char c )
{
    return *s == '\0'
              ? 0
              : countChars( s + 1, c ) + (*s == c);
}

Pero, de hecho, usaría un bucle, ya que esa es la estructura de control correcta para usar.

  • ah, dulzura y luz 🙂 – ¿pero no puedes hacer un ternario para que solo haya un retorno (y no si)?

    – KevinDTimm

    20 de noviembre de 2010 a las 23:19

  • Pienso que el | se supone que es un :. Además, “sin bucles” está bien, pero no es exactamente tan legible ni fácil de mantener como un bucle, y tampoco va a ser más rápido. (Aunque puede que no sea más lento, gracias a la recursividad de la cola). El código inteligente no siempre es un buen código, especialmente cuando ofusca el significado.

    – cdhowie

    20 de noviembre de 2010 a las 23:20


  • Pero tu están usando un bucle! (Simplemente no está utilizando las palabras clave for/while).

    usuario166390

    20 de noviembre de 2010 a las 23:24


  • @pst: no es un bucle, usa recursividad, que en este caso es posiblemente peor.

    – tvanfosson

    20 de noviembre de 2010 a las 23:26

  • Necesitas *s==c entre paréntesis. + tiene mayor precedencia que ==obviamente.

    – R.. GitHub DEJA DE AYUDAR A ICE

    21 de noviembre de 2010 a las 14:17

Sin bucles será difícil ya que no hay una función de biblioteca C estándar que haga esto y debe mirar todos los caracteres 🙂

Voy a tomar la solución obvia:

int i, count;
for (i=0, count=0; str[i]; i++)
  count += (str[i] == '.');

Siéntase libre de comprimir las dos líneas de código real en una sola si es necesario 🙂

avatar de usuario
steve jesop

Si está interesado en una sola línea (bueno, dos):

size_t count = 0;
while(*str) if (*str++ == '.') ++count;

  • Aquí está reducido a una sola instrucción for que incluye la variable de bucle y la salida: for (size_t i=0; s[i] || printf("%d\n", i)>INT_MAX; s[i]=='.'?i++:s++); 😉

    – R.. GitHub DEJA DE AYUDAR A ICE

    21 de noviembre de 2010 a las 1:05

avatar de usuario
cdhowie

Todavía arrojaría esto en una función, parametrizando la cadena de origen y el carácter a buscar.

int count_characters(const char *str, char character)
{
    const char *p = str;
    int count = 0;

    do {
        if (*p == character)
            count++;
    } while (*(p++));

    return count;
}

  • Aquí está reducido a una sola instrucción for que incluye la variable de bucle y la salida: for (size_t i=0; s[i] || printf("%d\n", i)>INT_MAX; s[i]=='.'?i++:s++); 😉

    – R.. GitHub DEJA DE AYUDAR A ICE

    21 de noviembre de 2010 a las 1:05

avatar de usuario
Sanjeev

//Supongo que debería funcionar. Una línea y sin bucle.

int countChar(char *s, char letter) {
    return ((*s) ? (((*s++ == letter)? 1:0)) + countChar (s, letter)): 0);
}

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad