2009-02-27 1 views
1

Travailler sur (ce qui devrait être) un projet simple, prendre l'entrée de stdin et la reformater pour qu'elle corresponde aux spécifications de sortie. Je veux juste voir ce que les experts pensent de la fonction suivante qui est censée ignorer les k caractères jusqu'à la fin de la ligne, à moins que k < 0, où il va continuer à sauter des caractères jusqu'à ce qu'il atteigne le retour à la ligne.Critiquer ma fonction pour ignorer les caractères k du flux d'entrée

1 #include <stdio.h> 
25 int skip(int count){ 
26 int i; 
27 int ch; 
28 
29 for(i = 0; count < 0 || i < count; i++){ 
30  ch = fgetc(stdin); 
31  if(ch == EOF){ 
32  return -1; 
33  } 
34  if(ch == '\n'){ 
35  return 0; 
36  } 
37 } 
38 return 1; 
39 } 

(y compris les numéros de ligne à des fins de référence)

+0

Vous ne signifie pas « espaces »-vous? On dirait qu'il saute –

+0

Votre code caractères ne se comporte pas Si vous rencontrez un saut de ligne, il sautera moins de k caractères si k> = 0. –

+0

@Dan: Vous avez raison, cependant, c'était mon intention, laissez-moi reformuler la spécification de la fonction: – sdellysse

Répondre

1

Il n'y a rien de grave avec ce code. Mais pour le rendre plus robuste, je voudrais:

  1. Enregistrer la valeur de fgetc(stdin) à une variable int, puis le tester pour vous assurer qu'il est un vide à l'aide isspace(), signalant une erreur sinon. Utilisez un int pas un char car fgetc() renvoie EOF à la fin du fichier, qui ne peut pas entrer dans un char.

  2. Une autre préoccupation mineure est que sur les systèmes de fichiers modernes, les tailles de fichiers peuvent être supérieures à INT_MAX. Au lieu de "simuler" une count valeur de INT_MAX lorsque k < 0, je voudrais changer le test de boucle pour le tester explicitement.

En résumé, la boucle principale devient:

int ch; 
for (i = 0; k < 0 || i < k; ++i) { 
    ch = fgetc(stdin); 
    if (ch == '\n') { 
     return 1; 
    } else if (ch == EOF) { 
     return -1;  /* Or some error code of your choice */ 
    } else if (!isspace(ch)) { 
     return -2;  /* Or some error code of your choice */ 
    } 
} 
+0

bien, j'étais ambigu à propos de l'utilisation du mot «espace» J'aurais dû dire «colonne», car il y a surtout des données de poubelle pour les k premières colonnes de chaque ligne, mais merci pour le conseil sur INT_MAX, puisque je ne travaille que sur une seule ligne de l'entrée, c'est discutable, mais j'aime écrire plus robuste que nécessaire – sdellysse

+0

Pas de problème. ctly est probablement plus important que l'entreprise INT_MAX, mais comme vous le dites, ça ne fait jamais mal d'être plus robuste que nécessaire :) –

0

Pas mal. Si vous avez travaillé avec moi et que vous avez écrit ce code, je ne vous demanderais pas de le changer.

Vous pouvez décrémenter count jusqu'à ce qu'il atteigne zéro, au lieu d'incrémenter i jusqu'à ce qu'il atteigne count, mais il est discutable si ce serait une amélioration ou non.

0

Je préférerais

if (k < 0) count = 0 
else  count = k; 

do { 
    if(fgetc(stdin) == '\n') return 1; 
    count--; 
} while (count != 0); 

return 0; 

pour éviter l'utilisation INT_MAX. Notez que les deux premières lignes pourraient aussi simplement être changées en "count = k;" et que vous pouvez changer la variable count en un type 64 bits pour gérer les entrées> 2 GB.

Si vous avez des entrées importantes, vous pouvez également essayer de lire des lignes entières ou même le fichier entier dans un tampon et de passer un pointeur sur la fonction de saut pour augmenter les performances.

0

Personnellement, je ne voudrais pas utiliser la comparaison avec INT_MAX et la variable de comptage séparée, et je décrémenter la valeur fournie plutôt que d'utiliser une boucle for.

Je pourrais même faire:

while (k < 0 || k--) { 
    ... 
} 

Notez que si (k < 0) le décrément arrive jamais à cause du comportement de court-circuit de l'opérateur ||, vous obtenez une boucle infinie à moins que vous sortir de la boucle par votre exemple pour \n

si (k == 0) la boucle prendra fin immédiatement (nb: post-décrément plutôt que pré-décrément)

0

critique: vous formatage:

") {" avec un espace entre est plus lisible

parfois vous utilisez "instruction if (expression);" et parfois "if (expression) {statement;}". J'utiliserais toujours le "{".

« while (», « si (» on aussi avec un espace après le mot-clé.

+0

Je serais d'accord avec vous pour toujours utiliser le {} après un si, pendant que j'essaie pour me recycler hors de la mauvaise habitude de ne pas les utiliser sur des clauses de déclaration unique. Cependant, je devrais être en désaccord avec le ") {" vs ") {". J'ai déjà du mal à garder une longueur de ligne <80 caractères. – sdellysse

+0

garder à la norme (dans ce cas K & R "programmation en C") –

Questions connexes