Input and Output (printf, fopen, fprintf, fgets, fscanf, fclose)

advertisement
clark
cs1713
syllabus
lecture notes
programming assignments
printf
This prints output based on a specification.
printf(specification, value1, value2, …);
The specification contains strings and format codes. Some format codes:
%s
show a null terminated string (must pass an address)
%d
show an integer value
%ld
show a long integer value
%f
show a floating point value
%lf
show a double value
%e
show a floating point value using scientific notation
%c
show single character
%x
show a hex value
%%
show a %
%p
print a pointer (must pass an address)
We use \n to cause the output to do a line feed.
A format code can be in the following form:
flag minWidth precision lengthModifier code
We go over this in more detail later in the semester, but here are some helpful
examples:
%10.2lf where 10 is the minWidth, 2 is the precision, l is the
lengthModifier (long floating point), and f is the code.
%.2lf
where this is the same as above, but it doesn't have a
minWidth.
%10s where 10 is the minWidth and s is the code. The value will be
right-justified.
%-10s where - specifies to left-justify, 10 is the minWidth, and s is
the code. The value will be left-justified.
%5.10s where 5 is the minWidth, 10 is the maximum width, and s is
the code. The value will be right-justified. If the
corresponding value is longer than 10 characters, the excess
characters will be truncated from the end.
homework
set up
char szName[21] = "Bob Wire";
int iOrderQuantity = 5;
double dUnitCost = 7.25;
char
cGender = 'F';
printf("name is %s\n", szName);
printf("Order Quantity is %d\n", iOrderQuantity);
printf("Unit cost is %lf\n", dUnitCost);
printf("Gender is %c\n", cGender);
Output:
name is Bob Wire
Order Quantity is 5
Unit cost is 7.250000
Gender is F
printf("Unit
printf("Unit
printf("Unit
printf("Unit
printf("Unit
Cost
Cost
Cost
Cost
Cost
in
in
in
in
in
10.2 is '%10.2lf'\n", dUnitCost);
9.3 is '%9.3lf'\n", dUnitCost);
.2 is '%.2lf'\n", dUnitCost);
-10.2 is '%-10.2lf'\n", dUnitCost);
-9.3 is '%-9.3lf'\n", dUnitCost);
printf("Name '%10s' and '%-10s'\n", szName, szName);
Output:
Unit Cost in 10.2 is '
7.25'
Unit Cost in 9.3 is '
7.250'
Unit Cost in .2 is '7.25'
Unit Cost in -10.2 is '7.25
'
Unit Cost in -9.3 is '7.250
'
Name ' Bob Wire' and 'Bob Wire '
Exercise: Using the Customer typedef, assume the customerM array has
already been populated and the number of customers is in iCustomerCnt.
Print an array of customers with a heading and the values in a table format.
Hint: use the same fieldwidth for the column heading and the value.
Instead of this for the heading:
printf("ID
Name
Balance\n");
use
printf("%-6s %-19s %10s\n", "ID", "Name", "Balance");
typedef struct
{
int iID;
// Assume it is 6 digits
char szName[20];
// 19 characters
double dBalance;
// allow 10 digits with 2 to the right of the decim
} Customer;
Customer customerM[30];
int iCustomerCnt;
int i;
// assume customerM and iCustomerCnt have been initialized.
// print the column heading
// print the contents of the array
Special constants
\n
line feed
\t
tab
\f
form feed
\"
double quote
\\
back slash
\a
alert
Redirecting output to a file
In Unix, you can specify where to direct the standard output by specifying
command > filename
You can also use fprintf which has an additional parameter for the file.
fprintf(file, specification, value1, value2, …);
The file should be opened with an fopen().
// Suppose the executable is one.exe. On the command line,
// we can specify where to direct the output when we run
// the program.
one.exe >myOutput.txt
#define OUT_FILE "myoutFile.txt"
FILE *fileOut;
fileOut = fopen(OUT_FILE, "w");
if (fileOut == NULL)
{
fprintf(stderr, "Could not open %s\n", OUT_FILE);
return 2;
}
fprintf(fileOut, "name is %s\n", szName);
fopen
FILE *fopen(char *pszFileName, char *pszMode)
fopen returns a FILE pointer to the file that was opened or NULL if it wasn't
successful.
Parameters:
 pszFileName is the name of the file to open. Sometimes it is necessary
to put the full path file name. (e.g., "~/cs1713/examavgInput.txt")
 pszMode is a string tells fopen how to open the specified file:
"r" open file as text stream input. If the file doesn't exist, fopen will
return NULL.
"w" open file for text stream output. It will create the file if it doesn't
already exist and overwrite the file it does already exist.
"a" open an existing file to append text to it.
"w+" open a file for read and write.
"rb" open file as binary input. If the file doesn't exist, fopen will
return NULL.
"wb" open a file for binary output.
"ab" open an existing file to append binary data to it.
"wb+" open a file for binary read and write
FILE *fileIn;
fileIn = fopen("~/cs1713/cs1713p2Input.txt", "r");
if (fileIn == NULL)
{
fprintf(stderr, "Could not open %s\n"
, "~/cs1713/cs1713p2Input.txt");
return 3;
// input file error
}
fgets and scanf
These are used to receive stream input.
fgets(stringVariable, maxLength, file); This reads from the specified file until
either maxLength - 1 characters are read or until a line feed character is
encountered.
scanf(formatString, address1, address2, …);
Facts about scanf():
 must be passed addresses since it stores its results in those addresses
 returns the number of successful conversions from its input to those
addresses
 null terminates resulting strings
#include <stdio.h>
int main(int argc, char *argv[])
{
struct
{
char szStockNumber[21];
double dInventoryUnitPrice;
int iStockCount;
} stock;
char *pszGetsResult;
// result of fgets
char szInputBuffer[100];
// entire input line
int iScanfCount;
pszGetsResult = fgets(szInputBuffer, 100, stdin);
if (pszGetsResult == NULL)
{
printf("ERROR: could not read data file\n");
return 3;
// input error
}
iScanfCount = sscanf(szInputBuffer, "%s %lf %d"
, stock.szStockNumber
, &stock.dInventoryUnitPrice
, &stock.iStockCount);
if (iScanfCount < 3)
{
printf("ERROR: only read %d values\n"
, iScanfCount);
return 3;
}
printf("Stock Number = %s, Unit Price = %.2lf, Stock Count = %d\n"
, stock.szStockNumber
, stock.dInventoryUnitPrice
, stock.iStockCount);
return 0; // normal exit
Problems can be avoided by using fgets to get a line of input data and store it
in a buffer. sscanf can be used to scan the data from that buffer and store the
results in specified variables.
}
scanf format codes do not have the same form as printf. There are several
forms:
maxSize lengthModifier code
[acceptValues]
[^delimiters]
For the first form (maxSize code) of scanf format codes:
 maxSize specifies the maximum number of characters to read.
 After scanf sees a non-white space character, the next white space
(blank, tab, newline) character will be the delimiter for the value.
 If you want to skip over a delimiter after you read a value, show the
delimiter in the formatString. Blanks in the formatString will match
zero to many white space characters.
 lengthModifier can be a letter l to specify a longer value (e.g., long,
double).
 The values for (lengthModifier and) code include:
%s
read a string and null terminate it
%d
read an integer value
%ld
read a long integer value
%f
read a floating point value
%lf
read a double value
%e
read a floating point value using scientific notation
%c
read single character
%x
read a hex value
%n
receives an integer value of the number of characters read so
far
 Notice that scanf doesn't have a precision. Do not specify %10.2lf.
Format codes like "10.2lf" do not work with scanf since it doesn't
understand the ".2".
Seq
1
2
3
4
5
6
7
8
9
10
11
12
13
szInputBuffer
Format
Cnt
123456 123 45.67
%s %d %lf
3
123456 123 45.67
%5s %d %lf
3
123456 123 45.67
%[1-9] %d %lf
3
123456 123 45.67
%[1-9],%d,%10lf
1
comma in format didn’t match space
123456,123,45.67
%[1-9],%d,%10lf
3
123456,123,45.67
%[^,],%d,%10lf
3
123456,123,45.67
%6[^,] ,%d,%10lf
3
123456 , 123,45.67
%[^,],%d,%10lf
3
123456 , 123,45.67
%[^, ],%d,%10lf
1
comma in format didn't match first space
123456 , 123,45.67
%[^, ] ,%d,%10lf
3
123456 , 123,45.67 %[^, ] ,%d,%10lf
3
123456 , 123,45.67 %[^, ] ,%d,%10lf 3
123456,123,45.67
%[^,] %d %10lf
1
comma in data isn't a valid numeric value for
szV1
'123456'
'12345'
'123456'
'123456'
iV2
123
6
123
n/a
dV3
45.67
123.00
45.67
n/a
'123456'
'123456'
'123456'
'123456 '
'123456'
123
123
123
123
n/a
45.67
45.67
45.67
45.67
n/a
'123456'
'123456'
'123456'
'123456'
%d
123
123
123
n/a
45.67
45.67
45.67
n/a
For second form ([acceptValues]) of scanf format codes:
 acceptValues is a list of acceptable values. To specify a range of
characters, a dash can be used.

Some interesting scanf format codes:
%[a-z]
reads the lower case characters a-z and stops when any other
character is read.
%[a-zA-Z] reads any alphabetic character and stops when any other character
is read.
%[^,]
reads everything but commas into the corresponding variable. This
means that input terminates with a comma instead of a space.
%20[^\n] reads everything but line feeds into the corresponding variable.
This means that the input terminates with a line feed or \0. It
places a maximum of 20 characters (plus a \0) in the variable.
// sscanf gets its input from a variable (1st argument)
char szLongAddress [] = "123 Dirt Rd\n";
long lStreetNumber;
char szStreet[11];
iScanfCount = sscanf(szInputStr, "%ld %10[^\n]\n"
, &lStreetNumber
, szStreet);
Warning!!! Warning !!! Warning !!!
scanf() must be passed addresses. Numeric variables pass values
instead of addresses. You must pass the address of numeric
variables using an &. This is also necessary for single byte
variables. Since the addresses of arrays are automatically
passed, it isn't necessary to use the & with arrays.
int iOrderQuantity;
char szCustomerId[10];
iScanfCount = scanf("%s %d", szCustomerId, iOrderQuantity);
scanf can overwrite memory!!
We didn't show gets(stringVariable) because it is even less
safe. It isn't passed the maxLength.
fclose
fclose(FILE *pfileVariable) is used to close a file, completing the I/O and freeing
internal memory used for the file.
Since iOrderQuantity is numeric, we must pass its address. In this exam
we passed its value which scanf will attempt to use as an address.
Depending on that value, it might have an addressing error or store a v
at that questionable address.
int iOrderQuantity;
char szCustomerId[10];
char szAddress[300];
iScanfCount = scanf("%s %d", szCustomerId, &iOrderQuantity);
With the data containing "012345678901 100", the value would continue p
szCustomerId and corrupt szAddress. Where is the zero byte?
See the CommandArg_c.txt for a full example using files.
Download