2009-04-10 12 views
10

J'apprends le C en tant que première langue, et je voulais juste vous demander, si vous pensiez que cet exercice était résolu de la bonne façon, je suis conscient que ce n'est probablement pas aussi complet que vous le feriez comme, mais je voulais des vues, donc je saurais que j'apprends bien.K & R Chapitre 1 - Exercice 22 solution, qu'en pensez-vous?

Merci

/* Exercise 1-22. Write a program to "fold" long input lines into two or 
* more shorter lines, after the last non-blank character that occurs 
* before then n-th column of input. Make sure your program does something 
* intelligent with very long lines, and if there are no blanks or tabs 
* before the specified column. 
* 
* ~svr 
* 
* [NOTE: Unfinished, but functional in a generic capacity] 
* Todo: 
* Handling of spaceless lines 
* Handling of lines consisting entirely of whitespace 
*/ 

#include <stdio.h> 
#define FOLD 25 
#define MAX 200 
#define NEWLINE '\n' 
#define BLANK ' ' 
#define DELIM 5 
#define TAB '\t' 

int 
main(void) 
{ 
    int line = 0, 
     space = 0, 
     newls = 0, 
      i = 0, 
      c = 0, 
      j = 0; 

    char array[MAX] = {0}; 

    while((c = getchar()) != EOF) { 
     ++line; 
     if(c == NEWLINE) 
      ++newls; 
     if((FOLD - line) < DELIM) { 
      if(c == BLANK) { 
       if(newls > 0) { 
        c = BLANK; 
        newls = 0; 
       } 
       else 
        c = NEWLINE; 
       line = 0; 
      } 
     } 
     array[i++] = c; 
    } 
    for(line = 0; line < i; line++) { 
     if(array[0] == NEWLINE) 
      ; 
     else 
      printf("%c", array[line]); 
    } 
    return 0; 
} 
+0

Peut-être que vous devriez résoudre vos propres devoirs a ssignments? –

+1

@Phil: Je pense qu'il l'a fait ... ça ou l'énorme bloc de code était criblé. – Shog9

+0

@Phil, il y a un grand précédent pour les gens qui posent des questions à la maison tant qu'ils ont fait un effort. Et vous ne savez pas vraiment que c'est les devoirs, @svr peut être autodidacte. C'est certainement mieux que les clowns qui ont juste coupé et collé leur question de devoirs verbatim. – paxdiablo

Répondre

0

Un problème évident est que vous allouez statiquement « array » et ne jamais vérifier les limites d'index tout en y accédant. Débordement de tampon en attente de se produire. En fait, vous ne réinitialisez jamais la variable i dans la première boucle, donc je suis un peu confus sur la façon dont le programme est censé fonctionner. Il semble que vous stockez l'entrée complète en mémoire avant de l'imprimer sous forme de mot? Donc, suggestions: fusionnez les deux boucles ensemble et imprimez la sortie pour chaque ligne que vous avez complétée. Ensuite, vous pouvez réutiliser le tableau pour la ligne suivante.

Oh, et de meilleurs noms de variables et quelques commentaires. Je n'ai aucune idée de ce que 'DELIM' est censé faire.

0

Il semble (sans test) que cela puisse fonctionner, mais cela semble plutôt compliqué.

Voici quelques pseudocode pour ma première pensée

const int MAXLINE = ?? — maximum line length parameter 
int chrIdx = 0 — index of the current character being considered 
int cand = -1 — "candidate index", Set to a potential break character 
char linebuf[bufsiz] 
int lineIdx = 0 — index into the output line 
char buffer[bufsiz] — a character buffer 
read input into buffer 
for ix = 0 to bufsiz -1 
do  
    if buffer[ix] == ' ' then 
     cand = ix 
    fi 
    linebuf[lineIdx] = buffer[ix] 
    lineIdx += 1 
    if lineIdx >= MAXLINE then 
     linebuf[cand] = NULL — end the string 
     print linebuf 
     do something to move remnants to front of line (memmove?) 
    fi 
od 

Il est tard et je viens d'avoir une ceinture, donc il peut y avoir des défauts, mais il montre l'idée générale - charger un tampon, et copiez le contenu du tampon à un tampon de ligne, en gardant une trace des points de rupture possibles. Lorsque vous approchez de la fin, utilisez le point d'arrêt.

7

Je suis sûr que vous sur la piste rigth, mais quelques conseils pour une meilleure lisibilité:

  • commentaire vos trucs
  • nom des variables correctement et au moins donner une description si vous refusez
  • être conséquente , une ligne unique si vous utilisez et d'autres pas. (AMHA, utilisez toujours {} il est donc plus lisible)
  • l'instruction if dans la dernière boucle for peut être mieux, comme

    if(array[0] != NEWLINE) 
    { 
     printf("%c", array[line]); 
    } 
+0

@Mafti: Je vais suivre toutes vos suggestions; c'était un premier brouillon, juste pour voir si je l'avais appris, d'une manière un peu élégante. Tu as raison à propos de la dernière séquence en boucle, je devrais probablement savoir mieux l'écrire en tant que tel. Merci –

2

Ce n'est pas bon à mon humble avis.

D'abord, il ne fait pas ce qu'on vous demandait. Vous étiez censé trouver le dernier blanc après un non vide avant la limite de la ligne de sortie. Votre programme n'essaie même pas de le faire à distance, il semble chercher à trouver le premier caractère vide après (marge - 5) (d'où vient le 5 - et si tous les mots avaient 9 lettres?). Cependant, il ne le fait pas non plus, à cause de votre manipulation avec la variable newls. En outre, cela:

for(line = 0; line < i; line++) { 
    if(array[0] == NEWLINE) 
     ; 
    else 
     printf("%c", array[line]); 
} 

est probablement faux, car vous vérifiez une condition qui ne change jamais tout au long de la boucle.

Et, last but not least, le stockage du fichier entier dans un tampon de taille fixe n'est pas bon, à cause de deux raisons:

  • le tampon est lié à débordement sur des fichiers volumineux
  • même si il ne déborderait jamais, les gens ne vous aimeraient toujours pas pour le stockage par exemple. un fichier gigaoctet en mémoire juste pour le couper en blocs de 25 caractères

Je pense que vous devriez recommencer, repenser votre algorithme (y compris les cas de coin), et seulement après cela, commencer le codage. Je vous suggère:

    processus
  • la ligne par ligne fichier (ce qui signifie lignes de sortie)
  • stocker la ligne dans un tampon assez grand pour contenir la plus grande ligne de sortie
  • recherche du personnage que vous aurez briser à dans le tampon
  • puis l'imprimer (indice: vous pouvez mettre fin à la chaîne avec « \ 0 » et imprimer avec printf("%s", ...)), copier ce que vous ne l'avez pas l'impression au début du tampon, procéder de cette