2010-09-21 19 views
9

Problème: Je dois pouvoir identifier quand deux espaces blancs se produisent de manière consécutive.Comment lire les espaces en utilisant scanf dans c?

J'ai lu les questions suivantes:

how to read a string from a \n delimited file

how to read scanf with spaces

Je suis au courant des problèmes scanf: http://c-faq.com/stdio/scanfprobs.html

entrée sera dans le format suivant:

1 5 3 2 4 6 2 1 9 0 

Deux espaces blancs indiquent que le jeu de données suivant doit être géré et comparé à lui-même. La longueur de la ligne est inconnue et le nombre ou les entiers de chaque groupe sont inconnus. Deux espaces sont les plus séparateurs de l'ensemble de données suivant.

Bien que je puisse utiliser des fgets et diverses fonctions intégrées pour résoudre ce problème, je suis à un point où la résolution du problème avec scanf à ce stade sera probablement plus facile. Cependant, si ce n'est pas le cas, en utilisant fgets, strtok et atoi feront la plupart du travail mais j'ai encore besoin d'identifier deux espaces d'affilée.

La partie ci-dessous prendra des entiers jusqu'à ce qu'un entier non-entier soit entré.

 
while (scanf ("%d", &x) == 1) 

Ce que je dois le faire est lu aussi bien et espaces blancs s'il y a deux espaces consécutifs je vais le programme de faire quelque chose de différent avec la prochaine série de données.

Et une fois que je reçois un espace blanc, je ne sais pas comment dire:

 
if ((input == "whitespace") && (previousInput == "whitespace")) 
    ya da ya da 
else (input == "whitespace") 
    ya da ya da 
else 
    ya da ya da 

J'apprécie votre temps et je vous remercie pour votre aide.

Leçon apprise: Alors qu'une solution pour scanf est affiché ci-dessous par Jonathan Leffler, la solution est un peu plus simple avec getc (par d'exiger la connaissance moins intime du scanf intérieur, les expressions régulières et char). Rétrospectivement, une meilleure connaissance des expressions régulières, scanf et char rendrait le problème plus facile et, bien sûr, de savoir quelles sont les fonctions disponibles et quelle aurait été la meilleure à utiliser dès le départ.

+2

C'est un format d'entrée assez horrible. Si vous en êtes responsable, modifiez-le. Si, comme je le soupçonne, on vous a confié un devoir, de la malchance, ce sont des enseignants sadiques. –

+3

Notez que «espace blanc» est différent de «deux espaces»; «espace blanc» signifie classiquement une variété de caractères possibles, y compris une tabulation et un espace (ou un espace), et parfois un fil de forme, une tabulation verticale ou une nouvelle ligne; et parfois retour arrière aussi. –

+0

@Jonathan Leffler: au moins, il n'essaie pas d'analyser Whitespace (http://compsoc.dur.ac.uk/whitespace/) – ninjalj

Répondre

6

getc et ungetc sont vos amis

#include <stdio.h> 

int main(void) { 
    int ch, spaces, x; 
    while (1) { 
    spaces = 0; 
    while (((ch = getc(stdin)) != EOF) && (ch == ' ')) spaces++; 
    if (ch == EOF) break; 
    ungetc(ch, stdin); 
    if (scanf("%d", &x) != 1) break; 
    printf("%d was preceded by %d spaces\n", x, spaces); 
    } 
    return 0; 
} 

Démo à http://ideone.com/xipm1

Modifier Rahhhhhhhhh ...J'ai téléchargé cela en tant que C++. Voici exactement la même chose, mais maintenant C99 strict (http://ideone.com/mGeVk)

+0

scanf, sscanf, fscanf, fgets, obtient, getc ... lol tant d'options. Je vais devoir lire sur getc et ungetc. Merci pour la réponse. – MykC

+0

+1 parce que 'getc()' et 'ungetc()' sont une meilleure façon de le faire que d'essayer simplement d'utiliser 'scanf()' - mais cela évite un peu la question. –

+4

@MykC: ** Non, PAS obtient! N'utilisez JAMAIS JAMAIS, JAMAIS ** – pmg

1
while (scanf ("%c", &x) == 1) 

En utilisant %c vous pouvez lire des caractères blancs, vous ne devez lire toutes les données et stocker en tableau. Ensuite, allouez char* cptr et obtenez cptr pour commencer de tableau, puis vous analysez votre tableau et si vous voulez lire les nombres décimaux, vous pouvez utiliser simplement sscanf sur cptr pendant que vous voulez lire décimal, mais vous devez avoir un pointeur en bonne position sur tableau (sur nombre ce que vous Wany lu)

if (((*(cptr + 1)) == ' ') && ((*cptr)== ' ')) 
    ya da ya da 
else ((*cptr)== ' ')) 
    ya da ya da 
    sscanf(++cptr, "%d", &x); 
else 
    ya da ya da 
+0

Ça a l'air bien. J'évite d'utiliser des pointeurs et des tableaux si je le peux. Note: Je vais utiliser des pointeurs et des tableaux quand cela a du sens. – MykC

+0

Je pense que si quelqu'un avait un ou plusieurs espaces, ils seraient tous stockés dans un seul caractère, ce qui empêcherait la méthode ci-dessus de fonctionner. – MykC

0

Quelle est votre définition de 'espace blanc'? Franchement, je ne pense pas que je veuille essayer d'utiliser scanf() pour identifier les espaces blancs doubles; presque toutes les autres méthodes seraient beaucoup plus faciles.

Cependant, si vous insistez pour faire le pas désespérément sensible, vous pouvez utiliser un code dérivé de ce qui suit:

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

int main(void) 
{ 
    int d; 
    char sp[3] = ""; 
    int n; 

    while ((n = scanf("%d%2[ \t]", &d, sp)) > 0) 
    { 
     printf("n = %d; d = %d; sp = <<%s>>", n, d, sp); 
     if (n == 2 && strlen(sp) == 2) 
      printf(" end of group"); 
     putchar('\n'); 
    } 
    return 0; 
} 

Les crochets enferment une classe de caractères et 2 avant qu'il insiste sur au plus de 2 caractères de la classe. Vous pourriez avoir à vous soucier de lire le saut de ligne et d'essayer d'obtenir plus de données pour satisfaire la classe de caractères - ce qui pourrait être résolu en supprimant le retour à la ligne de la classe de caractères. Mais alors, cela dépend de votre définition de l'espace blanc, et si les groupes sont automatiquement terminés par un saut de ligne ou non. Cela ne ferait pas de mal de réinitialiser sp[0] = '\0'; à la fin de la boucle.

Il est peut-être préférable d'inverser les champs pour détecter deux espaces avant un nombre. Mais cela échouerait dans le cas ordinaire, alors vous retomberiez sur un format simple pour lire le nombre (et si cela échoue, vous savez que vous n'avez ni espaces ni nombre - erreur). Notez que %d mastique l'espace blanc principal (tel que défini par la norme) - tous.

Plus je regarde ça, moins je l'aime 'scanf() seulement. Rappelle-moi de ne pas prendre de cours à ton université, s'il te plaît.

+1

Je crois que je dois seulement m'occuper d'un espace étant un seul emplacement vide de caractère ou ''. Je ne suis pas attaché à scanf, je suis seulement attaché à le faire de la manière la plus facile en supposant que je devais le faire à nouveau et pas seulement faire le travail. Je voulais juste voir s'il y avait une expression regex ou une astuce avec scanf que je pourrais ignorer qui résoudrait le problème de manière très simple puisque l'entrée est formulée. – MykC

+0

J'ai regardé votre réponse et il semble que scanf dans votre exemple retournera toujours 2. Je suis actuellement à la recherche dans quelle gamme de valeurs scanf peut revenir et pourquoi. – MykC

+0

Je suis corrigé, il ne retourne pas toujours 2. – MykC

0

Si vous voulez vraiment scanf fonctionnalité de type, vous pouvez utiliser fgets et sscanf, et utiliser le spécificateur %n pour obtenir scanf pour donner à votre programme les compensations pour le début et la fin de chaque travée des espaces en même temps, il fait le reste de son travail.

Sinon, abandonnez toute la famille scanf. C'est peut-être la partie la plus inutile de la bibliothèque standard, à mon avis.

+0

C'est utile, mais généralement mauvais. Si vous voulez ajouter l'équivalent d'une instruction print de débogage à un programme, alors c'est génial. Si vous voulez ajouter une entrée simple pour un programme de test ou de démonstration (où les bonnes pratiques de saisie ne sont pas ce que vous êtes en train de faire), alors c'est plutôt bien. Si vous voulez faire une entrée pour le code de production, c'est vraiment mauvais. – nategoose

+0

En fait, il y a une utilisation pour 'scanf': une version portable de' getline' (ou 'getdelim'), y compris le traitement propre des caractères NUL intégrés, peut être réalisé avec quelque chose comme' scanf ("% 99 [^ \ n] % n », buf, &cnt);' (où 99 est remplacé par votre taille de la mémoire tampon). –

+0

'scanf ("% 99 [^ \ n]% n", buf, &cnt);' a le problème qu'il ne sauve rien dans 'buf' et 'cnt' si l'entrée commence par' « \ n'' et laisse que' » \ n'' dans stdin Ceci est – chux

0

Voici une solution qui utilise uniquement la fonction scanf(). J'ai utilisé sscanf() dans cet exemple pour à peu près la même fonctionnalité.

#include <stdio.h> 


int p_1_cnt = 0, p_2_cnt = 0; 

void process_1(int x) 
{ 
    p_1_cnt++; 
} 


void process_2(int x) 
{ 
    p_2_cnt++; 
} 


char * input_line = "1 5 3 2 4 6 2 1 9 0"; 

int main(void) 
{ 
    char * ip = input_line; 

    int x = 0, ws_0 = 0, ws_1 = 0, preceding_spaces = 1, fields = -2; 

    while (sscanf (ip, "%d%n %n", &x, &ws_0, &ws_1) > 0) 
    { 
     ip += ws_0; 

     if ((preceding_spaces) == 1) 
      process_1(x); 
     else 
      process_2(x); 

     preceding_spaces = ws_1 - ws_0; 
    } 

    printf("\np_1_cnt = %d, p_2_cnt = %d", p_1_cnt, p_2_cnt); 
    _fgetchar(); 

    return 0; 
} 
Questions connexes