Remplacer:
for (int i = 0; i < 50; i++) {
for (int k = 0; k < 50; k++) {
fscanf(cola, "%c", &buff);
array[i][k] = buff;
}
}
avec:
for (int i = 0; i < 50; i++) {
for (int k = 0; k < 50; k++) {
int c = getc(cola);
if (c == EOF)
break;
array[i][k] = c;
}
}
Depuis buff
est alors utilisé, ne définissent pas. Notez que le type de retour de getc()
est un int
, pas seulement un char
. Vérifiez toujours la fonction d'E/S pour le succès/l'échec. Dans votre code d'origine, vous ne vérifiez même pas si l'opération d'E/S réussit, ce qui rend la détection d'EOF impossible.
Notez que ce code fait un certain nombre d'hypothèses qui peuvent ou ne peuvent pas être justifiables. Par exemple, vous supposez que chaque ligne du fichier comprend 49 caractères plus un saut de ligne; vous supposez également que vous n'aurez jamais besoin d'imprimer les informations sous la forme d'une 'chaîne' (votre code existant ne le fait pas, il imprime les caractères par caractère, donc c'est 'sûr').
Vous pouvez décrire l'entrée comme:
- lire jusqu'à 50 lignes avec un maximum de 49 caractères plus un saut de ligne dans chaque ligne, stocker le résultat dans la
array
variable chaque ligne étant un caractère nul chaîne terminée.
Ceci résiste mieux aux problèmes courants (lignes courtes, longues lignes, lignes insuffisantes). Le code pour ce pourrait être:
enum { LINE_LEN = 50, NUM_LINES = 50 };
char array[NUM_LINES][LINE_LEN];
int i;
for (i = 0; i < LINE_LEN; i++)
{
int c;
int k;
for (k = 0; k < LINE_LEN; k++)
{
c = getc(cola);
if (c == EOF || c == '\n')
break;
if (k == LINE_LEN - 1)
{
/* Too long - gobble excess */
while ((c = getc(cola)) != EOF && c != '\n')
;
break;
}
array[i][k] = c;
}
array[i][k] = '\0';
if (c == EOF)
break;
}
int num_lines = i; // You have num_lines lines of data in your array
J'ai trouvé une version de l'image de l'art ASCII Coca Cola ™ à https://www.ascii-code.com/ascii-art/logos/coca-cola.php qui ressemble à ce que vous avez dans vos images, mais il y a beaucoup d'autres sources et variantes:
__ ___ __ .ama ,
,d888a ,d88888888888ba. ,88"I) d
a88']8i a88".8"8) `"8888:88 " _a8'
.d8P' PP .d8P'.8 d) "8:88:baad8P'
,d8P' ,ama, .aa, .ama.g ,mmm d8P' 8 .8' 88):888P'
,d88' d8[ "8..a8"88 ,8I"88[ I88' d88 ]IaI" d8[
a88' dP "bm8mP8'(8'.8I 8[ d88' `" .88
,88I ]8' .d'.8 88' ,8' I[ ,88P ,ama ,ama, d8[ .ama.g
[88' I8, .d' ]8, ,88B ,d8 aI (88',88"8) d8[ "8. 88 ,8I"88[
]88 `888P' `8888" "88P"8m" I88 88[ 8[ dP "bm8m88[.8I 8[
]88, _,,aaaaaa,_ I88 8" 8 ]P' .d' 88 88' ,8' I[
`888a,. ,aadd88888888888bma. )88, ,]I I8, .d')88a8B ,d8 aI
"888888PP"' `8""""""8 "888PP' `888P' `88P"88P"8m"
La plus longue ligne de ce fichier est la première à 67 caractères plus le retour à la ligne; le plus court est de 61 caractères plus newline. Le fichier n'a que 13 lignes et 845 caractères (fins de ligne LF) au total. Ainsi, votre programme est mal équipé pour traiter ce fichier de données particulier. Il cherche 2 500 caractères et ne les obtiendra pas.
Mon code de test complet a été configuré pour lire à partir de l'entrée standard, plutôt que d'un nom de fichier fixe.
#include <stdio.h>
int main(void)
{
FILE *cola = stdin;
enum { LINE_LEN = 80, NUM_LINES = 50 };
char array[NUM_LINES][LINE_LEN];
int i; // Need value of i after loop
for (i = 0; i < NUM_LINES; i++)
{
int c; // Need value of c after loop
int k;
for (k = 0; k < LINE_LEN; k++)
{
c = getc(cola);
if (c == EOF || c == '\n')
break;
if (k == LINE_LEN - 1)
{
/* Too long - gobble excess */
while ((c = getc(cola)) != EOF && c != '\n')
;
break;
}
array[i][k] = c;
}
array[i][k] = '\0';
if (c == EOF)
break;
}
int num_lines = i; // You have num_lines lines of data in your array
for (i = 0; i < num_lines; i++)
puts(array[i]);
return 0;
}
Je l'ai testé sur le fichier de données représenté, avec une ligne vide à la fin, et avec quelques lignes contenant plus de 79 caractères après la ligne blanche. Il a correctement géré tous ces cas spéciaux. Notez que la gestion des entrées utilisateur est difficile; La gestion de l'entrée perverse de l'utilisateur est plus difficile. Le code est moins compact. Vous pouvez modifier les règles, puis modifier le code pour correspondre. Je ne suis pas sûr que ce soit la manière la plus minime de coder ceci; ça marche, cependant.Il pourrait être préférable d'avoir une fonction pour gérer la boucle d'entrée interne; la boucle externe pourrait tester la valeur de retour de cette fonction. Cela permettrait de réduire la manipulation de cas spéciaux.
#include <assert.h>
#include <limits.h>
#include <stdio.h>
static int read_line(FILE *fp, size_t buflen, char *buffer)
{
assert(buflen < INT_MAX);
int c; // Need value of c after loop
size_t k; // Need value of k after loop
for (k = 0; k < buflen; k++)
{
if ((c = getc(fp)) == EOF || c == '\n')
break;
if (k == buflen - 1)
{
/* Too long - gobble excess */
while ((c = getc(fp)) != EOF && c != '\n')
;
break;
}
buffer[k] = c;
}
buffer[k] = '\0';
return (k == 0 && c == EOF) ? EOF : (int)k;
}
int main(void)
{
enum { LINE_LEN = 80, NUM_LINES = 50 };
char array[NUM_LINES][LINE_LEN];
int i;
for (i = 0; i < NUM_LINES; i++)
{
if (read_line(stdin, LINE_LEN, array[i]) == EOF)
break;
}
int num_lines = i;
for (i = 0; i < num_lines; i++)
puts(array[i]);
return 0;
}
Ceci produit la même sortie à partir de la même entrée que la version précédente.
S'il vous plaît ne publiez pas les images de votre code. Au lieu de cela, créez un bloc de code qui inclut le code réel. –
Vérifiez la valeur de retour de 'fscanf'. – BLUEPIXY
J'ai édité maintenant mon message. –