J'ai essayé d'obtenir les entrées (chaînes) de l'utilisateur et de les stocker dans un tableau.Mais après avoir exécuté ce code, le programme s'est immédiatement écrasé.
#include <stdio.h>
int main() {
int i;
char *Word[3];
for(i=0;i<3;i++)
{
printf(" Enter a Word: ");
scanf("%s", &Word[i]);
}
printf("%s ", Word[0]);
return 0;
}
Il semble y avoir un peu de confusion dans ce domaine. Votre principal problème est que vous essayez d'écrire chaque mot à l'adresse de de chacun des pointeurs que vous déclarez avec char *Word[3];
. (pour ne pas mentionner que vous n'avez pas de mémoire allouée à l'emplacement indiqué par chaque pointeur - mais vous n'y arrivez jamais car vous essayez d'écrire à l'adresse de chaque pointeur avec plutôt &Word[i]
que le pointeur lui-même)
Bien que vous puissiez utiliser scanf
, vous rencontrerez rapidement l’un des nombreux écueils liés à la saisie de l’utilisateur avec scanf
qui gênera tous les nouveaux programmeurs C (par exemple ne pouvant pas gérer le '\n'
laissé dans le tampon d’entrée , ne parvient pas à gérer les espaces dans les chaînes , ne limite pas le nombre de caractères lus/écrits , échec de la validation de la lecture ou du traitement de EOF , etc ... )
Une meilleure approche consiste simplement à utiliser fgets
et à couper le '\n'
que fgets
lit et inclut dans le tampon dans lequel il stocke la chaîne. Un exemple simple serait:
#include <stdio.h>
#include <string.h>
#define NWDS 3 /* declare a constant for the maximum number of words */
int main (void) {
int i, n = 0;
char Word[NWDS][50] = { "" }; /* provide storage or allocate */
for (i = 0; i < NWDS; i++) { /* for a max of NWDS */
printf ("Enter Word : "); /* Prompt */
if (!fgets (Word[i], sizeof Word[i], stdin)) /* read/validate */
break; /* protect against EOF */
size_t len = strlen (Word[i]); /* get length */
if (Word[i][len-1] == '\n') /* check for trailing '\n' */
Word[i][--len] = 0; /* overwrite with nulbyte */
}
n = i; /* store number of words read */
putchar ('\n'); /* make it pretty */
for (i = 0; i < n; i++) /* output each Word read */
printf (" Word[%d] : %s\n", i, Word[i]);
#if (defined _WIN32 || defined _WIN64)
getchar(); /* keep terminal open until keypress if on windows */
#endif
return 0;
}
Allez-y et annulez la saisie à tout moment en générant un EOF
lors de la saisie (ctrl + d sur Linux ou ctrl + z sur windoze), vous êtes couvert.
Exemple d'utilisation/sortie
$ ./bin/wordsread
Enter Word : first Word
Enter Word : next Word
Enter Word : last Word
Word[0] : first Word
Word[1] : next Word
Word[2] : last Word
Examine les choses, examine les autres réponses et fais-moi savoir si tu as d'autres questions.
Dans cette ligne:
scanf("%s", &Word[i]);
Vous devez vous assurer que Word[i]
pointe quelque part et a suffisamment d’espace pour occuper la chaîne entrée. Puisque Word[i]
est un pointeur char *
, vous devez allouer de la mémoire pour cela à un moment donné. Sinon, il s’agit simplement d’un pointeur suspendu ne pointant nulle part.
Si vous souhaitez vous en tenir à scanf()
, vous pouvez au préalable allouer de l'espace avec malloc
.
malloc()
alloue la mémoire demandée sur le tas, puis retourne un pointeurvoid*
à la fin.
Vous pouvez appliquer malloc()
dans votre code comme ceci:
size_t malloc_size = 100;
for (i = 0; i < 3; i++) {
Word[i] = malloc(malloc_size * sizeof(char)); /* allocates 100 bytes */
printf("Enter Word: ");
scanf("%99s", Word[i]); /* Use %99s to avoid overflow */
/* No need to include & address, since Word[i] is already a char* pointer */
}
Remarque: Doit vérifier la valeur renvoyée de malloc()
, car il peut renvoyer NULL
en cas d'échec.
De plus, chaque fois que vous allouez de la mémoire avec l'utilisation de malloc()
, vous devez utiliser free
pour libérer la mémoire demandée à la fin:
free(Word[i]);
Word[i] = NULL; /* safe to make sure pointer is no longer pointing anywhere */
Une manière plus appropriée de lire les chaînes devrait être avec fgets
.
char *fgets(char *str, int n, FILE *stream)
lit une ligne à partir d'un flux d'entrée et copie les octets danschar *str
, auquel doit être attribué une taille den
octets comme seuil d'espace qu'il peut occuper.
Ce qu'il faut noter à propos de fgets:
\n
à la fin du tampon. Peut être enlevé facilement.NULL
. Si aucun caractère n'est lu, retourne quand même NULL
à la fin.n
.stdin
ou FILE *
. Voici un exemple d'utilisation de cette option pour lire une ligne d'entrée de stdin
:
char buffer[100]; /* statically declared buffer */
printf("Enter a string: ");
fgets(buffer, 100, stdin); /* read line of input into buffer. Needs error checking */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NUMSTR 3
#define BUFFSIZE 100
int main(void) {
char *words[NUMSTR];
char buffer[BUFFSIZE];
size_t i, count = 0, slen; /* can replace size_t with int if you prefer */
/* loops only for three input strings */
for (i = 0; i < NUMSTR; i++) {
/* read input of one string, with error checking */
printf("Enter a Word: ");
if (fgets(buffer, BUFFSIZE, stdin) == NULL) {
fprintf(stderr, "Error reading string into buffer.\n");
exit(EXIT_FAILURE);
}
/* removing newline from buffer, along with checking for overflow from buffer */
slen = strlen(buffer);
if (slen > 0) {
if (buffer[slen-1] == '\n') {
buffer[slen-1] = '\0';
} else {
printf("Exceeded buffer length of %d.\n", BUFFSIZE);
exit(EXIT_FAILURE);
}
}
/* checking if nothing was entered */
if (!*buffer) {
printf("No string entered.\n");
exit(EXIT_FAILURE);
}
/* allocate space for `words[i]` and null terminator */
words[count] = malloc(strlen(buffer)+1);
/* checking return of malloc, very good to do this */
if (!words[count]) {
printf("Cannot allocate memory for string.\n");
exit(EXIT_FAILURE);
}
/* if everything is fine, copy over into your array of pointers */
strcpy(words[count], buffer);
/* increment count, ready for next space in array */
count++;
}
/* reading input is finished, now time to print and free the strings */
printf("\nYour strings:\n");
for (i = 0; i < count; i++) {
printf("words[%zu] = %s\n", i, words[i]);
free(words[i]);
words[i] = NULL;
}
return 0;
}
Exemple d'entrée:
Enter a Word: Hello
Enter a Word: World
Enter a Word: Woohoo
Sortie:
Your strings:
words[0] = Hello
words[1] = World
words[2] = Woohoo
Vous déclarez Word en tant que tableau de pointeur (char * Word [3];). Vous devez allouer de la mémoire pour stocker des données. Allouez la mémoire avec malloc ou des fonctions similaires avant d'attribuer des valeurs.
char *Word[3]; // <-- this is an array of 3 dangling pointers, of type char*
// they still point nowhere, we later need to set them to some allocated location.
...
for(i=0;i<3;i++) {
Word[i] = malloc(some_max_size * sizeof(char)); // <-- allocate space for your Word
printf(" Enter a Word: ");
scanf("%s", Word[i]); // <-- not &Word[i]; Word[i] is already a char* pointer
}
Oui, le code se bloque parce que déclarer un tableau de pointeurs de caractères Ne suffit pas, vous devez configurer les pointeurs pour qu'ils pointent Vers la mémoire où les chaînes peuvent être stockées.
Par exemple.
const int maxLen = 32;
char* Word[3] = {NULL,NULL,NULL};
Word[i] = malloc(maxLen);
lisez ensuite la chaîne sur le clavier pour vous assurer qu'elle n'est pas trop long use fgets et maxLen:
printf("Enter a Word:");
fgets(Word[i],maxLen,stdin);