11.18 IO ASCII EOF
intro-to-computer-science-gtiit-06-2024.pdf
Example: Computing Powers of 2
/* Some powers of 2 are printed. */
#include <stdio.h>
int main(void) {
int i = 1, power = 1;
while (i <= 10) {
printf("%-6d", power *= 2);
i++;
}
printf("\n");
return 0;
}
The output of the program is:
2 4 8 16 32 64 128 256 512 1024
Example: Computing Powers of 2
/* Some powers of 2 are printed. */
#include <stdio.h>
int main(void) {
for (int i = 1, power = 2; i <= 10; i++) {
printf("%-6d", power);
power = power * 2;
}
printf("\n");
return 0;
}
The output of the program is:
2 4 8 16 32 64 128 256 512 1024
About printf()
Formatting
printf("%-6d", power *= 2);
- The placeholder
%-6d
indicates that the value is to be printed as a decimal integer with a field width of 6. (including the length of number) - The minus sign indicates that the value is to be left-adjusted in its field.
Try without the minus sign to align values to the right: %6d
.
Complete information about formatting is available in the manpage of printf()
:
$ man 3 printf
Standard Input and Standard Output
-
Consider the following program:
-
It reads characters from the standard input (normally the keyboard) with
scanf()
. - It writes each character twice to the standard output (normally the terminal screen) with
printf()
. -
%c
is the placeholder to read and print a single character.
Example Program:
#include <stdio.h>
int main(void) {
char c;
while (scanf("%c", &c) == 1) {
printf("%c", c);
printf("%c", c);
}
return 0;
}
If we input abcd
, then the computer read in sequence 'a''b''c'd''\n''EOF'
Return Value of scanf()
- When
scanf()
is successful, it returns the number of input items successfully matched and assigned. - This value can be fewer than provided for, or even zero, in the event of an early matching failure.
- In the example:
scanf("%c", &c)
-
Details:
-
It has a single placeholder (
%c
). - While
scanf("%c", &c)
returns1
, the reading of input is correct.
Example Program:
#include <stdio.h>
int main(void) {
char c;
while (scanf("%c", &c) == 1) {
printf("%c", c);
printf("%c", c);
}
return 0;
}
Redirection of Input and Output
- Suppose we compile the program into an executable
dbl_out
:
$ tcc -w dbl_out.c -o dbl_out
- We can use redirection to allow the executable to receive input and produce output in different ways:
$ ./dbl_out
: Input from keyboard (stdin), output to screen (stdout)
$ ./dbl_out < infile
: Input from file "infile", output to screen (stdout)
$ ./dbl_out > outfile
: Input from keyboard (stdin), output to file "outfile"
$ ./dbl_out < infile > outfile
: Input from file "infile", output to file "outfile"
Why does the loop end?
- When using this program with a standard input redirection:
$ ./dbl_out < infile
- The input file is consumed.
- When it is completely consumed, an End-of-File (EOF) signal is sent to the program, making
scanf()
return a special value (not1
).
Example Code:
#include <stdio.h>
int main(void) {
char c;
while (scanf("%c", &c) == 1) {
printf("%c", c);
printf("%c", c);
}
return 0;
}
The End-of-File Signal
- When the input is taken from a file, the end-of-file signal is automatically generated when the input file is completely fed to the program.
- When a program takes its input from the keyboard, it is necessary to generate an end-of-file signal manually.
- In Linux,
Ctrl+D
is the typical way to generate an end-of-file signal.
Control+C and End-of-File Are Not The Same
- The following command is of special interest:
$ ./dbl_out > outfile
- This command causes
dbl_out
to take its input from the keyboard (standard input) and to write its output in the fileoutfile
, provided that you issue an end-of-file signal when you are finished. - Important:
If, instead of typing
Ctrl+D
, you typeCtrl+C
to kill the program, nothing gets written intooutfile
!
getchar()
and putchar()
- Functions
getchar()
andputchar()
are defined in stdio.h
. -
Usage:
-
getchar()
is used to read a single character from the keyboard. -
putchar()
is used to write a single character to the screen. -
Common use cases:
-
Typically used to manipulate character data.
- Sometimes more convenient to use than
scanf()
andprintf()
.
getchar()
Example
int main() {
int input;
input = getchar(); // Read a single character from input
if (input == 'a' || input == 'e' || input == 'i' || input == 'o' || input == 'u') {
printf("We have a vowel!\n");
} else {
printf("This is not a vowel.\n");
}
return 0;
}
Example with getchar()
and putchar()
int main(void) {
int c;
// Continuously read characters until EOF is encountered
while ((c = getchar()) != EOF) {
putchar(c); // Output the character
putchar(c); // Output the character again
}
return 0;
}
Example with getchar()
and putchar()
int main(void) {
int c;
c = getchar(); // Read the first character
while (c != EOF) { // Continue until EOF is encountered
putchar(c); // Output the character
putchar(c); // Output the character again
c = getchar(); // Read the next character
}
return 0;
}
ASCII
The American Standard Code for Information Interchange (ASCII) is a standard that sets how to interpret integers from 0 to 127 (0x00 to 0x7F in hexadecimal) as printable characters and control codes.
getchar()
and Integer Constants According to ASCII
int main() {
int input;
input = getchar();
if (input == 97 || input == 101 || input == 105 || input == 111 || input == 117)
printf("We have a vowel!\n");
else
printf("This is not a vowel.\n");
return 0;
}
getchar()
and Integer Constants (in Hexadecimal)
int main() {
int input;
input = getchar();
if (input == 0x61 || input == 0x65 || input == 0x69 || input == 0x6F || input == 0x75)
printf("We have a vowel!\n");
else
printf("This is not a vowel.\n");
return 0;
}
Why is c
of type int
and not char
?
-
EOF
is defined in stdio.h
as-1
. -
The actual value of
EOF
is system-dependent. - Value
-1
is often used, but it is better to useEOF
and let the filestdio.h
define its concrete value. -
getchar()
evaluates to anint
value, notchar
. -
The value used to signal the end of the file cannot be a character value (e.g.,
-1
). - Because
c
is anint
, it can hold all possible character values and the special valueEOF
.
int main(void) {
int c;
while ((c = getchar()) != EOF) {
putchar(c);
putchar(c);
}
return 0;
}
ASCII: Observations
-
The most commonly used sequences of characters exist in ASCII as sequences:
-
Characters
'0'
to'9'
(digits) - Characters
'A'
to'Z'
(uppercase Latin alphabet) - Characters
'a'
to'z'
(lowercase Latin alphabet)
Checking whether some character is a digit, an uppercase letter, or a lowercase letter can be done with a condition that checks for an interval.
Example: Capitalizing Letters
#include <stdio.h>
int main(void) {
int c;
while ((c = getchar()) != EOF) {
if (c >= 'a' && c <= 'z') {
putchar(c + 'A' - 'a');
} else {
putchar(c);
}
}
return 0;
}
No Need to Learn ASCII Codes
- It is not necessary to memorize the integer ASCII codes that correspond to characters.
- It’s generally enough to remember that character codes are integers, and groups of related commonly used symbols are organized in sorted intervals.
Some Character Constants and Their Corresponding Integer Values:
Character Constants | Corresponding Values |
---|---|
'a' , 'b' , 'c' … 'z' |
97, 98, 99 … 122 |
'A' , 'B' , 'C' … 'Z' |
65, 66, 67 … 90 |
'0' , '1' , '2' … '9' |
48, 49, 50 … 57 |
'&' , '*' , '+' |
38, 42, 43 |