2008-10-11 10 views

Répondre

11

Peut-être le plus simple est d'utiliser la fonction strtok() (ou strtok_r() si réentrée est une préoccupation):

char str[] = "..1...10...20"; 
char *p = strtok(str, "."); 
while (p != NULL) { 
    printf("%d\n", atoi(p)); 
    p = strtok(NULL, "."); 
} 

Une fois que vous avez les résultats de l'appel atoi(), il devrait être une simple question pour sauver les entiers dans un tableau.

+0

Je vais essayer ça! –

4

Vous pouvez utiliser un code sscanf avec affectation supprimée (% * [.]) Pour passer au-dessus des points (ou tout autre caractère souhaité) et un code de comptage de caractères numérisés% n pour avancer le pointeur de chaîne.

const char *s = "..1....10..20....30...40....50...80..."; 
int num, nc; 

while (sscanf(s, "%*[.]%d%n", &num, &nc) == 1) { 
    printf("%d\n", num); 
    s += nc; 
} 
+0

Pour répondre à la plainte de Robert Gamble selon laquelle cela ne gère pas les chaînes sans points principaux, vous pouvez choisir d'écrire ceci: while (sscanf (s, "% d% n", & num, & nc) == 1 || sscanf (s, "% * [.]% d% n", & num, & nc) == 1)/* L'évaluation en court-circuit est géniale */ – ephemient

-2

Je préfère l'utilisation de strtok dans une boucle for. Cela semble plus naturel, bien que la syntaxe semble un peu étrange.

char str[] = "..1....10..20....30...40....50...80..." 
for (char* p = strtok(strtok, "."); p != NULL; p = strtok(NULL, ".")) 
{ 
    printf("%d\n", atoi(p)); 
} 
+0

En effet, cela semble assez bizarre. J'aurais attendu quelque chose comme pour (p = strtok (str, ","), p = strtok (NULL, ".");), Un point-virgule après la première ligne et une déclaration de p. – mweerden

+0

Ouais - le code est écrit du haut de ma tête. Corrigée. –

+0

Je ne pense pas que cela fonctionnera pour avoir l'initialisation dans la position de test de la boucle for. Ceci serait exécuté chaque fois au début de la boucle. Je ne pense pas que ce soit ce que tu veux. La version de mweerden est meilleure, mais j'utilise un test explicite dans la position de test et déplace le prochain jeton à la fin. – tvanfosson

1

Voici la bonne façon de le faire, il est un peu plus longue que la façon la plus simple, mais il ne souffre pas de comportement non défini si la valeur lue est hors de portée, fonctionne correctement si le premier caractère est pas un point, etc. Vous n'avez pas spécifié si les nombres pouvaient être négatifs, donc j'ai utilisé un type signé mais seulement permettez des valeurs positives, vous pouvez facilement changer cela en permettant le signe négatif en haut de la boucle while interne. Cette version permet à tous les caractères non numériques de délimiter des entiers, si vous voulez seulement que les points soient autorisés, vous pouvez modifier la boucle interne pour sauter seulement les points et ensuite vérifier un chiffre.

#include <stdio.h> 
#include <stdlib.h> 
#include <ctype.h> 
#include <errno.h> 

#define ARRAY_SIZE 10 

size_t store_numbers (const char *s, long *array, size_t elems) 
{ 
    /* Scan string s, returning the number of integers found, delimited by 
    * non-digit characters. If array is not null, store the first elems 
    * numbers into the provided array */ 

    long value; 
    char *endptr; 
    size_t index = 0; 

    while (*s) 
    { 
    /* Skip any non-digits, add '-' to support negative numbers */ 
    while (!isdigit(*s) && *s != '\0') 
     s++; 

    /* Try to read a number with strtol, set errno to 0 first as 
    * we need it to detect a range error. */ 
    errno = 0; 
    value = strtol(s, &endptr, 10); 

    if (s == endptr) break; /* Conversion failed, end of input */ 
    if (errno != 0) { /* Error handling for out of range values here */ } 

    /* Store value if array is not null and index is within array bounds */ 
    if (array && index < elems) array[index] = value; 
    index++; 

    /* Update s to point to the first character not processed by strtol */ 
    s = endptr; 
    } 

    /* Return the number of numbers found which may be more than were stored */ 
    return index; 
} 

void print_numbers (const long *a, size_t elems) 
{ 
    size_t idx; 
    for (idx = 0; idx < elems; idx++) printf("%ld\n", a[idx]); 
    return; 
} 

int main (void) 
{ 
    size_t found, stored; 
    long numbers[ARRAY_SIZE]; 
    found = store_numbers("..1....10..20....30...40....50...80...", numbers, ARRAY_SIZE); 

    if (found > ARRAY_SIZE) 
    stored = ARRAY_SIZE; 
    else 
    stored = found; 

    printf("Found %zu numbers, stored %zu numbers:\n", found, stored); 
    print_numbers(numbers, stored); 

    return 0; 
} 
+0

Premièrement, la réponse simple ne se casse pas s'il n'y a pas de points principaux et par définition puisque c'est l'analyse d'un indicateur de progression, l'entrée est bien délimitée en termes de gamme de nombres. Utiliser strtol() ou strtoul() est probablement une amélioration par rapport à atoi(), mais votre solution est inutilement complexe. –

+0

La version strtok ne fonctionne pas sur les littéraux de chaîne, ne stocke pas les nombres dans un tableau et utilise l'atoi problématique. La solution sscanf ne fonctionne pas sans les premiers points et a des problèmes similaires à atoi. Ma solution est plus longue mais c'est aussi un programme complet avec vérification des erreurs et commentaires. –