Je travaille sur un devoir qui lit un fichier texte et ajoute un numéro de ligne au début de chaque ligne.
Je suis assez nouveau dans le codage donc je suis désolé si c'est une tâche simple. Le code que j'ai écrit me donnera une sortie qui me dira combien de lignes sont dans le fichier, mais je ne peux pas comprendre comment le faire numéroter les lignes et me les montrer.
000001 This is a text file 000002 This text file has words in it.
Exemple d'entrée:
This is a text file This text file has words in it.
Exemple de sortie:
//lineNumber = 1;
//Open the file
//While ((c = read a character) is not EOF)
// If (c is \n)
// Print "lineNumber", then increment it
// Print c
//End while
//Close the file
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main() {
int ln = 1;
char c;
FILE *fp = fopen("text.txt", "r");
while((c=getc(fp))!=EOF) {
if (c=='\n'){
ln++;
}
}
printf("lines num: %d",c);
fclose(fp);
//return 0;
}
p>
4 Réponses :
vous avez un programme qui compte le nombre de lignes dans le fichier, vous devez le changer pour qu'au lieu d'afficher le nombre à la fin, vous deviez faire écho au contenu du fichier
(par exemple en utilisant putchar (c); après chaque getc ()) et
à chaque fois que vous voyez un \ n (et aussi au début du fichier)
vous devez imprimer un nombre avec des zéros non significatifs, puis un espace.
printf ("% 06d", ln); est probablement ce que vous voulez pour cela.
Vous avez un grand nombre de petits problèmes à résoudre. Premièrement, sauf si vous utilisez un compilateur non conforme, les déclarations conformes pour main sont int main (void) et int main (int argc, char ** argv) (que vous verrez écrit avec l'équivalent char * argv [] ). Voir: C11 Standard §5.1.2.2.1 Démarrage du programme p1 (brouillon n1570) . Voir aussi: Que doit renvoyer main () en C et C ++?
Ensuite, c doit être de type int pas de type char pour correspondre à EOF , par exemple
$ ./bin/linenos ../dat/captnjack_noeol.txt 000001 This is a tale 000002 Of Captain Jack Sparrow 000003 A Pirate So Brave 000004 On the Seven Seas.
Don ' t coder en dur les noms de fichiers ou utiliser des nombres magiques . Soit passez le nom de fichier comme argument à main () , soit demandez-le dans votre programme. Vous pouvez facilement prendre un nom de fichier à ouvrir ou à lire à partir de stdin par default avec l'opérateur ternaire comme suit:
$ cat ../dat/captnjack.txt This is a tale Of Captain Jack Sparrow A Pirate So Brave On the Seven Seas.
Enfin pour votre code, puisque vous voulez Préfixer chaque ligne avec le numéro de ligne, vous devez sortir le numéro de ligne de la première ligne Avant de sortir les caractères de cette ligne ( et la même chose pour chaque ligne suivante). Vous pouvez le faire simplement en produisant d'abord le nombre (en utilisant le spécificateur de conversion "% 06zu" avec les modificateurs '0' pour afficher les zéros non significatifs et le champ largeur 6 pour correspondre à votre format affiché). Notez également que le type de votre compteur ln est passé de int à size_t , le type recommandé pour les compteurs en C (vous ne pouvez pas nombre de lignes négatif).
En associant ceci à l'utilisation du dernier caractère pour permettre de vérifier le '\ n' avant de sortir vos caractères , vous pouvez faire:
#include <stdio.h>
int main (int argc, char **argv) {
int c, last = 0; /* c must be type int, not char to match EOF */
size_t ln = 1; /* use size_t for counters */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
printf ("%06zu ", ln++); /* output line 1 number */
while ((c = getc(fp)) != EOF) { /* read each character */
if (last) /* test if last set */
putchar (last); /* output all characters */
if (last == '\n') /* test if last is newline */
printf ("%06zu ", ln++); /* output next line number */
last = c; /* set last to c */
}
putchar (last); /* output final character */
if (last != '\n') /* check POSIX eof */
putchar('\n'); /* tidy up with newline */
if (fp != stdin) /* close file if not stdin */
fclose (fp);
return 0;
}
( remarque: la vérification de if (last! = '\ n') après avoir quitté la boucle vérifie la présence d'une ligne POSIX se terminant sur la dernière ligne, et sinon, vous devez afficher manuellement un '\ n' afin que votre programme soit compatible POSIX)
Exemple de fichier d'entrée
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
Exemple d'utilisation / de sortie
int c, last = 0; /* c must be type int, not char to match EOF */
Pour numéroter les lignes, ou pour modifier n'importe quelle partie du fichier d'ailleurs, il est préférable de charger le fichier en mémoire sous forme de chaîne, de manipuler cette chaîne (dans ce cas, d'ajouter des numéros de ligne) puis de créer un espace nouveau fichier. Copiez la chaîne modifiée dans le nouveau fichier, puis renommez-la avec le chemin de l'ancien, afin de l'écraser.
/* fputs(numbered, fpNumbered); */ printf("%s", numbered);
Si vous voulez seulement imprimer les lignes numérotées sans même toucher le fichier, puis vous remplacez l'instruction fputs dans le code ci-dessus par un appel à printf:
/* fp: File whose lines are to be numbered
pathOld: Its path */
void giveLineNos(FILE *fp, const char *pathOld)
{
char line[MAXLINE]; /* line that is read in */
char numbered[MAXLINE + 8]; /* line that will include its number */
int i;
char tempName[L_tmpnam];
tmpnam(tempName); /* generate filename guaranteed to be unique */
FILE *fpNumbered = fopen(tempName, "w"); /* create temporary file onto
which we will write; error checking omitted */
for (i = 0; fgets(line, MAXLINE, fp) != NULL; ++i) {
/* write out the line number followed by its contents */
snprintf(numbered, MAXLINE + 8, "%d: ", i + 1);
strcat(numbered, line);
fputs(numbered, fpNumbered); /* save line to file */
}
rename(tempName, pathOld); /* rename the temporary file to that of
the old one, thereby overwriting it */
fclose(fpNumbered);
fclose(fp);
}
(mettant une nouvelle ligne après % s est erronée car fgets met déjà une nouvelle ligne dans le tampon ligne , qui est ensuite transférée dans numérotée .)
Notez également que votre main n'est pas standard. Utilisez int comme type de retour, et non void.
Je recommande de ne pas incrémenter le nombre de lignes avec chaque '\ n' et d'incrémenter à la place le nombre de lignes chaque fois qu'un caractère est lu après un ' \ n '. C'est aussi à ce moment que le code doit imprimer le numéro de ligne
unsigned long ln = 0;
int prev = '\n';
int c; // Use int here, not char
while((c=getc(fp))!=EOF) {
if (prev == '\n'){
printf("%06lu ", ++ln);
}
putchar(c);
prev = c;
}
if (prev != '\n') {
putchar('\n'); // print a \n for input that lacks a final \n
}
printf("lines num: %lu\n", ln);
Remarquez que ce qui précède fonctionne bien lorsqu'il y a 0 ligne (pas de données) et lorsque l'entrée ne se termine pas par un '\ n '.
Une faiblesse courante de l'utilisation de fgets () est 1) lorsque la longueur de la ligne dépasse le tampon d'entrée, un traitement spécial est nécessaire 2) lorsque l'entrée contient de manière inattendue un caractère nul , ce qui nuit à la gestion des chaînes tropicales. getchar () n'a pas ces problèmes.
printf ("lines num:% d", c);pourquoi passez-vous le caractère dans le fichier (c)? Vous voulez passer la variablelnici.Si vous traitez des lignes, utilisez
fgets ()(ou POSIXgetline ()) pour lire des lignes entières (assurez-vous que le tampon est grand - 4 Kio est à peu près correct) . Il est alors trivial d’imprimer les numéros de ligne au début d’une ligne. A défaut, gardez une trace du numéro de colonne: imprimez le numéro de ligne après avoir lu un caractère lorsque le numéro de colonne est zéro, puis incrémentez le numéro de colonne. Lorsque vous lisez une nouvelle ligne, réinitialisez le numéro de colonne à zéro après avoir imprimé le caractère.J'aborderais cela avec la fonction
fgets (), mais qui pourrait ne pas lire une ligne entière. Si la chaîne d'entrée a un retour à la ligne final, il s'agit d'une ligne entière ou de la dernière partie d'une ligne interrompue, vous incrémenterez donc le numéro de ligne. La dernière ligne d'un fichier texte peut ne pas se terminer par une nouvelle ligne, mais cela n'a pas d'importance car il n'y aura pas d'autre numéro de ligne à imprimer.Est-ce que le pseudo-code en haut du fichier vous a été donné par l'enseignant comme moyen de l'implémenter?
@ChrisWhite - le pseudo-code est bogué: il n'imprime pas le numéro de ligne pour la première ligne de sortie.
D'accord, mais nous ne voulons pas suggérer quelque chose (fgets) qui pourrait ne pas faire partie de la mission.
Je ne traiterais pas des lignes entières. Vous n'en avez pas besoin. Vous n'avez besoin de lire qu'un caractère à la fois. Commencez par écrire "00001". Ensuite, lisez un caractère à la fois et imprimez-le. (Utilisez getchar, pas fgets). Si ce caractère est une nouvelle ligne, imprimez le numéro de ligne suivant. N'essayez pas non plus de réécrire dans le même fichier. Mettez toute votre sortie dans un fichier différent, puis renommez le fichier à la fin. (Ou (de préférence IMO) ne manipulez pas du tout les fichiers: lisez stdin et écrivez stdout. Faites toutes les manipulations de fichiers dans le shell lorsque vous appelez votre programme.)
oui, c'est totalement inutile, putchar () de putc () est suffisant et c'est probablement déjà appris. l'impression sur stdout peut être suffisante, vérifiez le libellé de l'affectation. la modification de l'entrée est compliquée et rend les tests plus difficiles.
Notez qu'une ligne peut se terminer par 0x0A, 0x0D, 0x0A 0x0d, 0x0D 0x0A, 0x0B, 0x0C si le texte est en ASCII et 0x85, 0xE2,0x80,0xA8 (0x2028) ou 0xE2,0x80,0xA9 (0x2029) si c'est encodé en UTF-8.
@some, en supposant que le code ci-dessus compte correctement le nombre de lignes, il n'est probablement pas nécessaire de traiter l'unicode. aussi ces points de code semblent se rapporter au "formatage du document" plutôt qu'aux "fichiers texte".