4 Part 1: get, put, del 4.2 User interface (main.c) The main function will contain the main loop of your program and should behave like this: 1. Create an empty dictionary 2. Print ">" on the standard output (this is important). 3. Read the command from the user; the first three characters are the command name, then a space, then the arguments, and a newline character \n. 4. If the command is unknown, exit. 5. If end-of-file was read (EOF), destroy the dictionary and exit. 6. Otherwise, execute the corresponding command and go back to 2. To read from the standard input, you will be using the stream reading functions from the standard library, with stream being stdin, a variable defined in : • int fgetc (FILE* stream): read one character of the given stream. This returns the constant EOF on end of file. • char* fgets (char* s, int size, FILE* stream): read in at most one less than size chars from stream and stores them into the buffer pointed to by or a newline. If a newline is read, it is stored into the buffer. A terminating null byte (\ė) is stored after the last character. S. Reading stops after an EOF The function fgets is a bit tricky to work with when you want to read a whole line. Indeed, if the line is very long, fgets needs to be called multiple times. A video aside for this lab walks you through implementing a robust "readline" function. To write to the standard output, you will be using printf(3). -Note In Part 3, you will be dealing with reading and writing from files. In fact, the standard input and standard output are files from the point of view of the standard library. You can see this in fgets, for instance, where the third argument is of type FILE* and we use the variable stdin for this stream. Similarly, printf is tf is simply a jindows shortcut for fprintf (stdout, ...). On UNIX machines, the standard input and output are accessible as “fake” files, located in /dev; since these are per-process (each process has its own standard input/output), when accessing the file /dev/stdout, the kernel checks which process is accessing them and returns the correct file ings to activate Windows. descriptor. -Note All these f* functions are buffered: since actually reading and writing to a file is very costly (it requires a system call, Ch. 8), these actions are done in temporary buffers in memory, and system calls are made only when needed (buffer full when writing, buffer empty when reading). We will see more about buffering in Ch. 10. Let us simply note the two following consequences of using buffered input/output: Calling fgetc multiple times to get a full line is nearly as efficient as calling fgets. Writing is done to a temporary buffer and is actually sent (flushed) to the stream (e.g., stdout) when the buffer is full or fflush (stream) is called. You need not worry about this for this lab, since you will be interacting with the program on a terminal, where flushing is automatically done after each call to printf(3). To emulate this, the driver calls your program with stdbuf (1) to disable buffering. If it weren't doing this, the driver would be stuck trying to read data that dict would have stored in a buffer, but not flushed. 4.2.1 Commands The three commands to be implemented in this part are: get KEY: print the value associated with KEY followed by a newline \n. If no such value exists, a blank line is printed. ⚫ put KEY: VALUE: store the pair KEY / VALUE. Note that both KEY and VALUE can be arbitrary strings, with the only guarantee being that KEY does not contain a colon. Additionally, these strings don't contain a newline \n. Nothing is printed in return. ⚫ del KEY: delete the pair associated with KEY, if it exists. Nothing is printed in return, even if the key does not exist in the dictionary.
4 Part 1: get, put, del 4.2 User interface (main.c) The main function will contain the main loop of your program and should behave like this: 1. Create an empty dictionary 2. Print ">" on the standard output (this is important). 3. Read the command from the user; the first three characters are the command name, then a space, then the arguments, and a newline character \n. 4. If the command is unknown, exit. 5. If end-of-file was read (EOF), destroy the dictionary and exit. 6. Otherwise, execute the corresponding command and go back to 2. To read from the standard input, you will be using the stream reading functions from the standard library, with stream being stdin, a variable defined in : • int fgetc (FILE* stream): read one character of the given stream. This returns the constant EOF on end of file. • char* fgets (char* s, int size, FILE* stream): read in at most one less than size chars from stream and stores them into the buffer pointed to by or a newline. If a newline is read, it is stored into the buffer. A terminating null byte (\ė) is stored after the last character. S. Reading stops after an EOF The function fgets is a bit tricky to work with when you want to read a whole line. Indeed, if the line is very long, fgets needs to be called multiple times. A video aside for this lab walks you through implementing a robust "readline" function. To write to the standard output, you will be using printf(3). -Note In Part 3, you will be dealing with reading and writing from files. In fact, the standard input and standard output are files from the point of view of the standard library. You can see this in fgets, for instance, where the third argument is of type FILE* and we use the variable stdin for this stream. Similarly, printf is tf is simply a jindows shortcut for fprintf (stdout, ...). On UNIX machines, the standard input and output are accessible as “fake” files, located in /dev; since these are per-process (each process has its own standard input/output), when accessing the file /dev/stdout, the kernel checks which process is accessing them and returns the correct file ings to activate Windows. descriptor. -Note All these f* functions are buffered: since actually reading and writing to a file is very costly (it requires a system call, Ch. 8), these actions are done in temporary buffers in memory, and system calls are made only when needed (buffer full when writing, buffer empty when reading). We will see more about buffering in Ch. 10. Let us simply note the two following consequences of using buffered input/output: Calling fgetc multiple times to get a full line is nearly as efficient as calling fgets. Writing is done to a temporary buffer and is actually sent (flushed) to the stream (e.g., stdout) when the buffer is full or fflush (stream) is called. You need not worry about this for this lab, since you will be interacting with the program on a terminal, where flushing is automatically done after each call to printf(3). To emulate this, the driver calls your program with stdbuf (1) to disable buffering. If it weren't doing this, the driver would be stuck trying to read data that dict would have stored in a buffer, but not flushed. 4.2.1 Commands The three commands to be implemented in this part are: get KEY: print the value associated with KEY followed by a newline \n. If no such value exists, a blank line is printed. ⚫ put KEY: VALUE: store the pair KEY / VALUE. Note that both KEY and VALUE can be arbitrary strings, with the only guarantee being that KEY does not contain a colon. Additionally, these strings don't contain a newline \n. Nothing is printed in return. ⚫ del KEY: delete the pair associated with KEY, if it exists. Nothing is printed in return, even if the key does not exist in the dictionary.
Related questions
Question
Expert Solution
This question has been solved!
Explore an expertly crafted, step-by-step solution for a thorough understanding of key concepts.
Step by step
Solved in 2 steps