SPR 23 - 04 - DesignLogical
SPR 23 - 04 - DesignLogical
2
Recall: The charcount Program
The program: charcount.c
#include <stdio.h>
/* Write to stdout the number of
chars in stdin. Return 0. */
int main(void) {
int c;
int charCount = 0;
c = getchar();
while (c != EOF) {
charCount++;
c = getchar();
}
printf("%d\n", charCount);
return 0;
3
}
stdio.h Features (types, constants, variables)
$ man stdio.h
NAME
stdio.h -- standard buffered input/output
SYNOPSIS
#include <stdio.h>
DESCRIPTION
The <stdio.h> header shall define the following data types through typedef:
FILE A structure containing information about a file.
size_t As described in <stddef.h>.
The <stdio.h> header shall define the following macro which shall expand to an
integer constant expression with type int and a negative value:
EOF End-of-file return value.
The <stdio.h> header shall define the following macros which shall expand to
expressions of type ``pointer to FILE'' that point to the FILE objects associated,
respectively, with the standard error, input, and output streams:
stderr Standard error output stream.
4 stdin Standard input stream.
stdout Standard output stream.
stdio.h Features (functions)
$ man stdio.h
...
The following shall be declared as functions and may also be defined as macros.
Function prototypes shall be provided.
int fclose(FILE *);
int feof(FILE *);
int fflush(FILE *);
int fgetc(FILE *);
FILE *fopen(const char *restrict, const char *restrict);
int fprintf(FILE *restrict, const char *restrict, ...);
int fscanf(FILE *restrict, const char *restrict, ...);
int getc(FILE *);
int getchar(void);
int printf(const char *restrict, ...);
int putc(int, FILE *);
int putchar(int);
int scanf(const char *restrict, ...);
5
Character Input/Output (I/O) in C
Design of C:
• Does not provide I/O facilities in the language
• Instead provides I/O facilities in standard library, declared in stdio.h
• Constant: EOF
• Data type: FILE (described later in course)
• Variables: stdin, stdout, and stderr
• Functions: …
Reading characters
• getchar() function with return type wider than char (specifically, int)
• Returns EOF (a special non-character int) to indicate failure
• Reminder: there is no such thing as "the EOF character”
Writing characters
• putchar() function accepting one parameter
6 • For symmetry with getchar(), parameter is an int
iClicker Question
Q: There are other ways to charcount – which is best?
for (c = getchar(); c != EOF; c = getchar())
A.
charCount++;
Functionality
• Read all chars from stdin
• Convert each lower-case alphabetic char to upper case
• Leave other kinds of chars alone
• Write result to stdout
stdin stdout
Does this work? DOES THIS WORK?
It seems to work. upper IT SEEMS TO WORK.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 NUL HT LF
16
32 SP ! " # $ % & ' ( ) * + , - . /
48 0 1 2 3 4 5 6 7 8 9 : ; < = > ?
64 @ A B C D E F G H I J K L M N O
80 P Q R S T U V W X Y Z [ \ ] ^ _
96 ` a b c d e f g h i j k l m n o
112 p q r s t u v w x y z { | } ~
#include <stdio.h>
int main(void)
{
int c;
while ((c = getchar()) != EOF) {
if ((c >= 97) && (c <= 122))
c -= 32;
putchar(c);
} What’s wrong?
return 0;
}
10
EBCDIC
Extended Binary Coded Decimal Interchange Code (/ˈɛbsɪdɪk/)
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 NUL HT
16
32 LF
48
Partial map
64 SP . < ( + |
80 & ! $ * ) ;
96 - / | , % _ > ?
112 ` : # @ ' = "
128 a b c d e f g h i {
144 j k l m n o p q r }
160 ~ s t u v w x y z
176
192 A B C D E F G H I
208 J K L M N O P Q R
224 \ S T U V W X Y Z
240 0 1 2 3 4 5 6 7 8 9
11
Character Literals
Single quote syntax: 'a' is a value of type char with the value 97
Use backslash to write special characters
• Examples (with numeric equivalents in ASCII, EBCDIC):
12
An A1 FAQ:
13
upper Version 2
#include <stdio.h>
int main(void)
{
int c;
while ((c = getchar()) != EOF) {
if ((c >= 'a') && (c <= 'z'))
c += 'A' - 'a'; Arithmetic
putchar(c); on chars?
}
return 0;
}
14
What’s wrong now?
EBCDIC
Extended Binary Coded Decimal Interchange Code
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 NUL HT
16
32 LF
48
Partial map
64 SP . < ( + |
80 & ! $ * ) ;
96 - / | , % _ > ?
112 ` : # @ ' = "
128 a b c d e f g h i {
144 j k l m n o p q r }
160 ~ s t u v w x y z
176
192 A B C D E F G H I
208 J K L M N O P Q R
224 \ S T U V W X Y Z
240 0 1 2 3 4 5 6 7 8 9
15 Note: Lower case not contiguous; same for upper case
upper Version 3
#include <stdio.h>
#include <ctype.h>
int main(void)
{
int c;
while ((c = getchar()) != EOF) {
if (islower(c))
c = toupper(c);
putchar(c);
}
return 0;
}
16
iClicker Question
Q: Is the if statement really necessary?
SYNOPSIS
#include <ctype.h>
int toupper(int c);
int tolower(int c);
DESCRIPTION
toupper() converts the letter c to upper case, if possible.
tolower() converts the letter c to lower case, if possible.
RETURN VALUE
The value returned is that of the converted letter,
or c if the conversion was not possible.
18
iClicker Question
Q: Is the if statement really necessary?
#include <stdio.h>
A. Yes, necessary
#include <ctype.h>
for correctness. int main(void)
{
B. Not necessary, int c;
while ((c = getchar()) != EOF) {
but I’d leave it in. if (islower(c))
c = toupper(c);
C. Not necessary, putchar(c);
}
and I’d get rid of it.
return 0;
}
19
Aside: Unicode
Back in 1970s, English was the only language in the world[citation needed]
so we all used this alphabet [citation needed] :
ASCII:
American Standard Code
for Information Interchange
20
Modern Unicode
When C was designed, characters fit into 8 (really 7) bits, so C’s chars are 8 bits long.
When Java was designed, Unicode fit into 16 bits, so Java’s chars are 16 bits long.
Then this happened:
https://xkcd.com/1953/
21
Result: modern systems use variable length (UTF-8/16/32) encoding for Unicode.
Recall: The upper1 Program
Functionality
• Read all chars from stdin
• Capitalize the first letter of each word
• “cos 217 rocks” ⇒ “Cos 217 Rocks”
• Write result to stdout
stdin stdout
cos 217 rocks Cos 217 Rocks
Does this work? upper1 Does This Work?
It seems to work. It Seems To Work.
What we need: maintain extra information, namely “in a word” vs “not in a word”
• Need systematic way of reasoning about what to do with that information
22
upper1 Version 3
#include <stdio.h> int main(void)
#include <ctype.h> {
enum Statetype {NORMAL, INWORD}; int c;
enum Statetype state = NORMAL;
enum Statetype handleNormalState(int c) while ((c = getchar()) != EOF) {
{ switch (state) {
enum Statetype state; case NORMAL:
if (isalpha(c)) { state = handleNormalState(c);
putchar(toupper(c)); break;
state = INWORD; case INWORD:
} else { state = handleInwordState(c);
putchar(c); break;
state = NORMAL; }
} }
return state; return 0;
} }
Problem:
•The program works, but…
•No comments
Solution:
•Add (at least) function-level comments
24
Function Comments
int main(void) {
27 /* Use a DFA approach. state indicates the DFA state. */
enum Statetype state = NORMAL;
Agenda
Simple C Programs
•charcount
• character I/O
•upper (ctype library)
• portability concerns
• char details
•upper1 (switch statements, enums, functions)
• internal documentation (i.e., comments)
28
Declaring Variables
Motivation:
• Declaring variables allows compiler to check “spelling”
• Declaring variables allows compiler to allocate memory more efficiently
• Declaring variables’ types produces fewer surprises at runtime
• Declaring variables requires more from the programmer
• Extra verbiage
• Type foresight
• “Do what I mean, not what I say”
29
Declaring Variables
Examples:
int i;
int i, j;
int i = 5;
const int i = 5; /* value of i cannot change */
static int i; /* covered later in course */
extern int i; /* covered later in course */
30
Declaring Variables
{ {
int i; int i;
/* Non-declaration int j;
stmts that use i. */ /* Non-declaration
… stmts that use i. */
int j; …
/* Non-declaration /* Non-declaration
stmts that use j. */ stmts that use j. */
… …
} }
31
Illegal in C89 Legal in C89
Agenda
Simple C Programs
•upper (character data and I/O, ctype library)
• portability concerns
•upper1 (switch statements, enums, functions)
• DFA program design
32
Logical Data Types
@lunarts
•Conventions:
• Statements (if, while, etc.) use 0 ⇒ FALSE, ≠0 ⇒ TRUE
• Relational operators (<, >, etc.) and logical operators (!, &&, ||) produce the result 0 or 1
33
Logical Data Type Shortcuts
Using integers to represent logical data permits shortcuts
…
int i;
…
if (i) /* same as (i != 0) */
statement1;
else
statement2;
…
i = (1 != 2) + (3 > 4);
34
iClicker? More like iBrainteaser!
Q: What is int i set to in the following code?
…
int i; What happens
… in Java?
i = 0;
…
if (i = 5)
statement1; What happens
… in C?
36
Next time … numbers! (Bigger than 127.)
37
Mick Haupt