#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*********************************************************************
NAME : wipestring( string )
USAGE : Wipe useless values from the string...
PARAMETERS : char const *string to wipe...
*********************************************************************/
void
wipestring (char const *string)
{
char *p = strchr (string, 'n');
if (p)
{
*p = ' ';
}
else
{
int c;
while ((c = getchar ()) != 'n' && c != EOF)
{
}
}
}
/*********************************************************************
NAME : verify ( string, size, function_name )
USAGE : verify if the user input is correct
PARAMETERS :
- The string to check and to fill if the user enter something
- The size of the string
- The name of the function to give accurate error messages
RETURNS :
- EXIT_SUCCESS
- EXIT_FAILURE
*********************************************************************/
int
verify (char *string, size_t size, const char *function_name)
{
/* The error number */
int err = EXIT_SUCCESS;
/* Check if there's an input */
if (fgets (string, (int) size, stdin) == NULL)
{
printf ("Input Error at %sn", function_name);
err = EXIT_FAILURE;
}
/* Check if the user entered something */
else
{
wipestring (string);
if (*string == ' ')
{
printf ("No input at %sn", function_name);
err = EXIT_FAILURE;
}
}
return err;
}
/*********************************************************************
NAME : takeadress ( address, size, name )
PARAMETERS :
- The address
- The size of this string
- Its name
RETURNS : See verify()
*********************************************************************/
int
takeadress (char *address, size_t size, const char *name)
{
/* The return value */
int ret = 0;
(void) printf ("Please enter the address of the person : ");
(void) fflush (stdout);
ret = verify (address, size, name);
/* Check if the value is correct */
(void) printf ("The address is %sn", address);
return ret;
}
/*********************************************************************
NAME : take_postalcode ( name )
PARAMETERS : Name of the function.
RETURNS : The postal code entered by the user
*********************************************************************/
int
take_postalcode (const char *name)
{
/* The postal code */
unsigned int postal_code = 0;
/* User input */
char input[10];
/* Ask the postal code until the user gives one */
do
{
(void) printf ("Insert the postal code of the user city : ");
(void) fflush (stdout);
if (verify (input, sizeof (input), name) == EXIT_FAILURE)
{
postal_code = 0;
break;
}
}
while (sscanf (input, "%u", &postal_code) != 1);
/* Check if the value is correct */
(void) printf ("The postal code is : %dn", postal_code);
return postal_code;
}
int
main (void)
{
/* Mailing list structure */
struct mailing_list
{
/* The address and its according postal_code */
char address[50];
int postal_code;
} mail;
/* The return value */
int ret = EXIT_SUCCESS;
/* Initialize the postal_code to 0 */
mail.postal_code = 0;
(void) printf ("Mailing list database.n");
(void) printf ("---------------------n");
(void) printf
("nThis program will enter a new user in the mailing list
databasen");
ret = takeadress (mail.address, sizeof (mail.address),
"takeadress");
/* If all goes fine we continue */
if (ret == EXIT_SUCCESS)
mail.postal_code = take_postalcode ("take_postalcode");
/* If postal_code = 0, this is a failure */
if (mail.postal_code == 0)
ret = EXIT_FAILURE;
/* Successful */
if (ret == EXIT_SUCCESS)
printf ("Values added.n");
return ret;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*********************************************************************
NAME : wipestring( string )
USAGE : Wipe useless values from the string...
PARAMETERS : char const *string to wipe...
*********************************************************************/
void
wipestring (char const *string)
{
char *p = strchr (string, 'n');
if (p)
{
*p = ' ';
}
else
{
int c;
while ((c = getchar ()) != 'n' && c != EOF)
{
}
}
}
/*********************************************************************
NAME : verify ( string, size, function_name )
USAGE : verify if the user input is correct
PARAMETERS :
- The string to check and to fill if the user enter something
- The size of the string
- The name of the function to give accurate error messages
RETURNS :
- EXIT_SUCCESS
- EXIT_FAILURE
*********************************************************************/
int
verify (char *string, size_t size, const char *function_name)
{
/* The error number */
int err = EXIT_SUCCESS;
/* Check if there's an input */
if (fgets (string, (int) size, stdin) == NULL)
{
printf ("Input Error at %sn", function_name);
err = EXIT_FAILURE;
}
/* Check if the user entered something */
else
{
wipestring (string);
if (*string == ' ')
{
printf ("No input at %sn", function_name);
err = EXIT_FAILURE;
}
}
return err;
}
/*********************************************************************
NAME : takeadress ( address, size, name )
PARAMETERS :
- The address
- The size of this string
- Its name
RETURNS : See verify()
*********************************************************************/
int
takeadress (char *address, size_t size, const char *name)
{
/* The return value */
int ret = 0;
(void) printf ("Please enter the address of the person : ");
(void) fflush (stdout);
ret = verify (address, size, name);
/* Check if the value is correct */
(void) printf ("The address is %sn", address);
return ret;
}
/*********************************************************************
NAME : take_postalcode ( name )
PARAMETERS : Name of the function.
RETURNS : The postal code entered by the user
*********************************************************************/
int
take_postalcode (const char *name)
{
/* The postal code */
unsigned int postal_code = 0;
/* User input */
char input[10];
/* Ask the postal code until the user gives one */
do
{
(void) printf ("Insert the postal code of the user city : ");
(void) fflush (stdout);
if (verify (input, sizeof (input), name) == EXIT_FAILURE)
{
postal_code = 0;
break;
}
}
while (sscanf (input, "%u", &postal_code) != 1);
/* Check if the value is correct */
(void) printf ("The postal code is : %dn", postal_code);
return postal_code;
}
int
main (void)
{
/* Mailing list structure */
struct mailing_list
{
/* The address and its according postal_code */
char address[50];
int postal_code;
} mail;
/* The return value */
int ret = EXIT_SUCCESS;
/* Initialize the postal_code to 0 */
mail.postal_code = 0;
(void) printf ("Mailing list database.n");
(void) printf ("---------------------n");
(void) printf
("nThis program will enter a new user in the mailing list
databasen");
ret = takeadress (mail.address, sizeof (mail.address),
"takeadress");
/* If all goes fine we continue */
if (ret == EXIT_SUCCESS)
mail.postal_code = take_postalcode ("take_postalcode");
/* If postal_code = 0, this is a failure */
if (mail.postal_code == 0)
ret = EXIT_FAILURE;
/* Successful */
if (ret == EXIT_SUCCESS)
printf ("Values added.n");
return ret;
}
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/*********************************************************************
NAME : wipestring( string )
USAGE : Wipe useless values from the string...
PARAMETERS : char const *string to wipe...
*********************************************************************/
void
wipestring (char const *string)
{
char *p = strchr (string, 'n');
if (p)
{
*p = ' ';
}
else
{
int c;
while ((c = getchar ()) != 'n' && c != EOF)
{
}
}
}
/*********************************************************************
NAME : verify ( string, size, function_name )
USAGE : verify if the user input is correct
PARAMETERS :
- The string to check and to fill if the user enter something
- The size of the string
- The name of the function to give accurate error messages
RETURNS :
- EXIT_SUCCESS
- EXIT_FAILURE
*********************************************************************/
int
verify (char *string, size_t size, const char *function_name)
{
/* The error number */
int err = EXIT_SUCCESS;
/* Check if there's an input */
if (fgets (string, (int) size, stdin) == NULL)
{
printf ("Input Error at %sn", function_name);
err = EXIT_FAILURE;
}
/* Check if the user entered something */
else
{
wipestring (string);
if (*string == ' ')
{
printf ("No input at %sn", function_name);
err = EXIT_FAILURE;
}
}
return err;
}
/*********************************************************************
NAME : takeadress ( address, size, name )
PARAMETERS :
- The address
- The size of this string
- Its name
RETURNS : See verify()
*********************************************************************/
int
takeadress (char *address, size_t size, const char *name)
{
/* The return value */
int ret = 0;
(void) printf ("Please enter the address of the person : ");
(void) fflush (stdout);
ret = verify (address, size, name);
/* Check if the value is correct */
(void) printf ("The address is %sn", address);
return ret;
}
/*********************************************************************
NAME : take_postalcode ( name )
PARAMETERS : Name of the function.
RETURNS : The postal code entered by the user
*********************************************************************/
int
take_postalcode (const char *name)
{
/* The postal code */
unsigned int postal_code = 0;
/* User input */
char input[10];
/* Ask the postal code until the user gives one */
do
{
(void) printf ("Insert the postal code of the user city : ");
(void) fflush (stdout);
if (verify (input, sizeof (input), name) == EXIT_FAILURE)
{
postal_code = 0;
break;
}
}
while (sscanf (input, "%u", &postal_code) != 1);
/* Check if the value is correct */
(void) printf ("The postal code is : %dn", postal_code);
return postal_code;
}
int
main (void)
{
/* Mailing list structure */
struct mailing_list
{
/* The address and its according postal_code */
char address[50];
int postal_code;
} mail;
/* The return value */
int ret = EXIT_SUCCESS;
/* Initialize the postal_code to 0 */
mail.postal_code = 0;
(void) printf ("Mailing list database.n");
(void) printf ("---------------------n");
(void) printf
("nThis program will enter a new user in the mailing list
databasen");
ret = takeadress (mail.address, sizeof (mail.address),
"takeadress");
/* If all goes fine we continue */
if (ret == EXIT_SUCCESS)
mail.postal_code = take_postalcode ("take_postalcode");
/* If postal_code = 0, this is a failure */
if (mail.postal_code == 0)
ret = EXIT_FAILURE;
/* Successful */
if (ret == EXIT_SUCCESS)
printf ("Values added.n");
return ret;
}
#define IFSUCCESS if ( ret == EXIT_SUCCESS )
/* Continue unless we got a EXIT_FAILURE */
IFSUCCESS
ret = takeadress (mail.address, sizeof(mail.address));
IFSUCCESS
ret = take_postalcode (mail.postal_code,
sizeof(mail.postal_code));
/* Successful */
if (ret == EXIT_SUCCESS)
printf ("Values added.n");
return ret;
}
mailing-entry.c: (in function main)
mailing-entry.c:232:21: Passed storage mail.name not completely defined
(*(mail.name) is undefined): take_name (mail.name, ...)
Storage derivable from a parameter, return value or global is not
defined. Use /*@out@*/ to denote passed or returned storage which need
not be defined. (Use -compdef to inhibit warning)
Finished checking --- 1 code warning
#define IFSUCCESS if ( ret == EXIT_SUCCESS )
/* Continue unless we got a EXIT_FAILURE */
IFSUCCESS
ret = takeadress (mail.address, sizeof(mail.address));
IFSUCCESS
ret = take_postalcode (mail.postal_code,
sizeof(mail.postal_code));
/* Successful */
if (ret == EXIT_SUCCESS)
printf ("Values added.n");
return ret;
}
mailing-entry.c: (in function main)
mailing-entry.c:232:21: Passed storage mail.name not completely defined
(*(mail.name) is undefined): take_name (mail.name, ...)
Storage derivable from a parameter, return value or global is not
defined. Use /*@out@*/ to denote passed or returned storage which need
not be defined. (Use -compdef to inhibit warning)
Finished checking --- 1 code warning
#define IFSUCCESS if ( ret == EXIT_SUCCESS )
/* Continue unless we got a EXIT_FAILURE */
IFSUCCESS
ret = takeadress (mail.address, sizeof(mail.address));
IFSUCCESS
ret = take_postalcode (mail.postal_code,
sizeof(mail.postal_code));
/* Successful */
if (ret == EXIT_SUCCESS)
printf ("Values added.n");
return ret;
}
mailing-entry.c: (in function main)
mailing-entry.c:232:21: Passed storage mail.name not completely defined
(*(mail.name) is undefined): take_name (mail.name, ...)
Storage derivable from a parameter, return value or global is not
defined. Use /*@out@*/ to denote passed or returned storage which need
not be defined. (Use -compdef to inhibit warning)
Finished checking --- 1 code warning
putchar ('v');
for (i = 0; i < n - 2; i++)
{
putchar ('-');
}
putchar ('v');
putchar ('n');
}
#define TERR
do
{
if (err)
{
ret = EXIT_FAILURE;
goto ERR;
}
}
while (0)
{
int err;
err = take_name (mail.name, sizeof (mail.name));
TERR;
err = take_address (mail.address, sizeof (mail.address));
TERR;
err = take_postalcode (mail.postal_code, sizeof (mail.postal_code));
TERR;
}
#undef TERR
/* Successful */
printf ("Values added:n");
#define FMT "%15s"
printf (FMT ": %sn", "Name", mail.name);
printf (FMT ": %sn", "Values Address", mail.address);
printf (FMT ": %sn", "Postal code", mail.postal_code);
#undef FMT
ERR:
return ret;
}
putchar ('v');
for (i = 0; i < n - 2; i++)
{
putchar ('-');
}
putchar ('v');
putchar ('n');
}
#define TERR
do
{
if (err)
{
ret = EXIT_FAILURE;
goto ERR;
}
}
while (0)
{
int err;
err = take_name (mail.name, sizeof (mail.name));
TERR;
err = take_address (mail.address, sizeof (mail.address));
TERR;
err = take_postalcode (mail.postal_code, sizeof (mail.postal_code));
TERR;
}
#undef TERR
/* Successful */
printf ("Values added:n");
#define FMT "%15s"
printf (FMT ": %sn", "Name", mail.name);
printf (FMT ": %sn", "Values Address", mail.address);
printf (FMT ": %sn", "Postal code", mail.postal_code);
#undef FMT
ERR:
return ret;
}
putchar ('v');
for (i = 0; i < n - 2; i++)
{
putchar ('-');
}
putchar ('v');
putchar ('n');
}
#define TERR
do
{
if (err)
{
ret = EXIT_FAILURE;
goto ERR;
}
}
while (0)
{
int err;
err = take_name (mail.name, sizeof (mail.name));
TERR;
err = take_address (mail.address, sizeof (mail.address));
TERR;
err = take_postalcode (mail.postal_code, sizeof (mail.postal_code));
TERR;
}
#undef TERR
/* Successful */
printf ("Values added:n");
#define FMT "%15s"
printf (FMT ": %sn", "Name", mail.name);
printf (FMT ": %sn", "Values Address", mail.address);
printf (FMT ": %sn", "Postal code", mail.postal_code);
#undef FMT
ERR:
return ret;
}
#define TERR
do
{
if (err)
{
ret = EXIT_FAILURE;
goto ERR;
}
}
while (0)
Tiens j'ai toujours rever de savoir comment faire un goto en C :).
T'as pas peur de déclencher une guerre avec talibans anti-goto ?
{
int err;
err = take_name (mail.name, sizeof (mail.name));
TERR;
err = take_address (mail.address, sizeof (mail.address));
TERR;
err = take_postalcode (mail.postal_code, sizeof (mail.postal_code));
TERR;
}
#undef TERR
ERR:
return ret;
Si on veut délimiter ERR on fait comment ?
}
#define TERR
do
{
if (err)
{
ret = EXIT_FAILURE;
goto ERR;
}
}
while (0)
Tiens j'ai toujours rever de savoir comment faire un goto en C :).
T'as pas peur de déclencher une guerre avec talibans anti-goto ?
{
int err;
err = take_name (mail.name, sizeof (mail.name));
TERR;
err = take_address (mail.address, sizeof (mail.address));
TERR;
err = take_postalcode (mail.postal_code, sizeof (mail.postal_code));
TERR;
}
#undef TERR
ERR:
return ret;
Si on veut délimiter ERR on fait comment ?
}
#define TERR
do
{
if (err)
{
ret = EXIT_FAILURE;
goto ERR;
}
}
while (0)
Tiens j'ai toujours rever de savoir comment faire un goto en C :).
T'as pas peur de déclencher une guerre avec talibans anti-goto ?
{
int err;
err = take_name (mail.name, sizeof (mail.name));
TERR;
err = take_address (mail.address, sizeof (mail.address));
TERR;
err = take_postalcode (mail.postal_code, sizeof (mail.postal_code));
TERR;
}
#undef TERR
ERR:
return ret;
Si on veut délimiter ERR on fait comment ?
}
int main (void)
{
/* Mailing list structure */
struct mailing_list
{
char name[20];
char address[50];
char postal_code[12];
}
mail;
/* The return value */
int ret = EXIT_SUCCESS;
/* Describe */
(void) printf ("Mailing list database.n");
(void) printf ("---------------------n");
(void) printf ("nThis program will enter a new user in the mailing"
" list databasen");
#define TERR
do
{
if (err)
{
ret = EXIT_FAILURE;
goto ERR;
}
}
while (0)
{
int err;
err = take_name (mail.name, sizeof (mail.name));
TERR;
err = take_address (mail.address, sizeof (mail.address));
TERR;
err = take_postalcode (mail.postal_code, sizeof (mail.postal_code));
TERR;
}
#undef TERR
/* Successful */
printf ("Values added:n");
#define FMT "%15s"
printf (FMT ": %sn", "Name", mail.name);
printf (FMT ": %sn", "Values Address", mail.address);
printf (FMT ": %sn", "Postal code", mail.postal_code);
#undef FMT
ERR:
return ret;
}
int main (void)
{
/* Mailing list structure */
struct mailing_list
{
char name[20];
char address[50];
char postal_code[12];
}
mail;
/* The return value */
int ret = EXIT_SUCCESS;
/* Describe */
(void) printf ("Mailing list database.n");
(void) printf ("---------------------n");
(void) printf ("nThis program will enter a new user in the mailing"
" list databasen");
#define TERR
do
{
if (err)
{
ret = EXIT_FAILURE;
goto ERR;
}
}
while (0)
{
int err;
err = take_name (mail.name, sizeof (mail.name));
TERR;
err = take_address (mail.address, sizeof (mail.address));
TERR;
err = take_postalcode (mail.postal_code, sizeof (mail.postal_code));
TERR;
}
#undef TERR
/* Successful */
printf ("Values added:n");
#define FMT "%15s"
printf (FMT ": %sn", "Name", mail.name);
printf (FMT ": %sn", "Values Address", mail.address);
printf (FMT ": %sn", "Postal code", mail.postal_code);
#undef FMT
ERR:
return ret;
}
int main (void)
{
/* Mailing list structure */
struct mailing_list
{
char name[20];
char address[50];
char postal_code[12];
}
mail;
/* The return value */
int ret = EXIT_SUCCESS;
/* Describe */
(void) printf ("Mailing list database.n");
(void) printf ("---------------------n");
(void) printf ("nThis program will enter a new user in the mailing"
" list databasen");
#define TERR
do
{
if (err)
{
ret = EXIT_FAILURE;
goto ERR;
}
}
while (0)
{
int err;
err = take_name (mail.name, sizeof (mail.name));
TERR;
err = take_address (mail.address, sizeof (mail.address));
TERR;
err = take_postalcode (mail.postal_code, sizeof (mail.postal_code));
TERR;
}
#undef TERR
/* Successful */
printf ("Values added:n");
#define FMT "%15s"
printf (FMT ": %sn", "Name", mail.name);
printf (FMT ": %sn", "Values Address", mail.address);
printf (FMT ": %sn", "Postal code", mail.postal_code);
#undef FMT
ERR:
return ret;
}
In 'fr.comp.lang.c', Richard Delorme wrote:
<snip mon code>Franchement, je trouve cela très lourd. Qu'est-ce qui ne va pas avec :
int main (void)
{
/* Mailing list structure */
struct mailing_list
{
char name[20];
char address[50];
char postal_code[12];
}
mail;
/* Describe */
(void) printf ("Mailing list database.n");
(void) printf ("---------------------n");
(void) printf ("nThis program will enter a new user in the mailing"
" list databasen");
if (take_name (mail.name, sizeof (mail.name)))
return EXIT_FAILURE;
if (take_address (mail.address, sizeof (mail.address)))
return EXIT_FAILURE;
if (take_postalcode (mail.postal_code, sizeof (mail.postal_code)))
return EXIT_FAILURE;
/* Successful */
printf ("Values added:n");
#define FMT "%15s"
printf (FMT ": %sn", "Name", mail.name);
printf (FMT ": %sn", "Values Address", mail.address);
printf (FMT ": %sn", "Postal code", mail.postal_code);
#undef FMT
return EXIT_SUCCESS;
}
On risque de louper une action importante en sortie (libération de
ressource).
Si je veux mettre un point d'arret sur la sortie, je fais comment?Ce code est 30% plus court que le précédent, et à mon avis, nettement
plus
Faut pas exagerer.
[...]
Ramené au reste du code, ça fait pas lourd!
clair. D'où vient cette théorie du point de sortie systématiquement
unique d'une fonction ? Dans le cas présent, je trouve que cela obscurcit
le code,
De la programmation structurée.
Je ne comprend pas bien ta remarque sur
l'obscurcissement. On reproche souvent au C d'obliger le programmeur à
passer du temps à écrire du code de test, imbriquer des ifs etc. Je montre
une méthode d'allégement du codage, et non il faut encore qu'il y en ait
un qui rale.
Je te signale que le principe d'utiliser la macro permet par simple
recompilation d'affiner l'instrumentation du code, comme ajouter une trace
avec __FILE__, __LINE__ sans alourdir le code. Seule la macro est
modifiée(ou une macro spéciale de debug est crée). Visiblement, tu manques
d'expérience sur les gros projets pour ne pas comprendre l'intérêt de la
chose...
le ralentit (ajout de sauts et d'affectations) sans rien apporter. Je
sais
Ca apporte de la sécurité en matière de conception. On sait exactement par
où on passe en quittant. On sait ce qu'on a à faire, et on a pas besoin de
le multiplier.
qu'il est parfois pratique d'avoir un point de sortie unique, si l'on
nettoie certaines ressources (fichiers fermés, mémoire libérée,...), mais
ce n'est pas le cas ici. Il s'agit donc d'un abus de principe. Je ne suis
Je code de façon générique. Je ne m'occupe pas des cas particuliers ou
d'école des 'toy programs'. Je préfère exposer des principes généraux
réutilisables en toutes circonstances et qui on fait leur preuves.
Ruinant tous les efforts de spaghettisation du code.
Tu veux sans doute dire de 'despaghettisation'.
D'accord, un commentaire
serait le bienvenu, ou alors un traitement particulier pour les cas
d'erreur.
END:
/* fin commune */
fclose(fichier);
free(data);
return ret;
ERR:
/* traitement d'erreur */
goto END;
}
Je ne suis pas un adepte de goto, loin de là (Dégouté du BASIC, sauvé par
Pascal), mais au cours de nombreux débats sur fcl et clc, j'ai fini par
admettre que dans certains cas, il pouvait être utile, notamment pour
alléger les traitement d'erreurs (à condition de cacher les details gores
dans une macro a-priori locale)
In 'fr.comp.lang.c', Richard Delorme <abulmo@nospam.fr> wrote:
<snip mon code>
Franchement, je trouve cela très lourd. Qu'est-ce qui ne va pas avec :
int main (void)
{
/* Mailing list structure */
struct mailing_list
{
char name[20];
char address[50];
char postal_code[12];
}
mail;
/* Describe */
(void) printf ("Mailing list database.n");
(void) printf ("---------------------n");
(void) printf ("nThis program will enter a new user in the mailing"
" list databasen");
if (take_name (mail.name, sizeof (mail.name)))
return EXIT_FAILURE;
if (take_address (mail.address, sizeof (mail.address)))
return EXIT_FAILURE;
if (take_postalcode (mail.postal_code, sizeof (mail.postal_code)))
return EXIT_FAILURE;
/* Successful */
printf ("Values added:n");
#define FMT "%15s"
printf (FMT ": %sn", "Name", mail.name);
printf (FMT ": %sn", "Values Address", mail.address);
printf (FMT ": %sn", "Postal code", mail.postal_code);
#undef FMT
return EXIT_SUCCESS;
}
On risque de louper une action importante en sortie (libération de
ressource).
Si je veux mettre un point d'arret sur la sortie, je fais comment?
Ce code est 30% plus court que le précédent, et à mon avis, nettement
plus
Faut pas exagerer.
[...]
Ramené au reste du code, ça fait pas lourd!
clair. D'où vient cette théorie du point de sortie systématiquement
unique d'une fonction ? Dans le cas présent, je trouve que cela obscurcit
le code,
De la programmation structurée.
Je ne comprend pas bien ta remarque sur
l'obscurcissement. On reproche souvent au C d'obliger le programmeur à
passer du temps à écrire du code de test, imbriquer des ifs etc. Je montre
une méthode d'allégement du codage, et non il faut encore qu'il y en ait
un qui rale.
Je te signale que le principe d'utiliser la macro permet par simple
recompilation d'affiner l'instrumentation du code, comme ajouter une trace
avec __FILE__, __LINE__ sans alourdir le code. Seule la macro est
modifiée(ou une macro spéciale de debug est crée). Visiblement, tu manques
d'expérience sur les gros projets pour ne pas comprendre l'intérêt de la
chose...
le ralentit (ajout de sauts et d'affectations) sans rien apporter. Je
sais
Ca apporte de la sécurité en matière de conception. On sait exactement par
où on passe en quittant. On sait ce qu'on a à faire, et on a pas besoin de
le multiplier.
qu'il est parfois pratique d'avoir un point de sortie unique, si l'on
nettoie certaines ressources (fichiers fermés, mémoire libérée,...), mais
ce n'est pas le cas ici. Il s'agit donc d'un abus de principe. Je ne suis
Je code de façon générique. Je ne m'occupe pas des cas particuliers ou
d'école des 'toy programs'. Je préfère exposer des principes généraux
réutilisables en toutes circonstances et qui on fait leur preuves.
Ruinant tous les efforts de spaghettisation du code.
Tu veux sans doute dire de 'despaghettisation'.
D'accord, un commentaire
serait le bienvenu, ou alors un traitement particulier pour les cas
d'erreur.
END:
/* fin commune */
fclose(fichier);
free(data);
return ret;
ERR:
/* traitement d'erreur */
goto END;
}
Je ne suis pas un adepte de goto, loin de là (Dégouté du BASIC, sauvé par
Pascal), mais au cours de nombreux débats sur fcl et clc, j'ai fini par
admettre que dans certains cas, il pouvait être utile, notamment pour
alléger les traitement d'erreurs (à condition de cacher les details gores
dans une macro a-priori locale)
In 'fr.comp.lang.c', Richard Delorme wrote:
<snip mon code>Franchement, je trouve cela très lourd. Qu'est-ce qui ne va pas avec :
int main (void)
{
/* Mailing list structure */
struct mailing_list
{
char name[20];
char address[50];
char postal_code[12];
}
mail;
/* Describe */
(void) printf ("Mailing list database.n");
(void) printf ("---------------------n");
(void) printf ("nThis program will enter a new user in the mailing"
" list databasen");
if (take_name (mail.name, sizeof (mail.name)))
return EXIT_FAILURE;
if (take_address (mail.address, sizeof (mail.address)))
return EXIT_FAILURE;
if (take_postalcode (mail.postal_code, sizeof (mail.postal_code)))
return EXIT_FAILURE;
/* Successful */
printf ("Values added:n");
#define FMT "%15s"
printf (FMT ": %sn", "Name", mail.name);
printf (FMT ": %sn", "Values Address", mail.address);
printf (FMT ": %sn", "Postal code", mail.postal_code);
#undef FMT
return EXIT_SUCCESS;
}
On risque de louper une action importante en sortie (libération de
ressource).
Si je veux mettre un point d'arret sur la sortie, je fais comment?Ce code est 30% plus court que le précédent, et à mon avis, nettement
plus
Faut pas exagerer.
[...]
Ramené au reste du code, ça fait pas lourd!
clair. D'où vient cette théorie du point de sortie systématiquement
unique d'une fonction ? Dans le cas présent, je trouve que cela obscurcit
le code,
De la programmation structurée.
Je ne comprend pas bien ta remarque sur
l'obscurcissement. On reproche souvent au C d'obliger le programmeur à
passer du temps à écrire du code de test, imbriquer des ifs etc. Je montre
une méthode d'allégement du codage, et non il faut encore qu'il y en ait
un qui rale.
Je te signale que le principe d'utiliser la macro permet par simple
recompilation d'affiner l'instrumentation du code, comme ajouter une trace
avec __FILE__, __LINE__ sans alourdir le code. Seule la macro est
modifiée(ou une macro spéciale de debug est crée). Visiblement, tu manques
d'expérience sur les gros projets pour ne pas comprendre l'intérêt de la
chose...
le ralentit (ajout de sauts et d'affectations) sans rien apporter. Je
sais
Ca apporte de la sécurité en matière de conception. On sait exactement par
où on passe en quittant. On sait ce qu'on a à faire, et on a pas besoin de
le multiplier.
qu'il est parfois pratique d'avoir un point de sortie unique, si l'on
nettoie certaines ressources (fichiers fermés, mémoire libérée,...), mais
ce n'est pas le cas ici. Il s'agit donc d'un abus de principe. Je ne suis
Je code de façon générique. Je ne m'occupe pas des cas particuliers ou
d'école des 'toy programs'. Je préfère exposer des principes généraux
réutilisables en toutes circonstances et qui on fait leur preuves.
Ruinant tous les efforts de spaghettisation du code.
Tu veux sans doute dire de 'despaghettisation'.
D'accord, un commentaire
serait le bienvenu, ou alors un traitement particulier pour les cas
d'erreur.
END:
/* fin commune */
fclose(fichier);
free(data);
return ret;
ERR:
/* traitement d'erreur */
goto END;
}
Je ne suis pas un adepte de goto, loin de là (Dégouté du BASIC, sauvé par
Pascal), mais au cours de nombreux débats sur fcl et clc, j'ai fini par
admettre que dans certains cas, il pouvait être utile, notamment pour
alléger les traitement d'erreurs (à condition de cacher les details gores
dans une macro a-priori locale)
int
main (void)
{
/* Mailing list structure */
struct mailing_list
{
char name[50];
char address[128];
char postal_code[12];
} mail;
/* The return value */
int ret = EXIT_SUCCESS;
/* Describe */
(void) printf ("Mailing list database.n");
(void) printf ("---------------------n");
(void) printf
("nThis program will enter a new user in the mailing list databasen");
ret = take_name(mail.name, sizeof(mail.name));
/* Continue unless we got a EXIT_FAILURE */
IFSUCCESS
ret = takeadress (mail.address, sizeof(mail.address));
IFSUCCESS
ret = take_postalcode (mail.postal_code, sizeof(mail.postal_code));
/* Successful */
if (ret == EXIT_SUCCESS)
printf ("Values added.n");
return ret;
}
Le problème est que splint me retourne :
mailing-entry.c: (in function main)
mailing-entry.c:232:21: Passed storage mail.name not completely defined
(*(mail.name) is undefined): take_name (mail.name, ...)
Storage derivable from a parameter, return value or global is not defined.
Use /*@out@*/ to denote passed or returned storage which need not be defined.
(Use -compdef to inhibit warning)
Finished checking --- 1 code warning
int
main (void)
{
/* Mailing list structure */
struct mailing_list
{
char name[50];
char address[128];
char postal_code[12];
} mail;
/* The return value */
int ret = EXIT_SUCCESS;
/* Describe */
(void) printf ("Mailing list database.n");
(void) printf ("---------------------n");
(void) printf
("nThis program will enter a new user in the mailing list databasen");
ret = take_name(mail.name, sizeof(mail.name));
/* Continue unless we got a EXIT_FAILURE */
IFSUCCESS
ret = takeadress (mail.address, sizeof(mail.address));
IFSUCCESS
ret = take_postalcode (mail.postal_code, sizeof(mail.postal_code));
/* Successful */
if (ret == EXIT_SUCCESS)
printf ("Values added.n");
return ret;
}
Le problème est que splint me retourne :
mailing-entry.c: (in function main)
mailing-entry.c:232:21: Passed storage mail.name not completely defined
(*(mail.name) is undefined): take_name (mail.name, ...)
Storage derivable from a parameter, return value or global is not defined.
Use /*@out@*/ to denote passed or returned storage which need not be defined.
(Use -compdef to inhibit warning)
Finished checking --- 1 code warning
int
main (void)
{
/* Mailing list structure */
struct mailing_list
{
char name[50];
char address[128];
char postal_code[12];
} mail;
/* The return value */
int ret = EXIT_SUCCESS;
/* Describe */
(void) printf ("Mailing list database.n");
(void) printf ("---------------------n");
(void) printf
("nThis program will enter a new user in the mailing list databasen");
ret = take_name(mail.name, sizeof(mail.name));
/* Continue unless we got a EXIT_FAILURE */
IFSUCCESS
ret = takeadress (mail.address, sizeof(mail.address));
IFSUCCESS
ret = take_postalcode (mail.postal_code, sizeof(mail.postal_code));
/* Successful */
if (ret == EXIT_SUCCESS)
printf ("Values added.n");
return ret;
}
Le problème est que splint me retourne :
mailing-entry.c: (in function main)
mailing-entry.c:232:21: Passed storage mail.name not completely defined
(*(mail.name) is undefined): take_name (mail.name, ...)
Storage derivable from a parameter, return value or global is not defined.
Use /*@out@*/ to denote passed or returned storage which need not be defined.
(Use -compdef to inhibit warning)
Finished checking --- 1 code warning
%-------------------------------------------
/* Mailing list structure */
struct mailing_list
{
char name[50];
char address[128];
char postal_code[12];
} mail = {"", "", ""};
%-------------------------------------------
Une autre manière est d'initialiser les champs un par un, de la façon
suivante, avant qu'ils soient utilisés :
%-------------------------------------------
mail.name[0] = ' ';
mail.address[0] = ' ';
mail.postal_code[0] = ' ';
%-------------------------------------------
%-------------------------------------------
/* Mailing list structure */
struct mailing_list
{
char name[50];
char address[128];
char postal_code[12];
} mail = {"", "", ""};
%-------------------------------------------
Une autre manière est d'initialiser les champs un par un, de la façon
suivante, avant qu'ils soient utilisés :
%-------------------------------------------
mail.name[0] = ' ';
mail.address[0] = ' ';
mail.postal_code[0] = ' ';
%-------------------------------------------
%-------------------------------------------
/* Mailing list structure */
struct mailing_list
{
char name[50];
char address[128];
char postal_code[12];
} mail = {"", "", ""};
%-------------------------------------------
Une autre manière est d'initialiser les champs un par un, de la façon
suivante, avant qu'ils soient utilisés :
%-------------------------------------------
mail.name[0] = ' ';
mail.address[0] = ' ';
mail.postal_code[0] = ' ';
%-------------------------------------------