2017-04-22 2 views
2

Je ne suis pas en mesure d'ouvrir/créer un fichier correctement en utilisant la fonction open(), donc j'ai pensé que l'utilisation de messages errno m'aidera à comprendre la raison. Cependant, je ne sais pas comment définir le if(), donc il m'imprime l'erreur. Je sais que le code comme cela devrait fonctionner:Comment imprimer errno tout en sauvant la valeur de la fonction?

if(open(handle,O_RDWR | O_CREAT) == -1){ 
     printf("%s\n",strerror(errno)); 
} 

mais si je veux sauver la valeur de l'open() à ma variable et si elle est -1 puis imprimer l'erreur aussi bien? Je ne veux pas appeler open() deux fois pour cela et je ne sais pas comment l'assigner si c'est ok et comment imprimer une erreur sinon.

#include <stdio.h> 
    #include <stdlib.h> 
    #include <fcntl.h> 
    #include <ctype.h> 
    #include <sys/types.h> 
    #include <sys/stat.h> 
    #include <string.h> 
    #include <errno.h> 


    int main(int argc, char **argv){ 
     int handle,i,help; 
     int *array = malloc(5*sizeof(int)); 
     float *red = malloc(5*sizeof(int)); 

     array[0]=5; 
     array[1]=4; 
     array[2]=3; 
     array[3]=2; 
     array[4]=1; 

     handle = open(argv[1], O_RDWR | O_CREAT); 
     if(handle == -1){ 
      printf("%s\n",strerror(errno)); 
     } 

     printf("handle 1 %d\n",handle); 
     write(handle,array,20); 
     close(handle); 

     handle = open(argv[1], O_RDONLY); 
     lseek(handle,0,SEEK_SET); 
     printf("handle %d\n",handle); 
     help=read(handle,&red,20); 
     printf("pomoc %d\n",help); 
     for(i=0; i<5; i++){ 
      printf("%d\n",(int)red[i]); 
     } 
     close(handle); 
     return 0; 
    } 
+0

c'est mon code "essayer" parce que je ne suis pas sûr comment la fonction read() fonctionne, donc je voulais essayer si je peux jeter n'importe quel type de pointeur là et lire toute quantité d'octets et si cela fonctionnera, mais je ne peut même pas passer la partie d'ouverture. – ligazetom

+0

Notez que vous ne devez pas continuer comme si le descripteur était ouvert après avoir signalé l'erreur. Et l'erreur doit être signalée sur le flux d'erreur standard, pas sur la sortie standard. –

Répondre

0

Il semble que vous le fassiez correctement; il suffit d'enregistrer la valeur de retour de open() dans une variable, puis comparez cela à -1. Bien.

Notez que ceci est cassé:

float *red = malloc(5*sizeof(int)); 

car il n'y a aucune garantie qu'un float est la même taille que l'int, cela est faux et très confus. Il est préférable de ne pas répéter le type dans le malloc() car cela risque d'introduire cette erreur. , Faire au lieu:

float * const red = malloc(5 * sizeof *red); 

Il utilise sizeof *red pour calculer sizeof (float), tout en vous assurant que le type est celui d'un pointeur réel dans votre programme. Notez également l'utilisation de const pour protéger contre red étant réattribuée plus tard, ce qui peut créer une fuite de mémoire.

+0

Je ne suis pas sûr parce que quand je le fais de cette façon soudainement gérer n'est pas -1 mais 0, et il ne sait pas quoi imprimer je suppose. A propos de l'allocation Je sais que ça ne peut pas être utilisé normalement J'ai dit, j'essaie juste ce qui peut être fait avec les fonctions de bas niveau, mais puisque vous l'avez choisi, puis-je demander comment le faire alors? Je dois écrire un octet de char non signé, puis un nombre aléatoire de flottants, tous en binaire. Comment devrais-je les relire en mémoire? – ligazetom

+0

@ligazetom C'est une question entièrement différente sur la façon d'encoder/sérialiser des données, et répondre dans un commentaire à cette question va à l'encontre de la façon dont ce site est censé fonctionner. S'il vous plaît poster une question pertinente, ou de la recherche, je sais que cela a eu lieu des tas de fois avant. – unwind

1

La bonne façon de le faire est la suivante:

if((handle=open(argv[1], O_RDWR|O_CREAT, 0666)) == -1){ 

Notez que l'argument pmode est nécessaire pour O_CREAT.

+0

Eh bien, quels sont ces modes? J'ai vu plus de discussions à ce sujet mais je n'ai pas vu de tut à ce sujet jusqu'à maintenant. Je suis sur Linux btw. – ligazetom

+0

'_S_IREAD' et' _S_IWRITE' ne sont pas standard. Le troisième argument de 'open' devrait presque toujours être' 0666'; l'exception la plus importante concerne les fichiers contenant _secrets_, pour lesquels '0600' est utilisé. – zwol

+0

'0666', ah, oui, unix. J'ai oublié. Merci Zwol. –

1

Le problème n'est pas assigner à une variable, c'est la façon que vous appelez open:

handle = open(argv[1], O_RDWR|O_CREAT); // wrong number of arguments 
if (handle == -1) { 
    printf("%s\n",strerror(errno)); 
} 

Lorsque vous utilisez O_CREAT, vous devez donner opentrois arguments. Si vous ne le faites pas, le comportement n'est pas défini. Par accident, vous obteniez un retour d'erreur − 1 lorsque l'appel open se trouvait à l'intérieur du if, et une valeur de retour non négative lorsque vous l'avez affecté à une variable.

Sauf si vous avez une raison concrète de faire autrement, le troisième argument à open devrait être le nombre magique 0666. (La raison concrète la plus courante de faire autrement est que vous créez un fichier qui contiendra information secrète, alors vous utilisez 0600.) (Le zéro de début est requis.) Il sont des constantes symboliques qui peuvent être utilisées pour le troisième argument à open mais, une fois que vous savez ce que signifient les «modes» numériques, les constantes symboliques sont en réalité plus difficiles à lire.Here is a detailed explanation of "modes" in both symbolic and numeric forms.

Soit dit en passant, lorsqu'un appel système échoue, vous devez toujours imprimer les deuxstrerror(errno)et le nom du fichier incriminé (le cas échéant):

handle = open(argv[1], O_RDWR|O_CREAT, 0666); 
if (handle == -1) { 
    printf("%s: %s\n", argv[1], strerror(errno)); 
    exit(1); 
} 

Et vous devriez penser à si vous devriez être en utilisant O_EXCL ou O_TRUNC.

+1

Ou considérer 'O_TRUNC' si vous n'utilisez pas' O_EXCL'? –