1

Bonjour à tous, je vien de m'inscrire sur votre forum et je souhaiterai un peu d'aide au sujet d'une petite question en C que je me pose :

Affecter une valeur prédéfinie à un tableau reste simple je fait char TABLEAU[255]; et j'ai ainci un tableau de 255 composents.
Je voudrai que ce sois l'utilisateur qui définisse la dimension de mon tableau, je voudrai savoir comment faire cela ?

Merci à ceux qui pourront m'aider.

2

tu allous ton tableau en dynamique :

soit t la taille du tableau, en nombre de cases.
t entier, de type int, long, short, ou dans le genre
TYPE est le type de ce que tu veux mettre dans ton tableau

tu fais
TYPE *tab;

tab = malloc(t * sizeof(TYPE)); // aloue t cases pour le tableau
if(tab == NULL)
{
// allocation a foiré => message d'erreur
}

et à la fin du prog, tu libère ton tableau, avec un
free(tab);
pour que la mémoire soit dé-sallouée


sinon, en C++, tu utilise new et delete à la place de malloc et free.
avatar
Tutorial C (TI-89/92+/v200) - Articles Développement Web (PHP, Javascript, ...)
« What is the sound of Perl? Is it not the sound of a wall that people have stopped banging their heads against? » - Larry Wall

3

Tu peux utiliser alloca je crois, mais bon là je te conseille malloc.
char *tableau;
int dimension;
scanf("%i",&dimension);
tableau=malloc(dimension*sizeof(char));
if (!tableau)     //Pas pu allouer
{
  printf("Erreur de mémoire -> malloc(dimension)");
  return;
}
[...]
free(tableau);
Mais lis quand-même la documentation pour mieux comprendre. C'est un point important du langage C wink
[Edit]: Post croisé complètement identique! magic
[Edit]: Squale92 l'a quand-même mieux expliqué en fin de compte.
avatar
Highway Runners, mon jeu de racing à la Outrun qu'il est sorti le 14 décembre 2016 ! N'hésitez pas à me soutenir :)

https://itunes.apple.com/us/app/highway-runners/id964932741

4

En faite j'ai mieux compris avec ta version Brunni peu être le nom de tes variables chinois merci à vous 2 pour ces réponses rapides, je vais tester tout ça smile

5

Post croisé complètement identique!

grin
Squale92 l'a quand-même mieux expliqué en fin de compte.

c pas gagné grin
je suis rarement clair dans mes explications grin
(sauf qd je fais une explication complète sur un truc complet en prennant bien mon temps pour le faire... ce qui n'est pas le cas ici)

Smaug> de rien smile
avatar
Tutorial C (TI-89/92+/v200) - Articles Développement Web (PHP, Javascript, ...)
« What is the sound of Perl? Is it not the sound of a wall that people have stopped banging their heads against? » - Larry Wall

6

En C99, tu mets char TABLEAU[n]; tout simplement.
avatar
Mes news pour calculatrices TI: Ti-Gen
Mes projets PC pour calculatrices TI: TIGCC, CalcForge (CalcForgeLP, Emu-TIGCC)
Mes chans IRC: #tigcc et #inspired sur irc.freequest.net (UTF-8)

Liberté, Égalité, Fraternité

7

mon petit programme est abouti, j'aimerai savoir si il y aurai des choses à améliorer et ou a corriger, le programe est assez simple je saisie la dimension d'un premier tableau A, je saisie des valeurs en fonction de la dimension de A ensuite je saisie la dimension d'un tableau B, j'entre les valeurs idem.
Ensuite je colle le contenue de B à la suite de A et j'affiche le tableau A.
#include <stdio.h>

int main(int argc, char *argv[]) {

char *A;
char *B;
int N, M, i, j;

printf("Dimension du premier tableau : ");
scanf("%d", &N);
A=(char *)malloc(N);

for (i=0;i<N;i++) {
printf("Saisissez une valeur : ");
scanf("%d", &A[i]);
}

printf("Dimension du deuxième tableau : ");
scanf("%d", &M);
B=(char *)malloc(M);

for (i=0;i<M;i++) {
printf("Saisissez une valeur : ");
scanf("%d", &B[i]);
}

A=(char *)realloc(A,M);

for (i=N,j=0;i<N+M;i++,j++) {
*(A+i) = *(B+j);
}

free(B);

for (i=0;i<N+M;i++) {
if (*(A+i) != 0 ) {
printf("Affichage : %d\n", A[i]);
}
}
free(A); }

Comme je débute je ne maitrise pas encore l'ecriture en C, je reste ouvert à tout commentaires ;-)

8

salut
lors de la reallocation de la memoire du tableau A, tu fais:
Smaug :
A=(char*)realloc(A,M);

cela ne correspond pas a l utilisation que tu veux en faire : realloc alloue M bloc de memoire et n ajoute pas M bloc de memoire en plus a la zone deja allouee. En supposant par exemple que M<N, lors de ta boucle for, tu ecris des le premier pasage dans une zone non alloue => erreur!! ( il est meme etonant que ton compilateur ne t ai rien dit... )
Par contre si tu fais:
if( (A=(char*)realloc(A,M+N)) ==NULL)
fprintf(stderr,"\n !! il y une erreur lors de l allocation memoire !!\n");

tu alloue bien sufisament de memoire pour rajouter les element du tableau B a la suite du tableau A
De plus ici, je verifie que l allocation a bien pu se faire.
Le monde se separe en 10 categories de gens : ceux qui connaissent le binaire et ceux qui ne le connaissent pas.

9

l utilisation de scanf est deconseillee car elle attend une entree formattee ( le f du scanf signifie formate )
il est nettement plus conseille d utilise fgets car cette fonction prend en parametre le nombre de caractere lu et il est nettement plus facile de savoir si il reste des caractere dans le buffer. Apres tu utilise strloul
Le monde se separe en 10 categories de gens : ceux qui connaissent le binaire et ceux qui ne le connaissent pas.

10

Alors pour la réallocation de mémoire j'avais lu le man de malloc ou eux spécifient ceci :

realloc() modifie la taille du bloc de mémoire pointé par ptr pour
l'amener à une taille de size octets. realloc() conserve le contenu de
la zone mémoire minimum entre la nouvelle et l'ancienne taille. Le con-
tenu de la zone de mémoire nouvellement allouée n'est pas initialis
Si ptr est NULL, l'appel de realloc() est équivalent malloc(size).
Si size vaut zéro, l'appel est équivalent free(ptr). Si ptr n'est
pas NULL, il doit avoir été obtenu par un appel antèrieur malloc(),
calloc() ou realloc().

Pour moi cela fut assez claire le realloc(A,M) concerve la taille mémoire allouée préalablement, ce qui expliquerai donc que mon compilateur (GCC 3.3.3) ne me signale pas un tel problême.

Pour scanf je comprend tout à fait, mais fgets n'est pas normalement utilisé pour lire les caractères d'un fichier ?
strloul je connais pas je vais me renseigner merci pour tes explications beer

11

un man de realloc m as donne ca:
#include <stdlib.h>

void *realloc(void *ptr, size_t size);

The realloc() function changes the size of the block pointed
to by ptr to size bytes and returns a pointer to the (possi-
bly moved) block. The contents will be unchanged up to the
lesser of the new and old sizes. If ptr is NULL, realloc()
behaves like malloc() for the specified size. If size is 0
and ptr is not a null pointer, the space pointed to is is
made available for further allocation by the application,
though not returned to the system. Memory is returned to the
system only upon termination of the application.
ca signifie bien que la zone jusqu au minimum entre la nouvelle taille et l ancienne taille est conservee, mais pas que l ancienne zone est conservee!!. Ce doit etre lors de la traduction que le sens de la phrase n a pas ete vraiment respectee

tu as aussi oublie d inclure stdlib.h!



quant a la specification de strtoul:
unsigned long strtoul(const char *str, char **endptr, int
base);

The strtoul() function converts the initial portion of the
string pointed to by str to a type unsigned long int
representation. First it decomposes the input string into
three parts: an initial, possibly empty, sequence of white-
space characters (as specified by isspace(3C)); a subject
sequence interpreted as an integer represented in some radix
determined by the value of base; and a final string of one
or more unrecognised characters, including the terminating
null byte of the input string. Then it attempts to convert
the subject sequence to an unsigned integer, and returns the
result.
sa definition est dans sdtlib.h




fgets est utilise pour lire une seqence de caractere a pertir d un flux, pas forcement d un fichier, si tu fais
char tableau[ une_longueur ];
fgets(tab,sizeof(tab),stdin);
ca fonctionne correctement
Le monde se separe en 10 categories de gens : ceux qui connaissent le binaire et ceux qui ne le connaissent pas.

12

salut,
Alors j'ai suivi tes conseils qui m'ont bien aidé, et permit d'avancer.
Par contre J'ai rencontré certains bugs au niveau de realloc() pour le tableau A, le resultat m'affichait des nombres éronés à 2 emplacements du tableau, par exemple au lieu d'avoir une suite comme ...7 8 9 10 11 12... j'avais ...7 8 0 53 11 12 etc.., j'avais aussi un seg fault si B étais supérieur à A avec un certains nombres d'éléments et vice versa, je me suis un peu pris la tête à essayer divers methodes et j'ai fini une version qui ne comporte plus aucuns bugs à ma connaissance :
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {

int *A, *B, *TRAV;
char val[50];
int N, M, i, j;


printf("Dimension du premier tableau : ");
fgets(val, sizeof(val), stdin);
N = atoi(val);
A=malloc(N*sizeof(int));
fflush(stdin);

for (i=0;i<N;i++) {
printf("Saisissez une valeur : ");
fgets(val, sizeof(val), stdin);
*(A+i) = atoi(val);
fflush(stdin);
}

printf("Dimension du deuxième tableau : ");
fgets(val,sizeof(val), stdin);
M = atoi(val);
B=malloc(M*sizeof(int));
fflush(stdin);

for (i=0;i<M;i++) {
printf("Saisissez une valeur : ");
fgets(val, sizeof(val), stdin);
*(B+i) = atoi(val);
fflush(stdin);
}

if ((TRAV=malloc(N*sizeof(int))) == NULL) {
fprintf(stderr, "\n !! il y a une erreur lors de l'allocation de TRAV\n");
};

/*Je sauve le contenu de A dans TRAV*/
for (i=0;i<=N;i++) {
*(TRAV+i) = *(A+i);
}

/*Et j'alloue les DIMS N et M a A*/
A=malloc(N+M*sizeof(int));

/*Je fini par mettre le backup de TRAV dans le tableau A*/
for (i=0;i<N;i++) {
*(A+i) = *(TRAV+i);
}

/*Copie du tableau "B" dans tableau "A"*/
for (i=N,j=0;i<N+M;i++,j++) {
*(A+i) = *(B+j);
}

/*Libère le buffer de B*/
free(B);

for (i=1;i<N+M;i++) {
printf("Affichage : %d\n", *(A+i));
}
free(A);
}


merci pour l'aide ! chinois

13

salut

flush n est defini que pour des flux sortant, c est a dire que, par exemple:
fflush(stdout);
fflush(stderr);
sont correct, par contre
fflush(stdin);
n est pas defini et depent des implantations, donc n est pas portable!!


d apres la specification de ta fonction main, ton programme renvoie un entier ( int main(...) ), il faut donc en renvoyer un, a la fin de ton programme met:
return 0;
OU
exit(EXIT_SUCCESS);



j ai pas bien compris a quoi sert TRAV, tu peux utiliser le meme prinipe que ton premier programme, c et dire que tu realloue A puis que tu copie B dans A... De plus la zone memoire allouee a TRAV n est pas liberee a la fin de ton programme!!

dans la boucle for ou tu sauvegarde le contenue de a dans trav, tu quitte la boucle si i<=N, c est pas bon, il faut quitter si i<N:
for(i=0,i<N,i++){...}
Il y a une erreur de meme genre dans la boucle d affichage: tu initialise i a 1 et pas a 0...


comme tu doit le savoir, l operateur '*' est prioritaire sur l operateur '+', quand tu alloue la deuxieme fois de la memoire a A, il faut mettre
A=malloc((N+M)*sizeof(int))



il vaut mieux utiliser strtoul et sa famille plutot que atoi, la gestion des erreur est plus simple! atoi renvoie 0 si il y a une erreur, il est donc dificile de savoir si il a eu une erreur ou si l utilisateur a rentre la valeur 0, tandis que strtoul utilise un pointeur qui vaut NULL si il n y a pas eu d erreur ou qui pointe sur le caractere qui n est pas correct, si il y en a un.
Le monde se separe en 10 categories de gens : ceux qui connaissent le binaire et ceux qui ne le connaissent pas.