2015-09-26 2 views
1

Nous venons de commencer le sujet des fonctions de bas niveau en C et pour une partie de cette affectation, nous devons demander une entrée utilisateur. Normalement, j'utiliserais printf() et scanf() cependant, pour cette affectation, nous ne pouvons utiliser que read(), write(), open(), close() et lseek().demander et lire dans l'entrée de l'utilisateur en utilisant des routines d'E/S non tamponnées

Ma question est comment voulez-vous lire l'entrée du clavier après l'impression à l'écran? Je comprends que je devrais utiliser read, le descripteur de fichier serait STDIN_FILENO, mais comment puis-je déterminer le nombre de taille? Comment puis-je garder une trace de ce que l'utilisateur a entré? Aurais-je besoin de créer un tableau char juste pour ça?

Aussi si quelqu'un pouvait référencer un bon matériel de lecture ou des tutoriels pour la programmation avec des fonctions de bas niveau qui aideraient beaucoup.

+0

La façon la plus simple est probablement de lire un caractère à la fois unt Vous obtenez une nouvelle ligne, en ajoutant les caractères à un tableau. –

+0

Si vous voulez lire à partir de stdin, n'auriez-vous pas besoin de spécifier la taille de la matrice avant la main? Je comprends ce que tu veux dire mais je ne sais pas comment je l'implémenterais. – user3538161

+0

Il n'y a pas vraiment de différence entre utiliser 'read/write' pour faire des entrées/sorties et utiliser' getchar/printf'. La principale différence est que vous ne profitez pas du luxe d'une sortie formatée ou d'une fonction d'impression variée. Vous devez faire la mise en forme en écrivant chaque morceau de sortie à «stdout» comme vous le souhaitez. Si vous êtes toujours coincé, faites le moi savoir. Vous utilisez read sur 'stdin' comme n'importe quel fichier. Vous déclarez un tampon (tableau) et lisez depuis «stdin» dans le tampon. Le retour de 'read' vous donne le nombre de caractères lus avec succès. –

Répondre

1

Continuant de mon commentaire précédent, il y a une différence très peu entre la lecture et l'écriture à l'aide stdinread et write et en utilisant des fonctions de niveau supérieur comme fgets et printf. La principale différence est que vous ne pouvez pas compter sur la chaîne de format fournie par le printf variadique, et avec read, vous êtes responsable de l'utilisation du retour pour savoir combien de caractères ont été réellement lus.

est Ci-dessous un court exemple montrant les rudiments de la lecture entrée de stdin avec read puis écrire cette information de retour avec write (Note: il y a des contrôles supplémentaires que vous devez ajouter comme vérifier que le nombre de caractères lus est inférieur à la taille du tampon pour savoir si plus de caractères restent à lire, etc ...) Vous pouvez toujours mettre une grande partie de l'invite et read dans une fonction pour faciliter l'utilisation répétitive.

Avec write, rappelez-vous juste, l'ordre que vous écrire des choses à stdoutest la chaîne de format. Il suffit donc de faire des appels logiques à write pour accomplir le formatage que vous désirez.Pendant que vous êtes libre d'utiliser les STDIN_FILENO définit, vous pouvez également utiliser simplement 0 - stdin, 1 - stdout et 2 - stderr:

#include <unistd.h> 

#define MAXC 256 

int main (void) { 

    char buf[MAXC] = {0}; 
    ssize_t nchr = 0; 

    /* write the prompt to stdout requesting input */ 
    write (1, "\n enter text : ", sizeof ("\n enter text : ")); 

    /* read up to MAXC characters from stdin */ 
    if ((nchr = read (0, buf, MAXC)) == -1) { 
     write (2, "error: read failure.\n", sizeof ("error: read failure.\n")); 
     return 1; 
    } 

    /* test if additional characters remain unread in stdin */ 
    if (nchr == MAXC && buf[nchr - 1] != '\n') 
     write (2, "warning: additional chars remain unread.\n", 
      sizeof ("warning: additional chars remain unread.\n")); 

    /* write the contents of buf to stdout */ 
    write (1, "\n text entered: ", sizeof ("\n text entered: ")); 
    write (1, buf, nchr-1); 
    write (1, "\n\n", sizeof ("\n\n")); 

    return 0; 
} 

Compile

gcc -Wall -Wextra -o bin/read_write_stdin read_write_stdin.c 

Sortie

$ ./bin/read_write_stdin 

enter text : The quick brown fox jumps over the lazy dog! 

text entered: The quick brown fox jumps over the lazy dog! 
+0

Je suis un peu confus avec écrire. Le deuxième argument ne doit-il pas être un pointeur vers un tampon? Comment êtes-vous capable de passer une chaîne? Ne lit pas non plus return 0 quand il atteint la fin du fichier? donc ne serait pas nchr = 0? – user3538161

+0

Il s'agit d'un pointeur vers un tampon. Le tampon est déclaré comme un tableau statique 'buf [MAXC]'. Cependant, lorsqu'il est passé en paramètre, le tableau * se décompose * en pointeur. C'est la même raison pour laquelle vous pouvez écrire 'int main '(int argc, char * argv [])' ou 'int main (int argc, char ** argv)'. Vous pouvez lire tout ce que vous voulez sur le sujet, il suffit de chercher ** C pointer decay **. J'ai simplement choisi un tableau statique pour garder l'exemple simple plutôt que de choisir d'allouer dynamiquement un pointeur avec 'malloc' et de le distraire de la logique' read' 'write'. ('calloc' serait un meilleur choix). –

2

La lecture de char par char serait mauvaise pour les performances. Les appels système sont plutôt chers. Le plus souvent, vous voulez une sorte de tampon (malloced, mémoire statique, sur la pile). La taille (une fois dépassée) n'a pas vraiment d'importance.

Si votre fd 0 est un terminal en mode cuit, vous obtiendrez une ligne sur chaque appel à lire (qui ne remplira généralement pas votre mémoire tampon). Ce qu'il est important de réaliser, c'est qu'une requête de lecture pour N octets n'a pas besoin de retourner N octets et qu'un retour de moins de N octets ne doit pas nécessairement signifier une erreur d'E/S. S'il s'agit d'un fichier sur disque, votre demande de lecture pour la taille de votre tampon aura tendance à être entièrement remplie.

La programmation avancée dans l'environnement Unix de Richard Stevens est un bon livre à ce sujet. Alors bien sûr, les pages de manuel pour les appels système.