Practical C Programming by Steve Oualline CS550 Operating Systems Tic Tac Toe Example See class website http catpagesnwmissouriedu m monismi cs550 exampleshtml Compilation ID: 568263
Download Presentation The PPT/PDF document "C Programming Day 4 based upon" is the property of its rightful owner. Permission is granted to download and print the materials on this web site for personal, non-commercial use only, and to display it on your personal computer provided you do not modify the materials and that you retain all copyright notices contained in the materials. By downloading content from our website, you accept the terms of this agreement.
Slide1
C Programming Day 4 based upon Practical C Programming by Steve Oualline
CS550
Operating SystemsSlide2
Tic Tac Toe Example
See class website
http://
catpages.nwmissouri.edu
/m/
monismi
/cs550/
examples.html
Compilation
gcc
TicTacToe.c
tttmain.c
-
ansi
-o
ttt.exeSlide3
Tic Tac Toe Makefile
Using a
makefile
for compilation
use
make
to compile
Makefiles
are similar to a script to compile programs
We break many of our programs into groups of files
header files with function prototypes (.h files)
.c files with function definitions
file or files containing main function(s)Slide4
Example Makefile
Example with one .c file
CC=
gcc
CFLAGS=-
ansi
prog3 : prog3.c
$(CC) $(CFLAGS) -o prog3 prog3.c
#There must be a tab on the line following prog3
#
(the target)
#Comments are preceded with a pound sign/hash
#
symbol (#)Slide5
More on MakefilesIf
you name your
makefile
"
makefile
", then to compile you
simply type
the command
make
.
Otherwise
, you need to specify the name
of your
makefile
as follows:
make
-f
my_makefile_nameSlide6
Tic Tac Toe Makefile
CC=
gcc
CFLAGS=-
ansi
#executable first, then
sources
ttt
:
TicTacToe.o
tttmain.o
$(CC) $(CFLAGS) -o
ttt
TicTacToe.o
tttmain.o
tttmain.o
:
TicTacToe.h
tttmain.c
$(CC) $(CFLAGS) -c
tttmain.c
TicTacToe.o
:
TicTacToe.h
TicTacToe.c
$(CC) $(CFLAGS) -c
TicTacToe.cSlide7
More on functionsvoid
functions
functions with parameters
return types
call by value
c
all by referenceSlide8
Call by value
int
min(
int
a,
int
b)
{
if(a < b)
return a;
return b;
}
The values of a and b are copied from those of the formal parameters.Slide9
Call by Reference Example for Arrays
#include <
stdio.h
>
//pass in the address of the
array
int
length(char[]);
//Call by
reference
void
changeChar
(char [],
int
, char);
//Call by value
void
changeInt
(
int
,
int
);Slide10
Example main Function
int
main(
int
argc
, char **
argv
){
char line[100];
while(1) {
fgets
(line,
sizeof
(line),
stdin
); //Read a line
line[
strlen
(line) - 1] = '\0'; //Remove '\n'
printf
("The length of this string is %d\n", length(line));
changeChar
(line, 2, 'x'); //Call the function
printf
("%s\n", line); //Print the modified string
int
q = 5;
changeInt
(q, 2); //What happens with call by value?
printf
("The value of q is %d\n", q);
}
}Slide11
Functions for Example
int
length(char
str
[]){
int
i
;
for(
i
= 0;
str
[
i
] != '\0';
i
++);
return
i
;
}
//Call by Reference
void
changeChar
(char
str
[],
int
pos
, char
new_char
){
str
[
pos
] =
new_char
;
}
//Call by value
void
changeInt
(
int
z,
int
y) {
z = y;
}Slide12
RecursionSame as in JavaWe won’t review this
Use as necessarySlide13
Macros#define
lets you define a macro
#define
works as a global text editor in your programSlide14
Macro Examples
#
define
PI 3.14
#
define
ENDIF }
if
(x == y)
{
...
ENDIFSlide15
Macro Examples
#
define
IF
if
(
#
define
THEN ){
IF x == y THEN
...
ENDIF
#
define
SQR(x) ((x)*(x)) //
Safe
macro
SQR(5 + 7)
#
define
SQR(x) (x*x) //
Unsafe
macroSlide16
Character MacrosCharacter macros are in
#include <
ctype.h
>
includes things like
is_digit
(x)
The text of the macros below is inserted in your code in place of the name of the macro.
#define
is_lower
(x) ((x) >= 97 && (x) <= 122)
#define SWAP(
x,y
) {\ //continue to next line
char temp; \
temp = (x); \
(x) = (y); \
(y) = temp; }Slide17
StructuresStructures are used to group data together
struct
Student
{
char
fName
[100];
char
lName
[100];
int
num919;
char classification[30];
} s1, s2; //Create a
struct
of type
//
struct
student and two structuresSlide18
Structures
struct
Student s3; //Create another
struct
Student
typedef
struct
Student
Student; //Rename
struct
Student as Student
Student s4; //Create another student
typedef
double
mydouble
;
strcpy
(s4.classification, "Freshman");
s4.num919 = 919000000;
s3.num919 = 23;
Student
slist
[100];
slist
[53].num919 = 919111111;Slide19
More on StructuresGenerically, a structure appears as follows:
struct
struct_type_name
{
variable_list
}
names_for_structs
;
both the type name and names are optional.
More examples:
struct
student {
char
fName
[100];
char
lName
[100];
int
num919;
};Slide20
More on Structures
typedef
struct
student student;
int
main(
int
argc
, char **
argv
){
student
sArr
[5];
strcpy
(
sArr
[0].
fName
, "David");
strcpy
(
sArr
[1].
fName
, "John");
...
}Slide21
More on typedef
typedef
old_type
new_type
; //Redefine an old type as a
//new one.
typedef
double dollars;
dollars wallet; double a;
wallet = 100.0;
wallet = wallet + 5;
a = 10;
wallet = a + wallet;
a = 3/4; //a is assigned 0
a = (double) 3 / 4; //a is assigned 0.75
//Recall types are
upcast
double <--
int
<-- charSlide22
<time.h>
time_t
is an
unsigned
int
time(0)
returns a value of type
time_t
int
a;
a = time(0) + 5; //Casting down
time(0)
is cast as an
int
, and will cause a compiler warning in most
cases.
a = (
int
) time(0) + 5; //avoids the warningSlide23
PointersPointers allow you to store and manipulate memory addresses.
Pointers are fun!!!
Pointers are used for arrays
int
arr
[5];
//
arr
contains the memory address of
//the beginning of the array
arr
Pointers are also seen in a different form:
type * name;
//"type *" indicates the address of a type
This can also be read as a pointer to memory type "type".Slide24
Super Important Example
int
* p; //A pointer to an integer
p = NULL; //NULL is in <
stdlib.h
> and is
//of
int
value zero or '\0’
int
a = 7;
p = &a; //The ampersand means "address of", so
/
/p is assigned
the address of a.
printf
("%d is a\n", a);
printf
("%d is a\n", *p); //get the value stored
//at the address in p
The * is the dereferencing operator
Dereferencing NULL will result in a segmentation fault. You cannot access memory address 0.Slide25
PointersPointers allow for call by reference and dynamic memory allocation
Use of the dereferencing operator (the * operator) to access the contents of a pointer
int
a = 8;
int
* b = &a; //Store the address of a in b
printf
("a is %d\n", a);
printf
("a is %d\n", *b);Slide26
PointersYou can try to print the contents of a static address, but it won't
always
work because most operating systems protect their memory.
printf
(”
C
ontents
of address 190 are %d\n", *((
int
*) 190) );
/
/This will work, though because
memory
//addresses
are unsigned
ints
printf
("%u is b\n", b);
printf
("%u is also b\n", &a);Slide27
Constant Pointers
Notice that you can't change the value of a constant.
const
int
result = 10;
result = 5; // causes an error
const
char *
str_ptr
= "Forty-nine";
const
char
arr
[28] = "Eighty-2";
str_ptr
=
arr
; //This is ok because the data is constant
str_ptr
[7] = 'B'; //Not ok because the data is constant
char *
const
name_ptr
= "Test pointer";
name_ptr
=
str_ptr
; //Won't work b/c the pointer is constant
name_ptr
[7] = 'b'; //will work b/c the pointer is constantSlide28
Call by ReferenceIn C there is no real call by reference.
It is simulated by passing the values of addresses to functions, that is, by passing pointers.Slide29
Call by Reference Example
void swap(
int
* a,
int
* b
){ //This swaps two variables
int
temp;
temp = *a
; //Dereference the address stored in a
*a = *b
;
*b = temp;
}
int
main(
int
argc
, char **
argv
){
int
x, y;
x = 5; y = 9;
printf
("x is %d and y is %d\n", x, y);
swap(&x, &y);
printf
("x is %d and y is %d\n", x, y);
return 0;
}Slide30
Scope RulesThe scope of an identifier (a variable) is the part of the program where the variable is accessible.
Normally, the basic rule for scope is that variables are only accessible within the block (set of curly brackets) in which they were declared.
Notice that variables declared in an inner block with the same
name as
those in an outer block take precedence within the inner block
.Slide31
Scope Example
int
main(
int
argc
, char **
argv
){
int
a = 2;
int
* p = a;
printf
("%d is a\n");
{
int
a = 7; //This a is different
printf
("%d is a\n", a);
printf
("%d is a from the outer block\n", *p);
}
printf
("%d is a\n");
return 0;
}Slide32
Void Pointers A void pointer can point to any type of memory.
These are essential for dynamic memory allocation.
void * name;Slide33
Void Pointer Example
int
main(
int
argc
, char **
argv
){
int
* p, * q, r;
double * x;
void * a;
r = 1000;
p = q = (
int
*) r;
a = (void *) r;
p = q = a;
x = a;
return 0;
}Slide34
Pointers and Arrays
int
arr
[6] = {1,2,3,4,5,6};
*(
arr
+ 2) = 56;
//Notice 2 is multiplied by
//
sizeof
(
int
)
What really happens is that we get
*(
arr
+ 2*
sizeof
(
int
))
the compiler takes care of the
sizeof
operation for us.Slide35
Example Part 1Loops used to sum up the values of an array using dereferencing instead of brackets.
*
arr
-->
arr
[0]
*(arr+1) -->
arr
[1]
...
int
sum = 0,
i
;
for(
i
= 0;
i
< N;
i
++)
sum += *(
arr
+
i
);Slide36
Example Part 2
//is the same as
for(
i
= 0;
i
< N;
i
++)
sum +=
arr
[
i
];
int
arr
[N] = {...};
int
* p;
int
sum = 0;
for(p =
arr
; p < &
arr
[N]; p++)
sum += *pSlide37
Dynamic Memory AllocationIn Java & C++,
new
is used for dynamic memory allocation.
You can use
delete
in C++ to free dynamic memory.
In C, we will use
malloc
and
calloc
for allocation and
free
for
deallocation
malloc
(
sizeof
(type)) //Specify the amount of memory
calloc
(n, object size) //Specify the number of items and type size
free((void *)
name_of_pointer
) //Free memory and cast as void
ptrSlide38
Examples
int
*a, n;
scanf
("%d", &n); //Read an
int
into n
if(n > 0)
//Allocate an array of size
n
a = (
int
*)
calloc
(n,
sizeof
(
int
));
else {
//print error and exit
printf
("Error: invalid array size.\n");
exit(0);
}
a[0] = 32;
...
free((void *) a); //
Deallocate
aSlide39
Card Example
struct
card {
char suit; //one byte
int
face_value
; //four bytes
};
typedef
struct
card card;
card * deck;Slide40
Card Example Continued
int
main(
int
argc
, char **
argv
)
{
int
size;
scanf
("%d", &size);
if(size > 0)
deck = (card *)
calloc
(size,
sizeof
(card));
/
/size of card is 5
deck[
i
].suit = 'd'; //d for diamonds
deck[
i
].
face_value
= 12;
/
/12th card (king if zero based)
free((void *) deck);
}Slide41
malloc, memset
, and
memcpy
Using
malloc
to allocate variables one at a time
int
* p; //Declare pointers p and q
int
* q;
//Allocate an
int
array and store its address in p
p = (
int
*)
malloc
(
sizeof
(
int
));
*p = 98; //Store 98 at memory location p
free((void *) p);
//Free (
deallocate
) the arraySlide42
malloc, memset, and
memcpy
//allocate an array of size n to p with
malloc
p = (
int
*)
malloc
(
sizeof
(
int
)*n);
q = (
int
*)
malloc
(
sizeof
(
int
)*n)
;
//Set all elements of p to zero
memset
(p, 0,
sizeof
(
int
)*n);
//make a copy of p in q using
//
memcpy
(
dest
, source, number of bytes
to
//copy
)
memcpy
(q, p,
sizeof
(
int
)*n);
free((void *) p);
free((void *) q);Slide43
Allocating Multi-Dimensional Arrays
//Declare a 2D array
int
**
mdArr
;
int
i
;
int
j;
//Allocate dimension 1
mdArr
= (
int
**)
calloc
(2,
sizeof
(
int
*));
for(
i
= 0;
i
< 2;
i
++) //Dim 2
mdArr
[
i
] = (
int
*)
calloc
(3,
sizeof
(
int
));Slide44
Allocating Multi-Dimensional Arrays
//Initialize
for(
i
= 0;
i
< 2;
i
++)
for(j = 0; j < 3; j++)
mdArr
[
i
][j] = j;
/
/
Deallocate
for
(
i
= 0;
i
< 2;
i
++)
free((void *)
mdArr
[
i
]);
free
((void *)
mdArr
);Slide45
Linked Lists
struct
element
{
int
data; //Data
struct
element * next;
//Next pointer
};
typedef
struct
element element;Slide46
Linked Lists
int
main(
int
argc
, char **
argv
)
{
element * head;
element *
cur_ptr
;
int
val
;
head = NULL; //Pointer to list
scanf
("%d", &
val
);Slide47
Linked Lists
while(
val
!= -999)
{
if(head == NULL)
{
/* list is empty */
head = (element *)
malloc
(
sizeof
(element));
(*head).data =
val
;
// or use
// head->data =
val
;
head->next = NULL;
cur_ptr
= head;
}Slide48
Linked Lists
else
{
cur_ptr
->next = (element *)
malloc
(
sizeof
(element));
cur_ptr
->next->data =
val
;
cur_ptr
->next->next = NULL;
cur_ptr
=
cur_ptr
->next;
}
//use
scanf
to read another value
}
}Slide49
Add an element
Add an element to the beginning of the list
ptr
->next = head;
head=
ptr
;
Add an element to the middle of the list
If using only one pointer
temp->next =
prev
->next;
prev
->next = temp;
If using two
temp->next = current;
prev
->next = temp;Slide50
Searching in arrays
int
arr
[5] = {7, 8, 1, 4, 3};
int
ele
,
i
;
int
flag = 0;
scanf
("%d",
ele
);
for
(
i
= 0;
i
< 5;
i
++)
if(
arr
[
i
] ==
ele
)
{
printf
("%d was found at position %d\n",
arr
[
i
],
i
);
flag = 1;
break;
}
/
/after loop
if
(!flag)
printf
("Value %d not found\n",
ele
);
Recall that worst case search time is a multiple of the array sizeSlide51
Linked List Searching
element * temp;
int
flag = 0;
for(temp = head; temp != NULL; temp = temp->next){
if(temp->data == value) {
printf
("%d was found\n", value);
flag = 1;
break;
}
}
if(!flag)
printf
("Not found\n");Slide52
File I/OIn
linux
we can use redirection for file input or output
prog1.exe < p1.in
p
rog1.exe > p1.out
prog1.exe < p1.in > p1.out
In
stdio.h
there is a
struct
called
FILE
and 3 pointers
stdin
standard input
stdout
standard output
stderr
standard errorSlide53
File I/ORecall that we have used
fgets
(
str
,
sizeof
(
str
),
stdin
)
for input
To open a file for writing, we use
FILE *
ofp
;
ofp
=
fopen
("filename", "w");
//"w" is for write
... //do work
fclose
(
ofp
);Slide54
Writing to a File Recall that we have used
fgets
(
str
,
sizeof
(
str
),
stdin
)
for input
To open a file for writing, we use
FILE *
ofp
;
ofp
=
fopen
("filename", "w");
//"w" is for write
... //do work
fclose
(
ofp
);Slide55
Writing to a fileuse
fprintf
to write to a file
fprintf
(
file_ptr
, "Text %d %s",
an_int
,
a_string
);
use
fscanf
or
fgets
for file input (read from a file)
FILE *
ifp
;
ifp
=
fopen
("filename", "r");
//Read from an existing file
fopen
returns
NULL
if the file cannot be read from or found
fscanf
(
ifp
,"%d %d", &a, &b);
fgets
(
str
,
sizeof
(
str
),
file_ptr
);
//For a line of file inputSlide56
File Position Indicator
fseek
(...)
,
ftell
(...)
ftell
(
file_ptr
)
tells the position of the file pointer in bytes
fseek
(
file_ptr
, offset, place)
goes to a position from place
0 - beginning of the file
1 -current position in the file
2 - end of the fileSlide57
Example
FILE *
fptr
;
int
filesize
;
fptr
=
fopen
("filename", "r");
fseek
(
fptr
, 0, 2);
filesize
=
ftell
(
fptr
);
//go back to the beginning of the
file
fseek
(
fptr
, 0, 0);Slide58
Reading and Writing Binary "rb
" - read binary
"
wb
" - write binary
Append to a file
"a" – append
"
ab
" - append binarySlide59
Example
FILE *
ifp
; //Input file pointer
FILE *
ofp
; //Output file pointer
int
val
;
int
sum = 0;
ifp
=
fopen
("
input_name
", "r"); //Open to read
ofp
=
fopen
("
output_name
", "w"); //Open to write
//Read until there is no more input
while(
fscanf
(
ifp
, "%d", &
val
) == 1)
{
fprintf
(
ofp
, "%d",
val
); //Store result in
//output file
sum +=
val
;
}
fprintf
(
ofp
, "\n sum %d", sum); Slide60
Error Checking
if(
ifp
== NULL)
{
printf
("input file not found\n");
printf
("Exiting...\n");
exit(0);
}