Author : Tom Torfs
Page : << Previous 13 Next >>
fopen("testfile","r");
if (f==NULL)
{
printf("Error: unable to open testfile for reading\n");
return EXIT_FAILURE;
}
This code opens the previously written "testfile" for reading. The only difference with the above code is that the "w" has been replaced with "r".
if (fgets(s, sizeof s, f) != NULL)
{
}
The fgets() function reads a string from a file. The middle parameter is the size of the string. We use the sizeof operator for this purpose, which will in this case return 20, the size of the s array. Be aware that this way of using sizeof will only work for arrays, not for e.g. a pointer to dynamically allocated memory (see 12. Dynamic memory allocation). It is important that you use the correct value here, because if the value is too large, too many characters can be read so that the array is overflowed, with unpredictable consequences (e.g. a core dump or system crash). The fgets() function will return NULL if an error occurred, hence the above if() statement.
p = strchr(s,'\n');
if (p!=NULL)
*p = '\0';
The fgets() function does not automatically remove the '\n' character that terminates a line. That's why it is manually removed by the above code. The return value of strchr(s,'\n') will be a pointer to the first occurence of the character '\n' in the string, or NULL if none is found. So we store this return value in the char pointer p, and if it is not NULL we set the newline character it is pointing at to the '\0' terminating character ('\0' is an octal character code constant (see 2.4. Functions and types), and is therefore equivalent to 0. It is often used instead of plain 0 to make clear that it is used as a character constant), thereby effectively terminating the string in such a way that the newline character is stripped off.
printf("%s\n",s);
The just read string is printed. If all went well, this should print the original text again.
fclose(f);
Again, the file is closed.
if (remove("testfile") != 0)
{
printf("Error: unable to remove testfile\n");
return EXIT_FAILURE;
}
The file we used to store our string is no longer needed, so we remove it using the remove() function. The remove() function will return 0 if it is successful, and nonzero if an error occurs (hence the above if() statement).
return EXIT_SUCCESS;
If we got here, all was successful, so we return to the operating system with status EXIT_SUCCESS.
Note: fgets() and fputs() are used for reading/writing strings, usually from/to text files. When interfacing with binary files, often non-string data should be read/written. That's what the fread()/fwrite() functions are for (see 16. Overview of the standard library) [*].
[*] When reading/writing a specified file format you may be tempted to use fread()/fwrite() to read/write structures from/to a file. However, there may (and will!) often be padding bytes inbetween member variables and at the end of the structure. So in that case you'll have to resort to either reading/writing every member variable separately, or if portability isn't your greatest concern your system may support a way of turning off this padding.
For reading/writing single characters the fgetc()/fputc() functions are available (see 16. Overview of the standard library) [*]. There are also the equivalent getc()/putc() functions which may be implemented as a macro (see 13. Preprocessor macros/conditionals).
[*] When using these functions you should store the return value in a variable of type int, not of type char, because they can return EOF if an error occurred.11.3. The interact program
/* prog11-2.c: interact */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char name[20];
char buffer[10];
char *p;
int age, ok;
printf("Enter your name: ");
fflush(stdout);
if (fgets(name, sizeof name, stdin) == NULL)
{
printf("Error reading name from stdin\n");
return EXIT_FAILURE;
}
p = strchr(name,'\n');
if (p!=NULL)
*p = '\0';
fprintf(stdout, "Welcome, %s!\n", name);
do
{
printf("Enter your age [1-150]: ");
fflush(stdout);
if (fgets(buffer, sizeof buffer, stdin) != NULL
&& sscanf(buffer, "%d", &age) == 1
&& age>=1 && age<=150)
{
ok = 1;
}
else
{
ok = 0;
printf("Invalid age! Enter again...\n");
}
}
while (!ok);
printf("Your age now is %d. In 10 years your age will be %d.\n",
age, age+10);
return EXIT_SUCCESS;
}
The output of this program should be something like this:
Enter your name: John Doe
Welcome, John Doe!
Enter your age [1-150]: 32
Your age now is 32. In 10 years your age will be 42.
11.4. Using the standard I/O streams
char name[20];
char buffer[10];
char *p;
int age, ok;
Here we define an array of 20 characters, which will be used to hold the name string, and an array of 10 characters, which will be used as an input buffer for the age, another char pointer which will be used for the return value of strchr(), and two integer variables: one for the age, and one that will be used as a flag variable (0 for not OK, 1 for OK).
printf("Enter your name: ");
fflush(stdout);
As seen in 3.3. printf(), if we don't end the text with a newline (which we don't do here because we want to stay on the same line), we must add an explicit fflush(stdout). fflush() makes sure all output is sent through (it flushes the buffers). stdout is the standard output stream, which is a pointer to FILE that corresponds to the output device that is also used by printf() etc. [*]
[*] fflush() should only be used for output streams, because when used on input streams it produces undefined behaviour; on some systems it clears any pending input characters but this is definitely not standardized behaviour
if (fgets(name, sizeof name, stdin) == NULL)
{
printf("Error reading name from stdin\n");
return EXIT_FAILURE;
}
p = strchr(name,'\n');
if (p!=NULL)
*p = '\0';
An fgets() [*] with error checking, followed by the stripping of the newline (if any), very similar to what we did in the fileio program.
[*] If the user attempts to enter more characters then allowed, the excess characters will be left on stdin to be read later. This may be undesirable, but isn't dealt with here to keep the code simple.
The only difference is that this time we don't use a pointer to FILE which we opened ourselves, but the stdin standard input stream, which is a pointer to FILE that is already opened for us. The following are available:
stdin standard input stream (often keyboard)
stdout standard output stream (often screen)
stderr standard error stream (often screen)
[*] Some systems support more, such as e.g. stdprn for a standard printer stream, but this is not standard.
You may notice that for obtaining input from the stdin stream, instead of fgets() some people use the gets() function. However, this function does not accept a size parameter, so it can't control the input to fit within the array and will therefore happily overwrite any memory past the array thereby causing undefined behaviour (core dump, system crash, ...). Concerning the gets() function I have only one advice: do NOT use it. At all.
fprintf(stdout, "Welcome, %s!\n", name);
The fprintf() function is equivalent to the printf() function, except that its first parameter is a pointer to FILE where the output will be written to. In this case stdout is used, which is the default for printf() anyway, so this is equivalent to:
printf("Welcome, %s!\n", name);
Onto the next construct:
do
{
}
while (!ok);
The code inside this loop is repeated until the ok variable becomes non-zero at
Page : << Previous 13 Next >>