¿Cómo extraer números de una cadena en c?

4 minutos de lectura

Digamos que tengo una cadena como ab234cid*(s349*(20kd y quiero extraer todos los números 234, 349, 20Qué tengo que hacer ?

  • (1) ¿Qué has intentado hasta ahora?, y (2) ¿estás familiarizado con esdigito()

    – WhozCraig

    15 de noviembre de 2012 a las 14:32

  • Lo hace -123 contar como un número? +123?

    –Keith Thompson

    30 mayo 2015 a las 0:00

avatar de usuario
Serguéi Kalinichenko

Puedes hacerlo con strtolMe gusta esto:

char *str = "ab234cid*(s349*(20kd", *p = str;
while (*p) { // While there are more characters to process...
    if ( isdigit(*p) || ( (*p=='-'||*p=='+') && isdigit(*(p+1)) )) {
        // Found a number
        long val = strtol(p, &p, 10); // Read number
        printf("%ld\n", val); // and print it.
    } else {
        // Otherwise, move on to the next character.
        p++;
    }
}

Enlace a idea.

  • +1: pero porque long long val = strtol();? Prefiero usar C99 strtoll() o definir val como long 🙂

    – pmg

    15 de noviembre de 2012 a las 14:39

  • En realidad, dado que no está buscando -Me gustaría unsigned long y strtoul. =)

    – Esteban Canon

    15 de noviembre de 2012 a las 14:40

  • @HappyGreenKidNaps Eso es lo que hace que el segundo parámetro de strtol tan útil.

    – Serguéi Kalinichenko

    15 de noviembre de 2012 a las 14:42

  • @HappyGreenKidNaps: si la llamada no tiene éxito porque no hay ningún dígito presente, el valor de p no será cambiado por la llamada (o mejor dicho, se actualizará con el mismo valor que tenía anteriormente).

    – Esteban Canon

    15 de noviembre de 2012 a las 15:41

  • ¿Qué tal si tiene un número negativo, digamos ab-234cid*?

    – Raulp

    12 de marzo de 2015 a las 10:20

avatar de usuario
hmjd

Una posible solución usando sscanf() y conjuntos de escaneo:

const char* s = "ab234cid*(s349*(20kd";
int i1, i2, i3;
if (3 == sscanf(s,
                "%*[^0123456789]%d%*[^0123456789]%d%*[^0123456789]%d",
                &i1,
                &i2,
                &i3))
{
    printf("%d %d %d\n", i1, i2, i3);
}

donde %*[^0123456789] significa ignorar la entrada hasta que se encuentre un dígito. Ver demostración en http://ideone.com/2hB4UW .

O, si se desconoce la cantidad de números, puede usar %n especificador para registrar la última posición leída en el búfer:

const char* s = "ab234cid*(s349*(20kd";
int total_n = 0;
int n;
int i;
while (1 == sscanf(s + total_n, "%*[^0123456789]%d%n", &i, &n))
{
    total_n += n;
    printf("%d\n", i);
}

  • La cadena proporcionada es arbitraria, esto puede no funcionar bien con un número aleatorio de enteros. ¡Gracias de cualquier manera!

    – CDT

    16 de noviembre de 2012 a las 13:13

  • @CDT, el segundo fragmento lo hace.

    – hmjd

    16 de noviembre de 2012 a las 13:37

  • ¿Por qué no funciona para la entrada? 234cid*(s349*(20kd ?

    – Sathyamoorthy R

    31/10/2017 a las 20:43

  • Esto no funciona para números positivos.

    – Mattwmaster58

    11 de diciembre de 2021 a las 1:36

aquí después de una solución simple usando sscanf:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

char str[256]="ab234cid*(s349*(20kd";
char tmp[256];

int main()
{

    int x;
    tmp[0]='\0';
    while (sscanf(str,"%[^0123456789]%s",tmp,str)>1||sscanf(str,"%d%s",&x,str))
    {
        if (tmp[0]=='\0')
        {
            printf("%d\r\n",x);
        }
        tmp[0]='\0';

    }
}

Cree una máquina de estado que opere con un principio básico: el carácter actual es un número.

  • Al pasar de no dígito a dígito, inicializa su número actual: = número.
  • al pasar de un dígito a otro, “cambia” el nuevo dígito en:
    numero_actual := numero_actual * 10 + numero;
  • al pasar de dígito a no dígito, genera el número_actual
  • cuando de no dígito a no dígito, no haces nada.

Las optimizaciones son posibles.

Si los números están separados por espacios en blanco en la cadena, puede usar sscanf(). Como no es el caso con su ejemplo, debe hacerlo usted mismo:

char tmp[256];

for(i=0;str[i];i++)
{
  j=0;
  while(str[i]>='0' && str[i]<='9')
  {
     tmp[j]=str[i];
     i++;
     j++;
  }
  tmp[j]=0;
  printf("%ld", strtol(tmp, &tmp, 10));
  // Or store in an integer array

}

avatar de usuario
Félix

#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
void main(int argc,char *argv[])
{
char *str ="ab234cid*(s349*(20kd", *ptr = str;
while (*ptr) { // While there are more characters to process...
    if ( isdigit(*ptr) ) {
        // Found a number
        int val = (int)strtol(ptr,&ptr, 10); // Read number
        printf("%d\n", val); // and print it.
    } else {
        // Otherwise, move on to the next character.
        ptr++;
    }
}

}

avatar de usuario
Divyanshu Kushwaha

O puede hacer una función simple como esta:

// Provided 'c' is only a numeric character
int parseInt (char c) {
    return c - '0';
}

  • Si decide responder una pregunta anterior que tiene respuestas correctas y bien establecidas, es posible que agregar una nueva respuesta tarde en el día no le dé ningún crédito. Si tiene alguna información nueva distintiva, o está convencido de que las otras respuestas son incorrectas, agregue una nueva respuesta, pero ‘otra respuesta más’ que brinda la misma información básica mucho tiempo después de que se formuló la pregunta por lo general no t ganar mucho crédito.

    –Jonathan Leffler

    02/09/2017 a las 22:53

¿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