CEG 221: Week 1 Lesson 1

Download Report

Transcript CEG 221: Week 1 Lesson 1

CEG 221
Lesson 3: Review II & Beyond
Mr. David Lippa
CEG220 & Beyond
• Advanced Input/Output
– Text I/O, Void pointers, Binary I/O
• Advanced Data Types
–
–
–
–
Pointers to Basic Types & Pass By Reference
Enumerated Types (enum)
Structures (struct) & Unions (union)
Pointers to Advanced types & Pointers to Pointers
• Advanced Programming
– Multiple files to separate interface from implementation
– Modifiers on variables (static, auto, extern)
– Modifers on functions (static vs. non-static)
• String Processing using <string.h>
File Input / Output
• Just as you can get/give user input from
the terminal with scanf/printf, you can do
so to/from strings (sscanf, sprintf) and files
(fscanf, fprintf).
• fscanf/fprintf take an additional parameter,
the input (or output) stream, as its first
argument
• These functions are used for text
input/output and are located in stdio.h
Text Input/Output
• Prototypes:
–
–
–
–
fscanf(FILE* pStream, const char *pString, …)
fprintf(FILE* pStream, const char *pString, …)
sscanf(char *pSource, const char*pString, …)
sprintf(char *pDestination, const char*pString,
…)
• Uses: conversions, (ie. converting “3.14159” to
the double 3.14159), writing text to files for
verification of data values, writing cross-platform
setting files (to avoid endian issues)
Analysis of Text I/O
• Advantages: easy for cross-platform data
storage – let’s the processor put the bytes
in the proper order with scanf/printf; easy
to verify correct results; generally more
compressible than their binary equivalents
• Disadvantages: files can get very large
(especially those, such as images)
Introduction to Binary File I/OO
• Most files are stored in binary format,
writing raw bytes to disk, and then later
read in and interpreted
• Use fread and fwrite from <stdio.h>,
which are significantly faster to read in
giant chunks of data
• Same prototypes for both fread/fwrite:
– size_t fread(void *pMemory, size_t size,
size_t numElements, FILE *pStream);
What is a void*?
• We’ve all seen the return type void before
– it means “nothing” (ie. A function that
returns void returns nothing). So a void* is
a pointer to nothing, right? WRONG!
• In fact, it’s a pointer to anything.
• A void* can be a pointer to an int, a char, a
char*, a char**, a FILE*.
• Because of this ambiguity, we cannot
dereference a void* (ie. If pVoid is a void*,
(*pVoid) is ambiguous
Using fread & fwrite
• Arguments:
– pMemory: the address to read/write from/to
– size: the size of each element (sizeof)
– pStream: the stream read/written from/to
– Returns the number of elements read/written
• Remember:
– Allocate new memory when using fread – either
dynamically (with malloc) or statically (passing
in the address using &). (ie. int integer; struct
pType p; see next slide for details)
Examples:
• To read an integer:
– int integer;
– fread(&integer, sizeof(int), 1, pInputFile)
• To read a structure that was written to disk
– struct PersonType p;
– fread(&p, sizeof(struct PersonType), 1,
pInputFile)
• In class: using fseek to jump around
Introduction to Advanced Types:
Terms
• Pointer – a memory address that is also a
variable
• We must first define a variable before we
can declare and use it
• Definition of a variable – specifies its
structure and members
• Declaration of a variable – creates an
instance of a variable of a type, according
to its types definition
Advanced Data Types:
Pointers to Basic Types
• We can create a pointer (a memory
address) to a variable.
• Pointers should be initialized to NULL, the
empty memory address (also 0x00000000)
• Pointers are always an ADDRESS, never
a value
• Dereferenced (convert ptr to value) with *
• Use & to convert a variable to a memory
address
Example: Pointers to Basic Types
int iValue = 10;
int *pInt = 5; // points to the ADDRESS 5
pInt = malloc(sizeof(int)); // allocate
*pInt = 5; // pInt points to memory containing 5
pInt = &iValue; // pInt points to iValue == 10
free(pInt); // free up the memory
pInt = NULL; // reset to NULL
Example: Pointers to Basic Types
(Continued)
• Something wrong in the previous slide!
– Cannot free up iValue since it wasn’t malloc’d!
– The memory malloc’d and formerly assigned
to pInt is LOST since we have no copy of that
pointer  MEMORY LEAK!
• How to fix
– Switch “pInt = &iValue;” and “free(pInt);”
Implications of Pointers:
Passing By Reference
• Because a pointer is simply a memory location,
passing pointers to functions lets us change the
value passed in – a feature not previously
allowed to us!
• This is called pass by reference (or pass by
pointer), as opposed to pass by value, where a
copy is made and the copy is modified
• We can use the & operator to get the address of
any variable (see example in next slide)
Passing By Reference
• Let’s say we have an integer and want to
modify it and the function void
doSomething(int *pInt) takes an int*. We
can use the & operator to get the address
of an int, passing the address of that int to
a function that takes an address of an int.
int p; // create p
doSomething(&p); // do sthg to p and change it
Advanced Data Types: Enums
• Enumerated Types are just a glorified
integer, assigned with a name and number
value. They can be in hexadecimal format
or in base 10 (ie. EyeColorType)
• They are custom data types that can be
used in switch() statements or if/else
chains to handle a variety of cases
• Since they are ints, they can be easily
written/read to/from files
Example: Enums
// define EyeColorType
enum EyeColorType { BLUE=0, BROWN=1, GREEN=2, HAZEL = 4 };
// …
// declare an EyeColorType called eColor
EyeColorType eColor = HAZEL; // remember HAZEL == 4
// …
switch(eColor) {
BLUE: …; break; // BLUE == 0
BROWN: …; break; // BROWN == 1
…
default: …; break; // this will be hit if eColor == 3
}
Advanced Data Types: Structs
• Structs are a heterogeneous data type that
is a collection of all its members
– Example:
– struct StudentType
•
•
•
•
First Name, Last Name
Age
Social Security Number
Number of credits taken to date
– What types would all of these members be?
Defining a Structure
enum GenderType { MALE, FEMALE };
typedef struct PersonType {
char mFirstName[40]; // a string
char mLastName[40]; // a string
enum GenderType mGender;
int mAge;
float mGPA;
struct PersonType *mpSpouse;
} Person;
Declaring a Structure
• How to declare a struct as a variable and
as a pointer:
– struct PersonType andrew;
– struct PersonType* pPerson;
• We can use “typedef” to create custom
types that help eliminate confusion after
the struct definition
– typedef Person* PersonPtr;
• Now we have PersonPtr and Person types
Declaring a Structure (Contd)
• We can now declare a pointer to a person
– PersonPtr pPerson1, pPerson2;
instead of having to do:
– struct PersonType *pPerson1, *pPerson2;
• Furthermore, the extension Ptr to every
pointer type clarifies what is a pointer and
what isn’t. If we wanted an array of
Person, we could create a pointer to a
PersonPtr.
Example: Structures
• An array of 14 persons:
Person myClass[14];
• A pointer to a person: PersonPtr pPerson;
• An array of 4 person pointers:
PersonPtr myFamily[4];
• What we cannot do:
– Inherit characteristics (ie. An engineer is a
person)
Using Structures
• To access a member of a pointer, we must
dereference the pointer (with *) and then
the structure (with .)
• Examples:
– myClass[0].mGPA = 4.00f;
– pPerson = malloc(sizeof(Person));
– (*pPerson).mGPA = 3.89f;
– pPerson->mGPA = 3.89f; // equivalent to above
– pPerson->mpSpouse = &myClass[0];
Advanced Data Types: Unions
• A union is just like a structure in terms of
memory usage and behavior, with one
exception: it only contains one of its
internal variables at a time.
• If struct PersonType were a union, setting
the gender field would be its only contents.
• Then, if the age were changed, the gender
would be lost
Side By Side: Unions and Structs
struct StudentType {
char mFirstName[30];
char mLastName[40];
char mSSN[9];
unsigned int mAge;
int mNumCreditsTaken;
char mStudentStatus;
};
union NumberType {
char mChar;
short mShrt;
int mInt;
long mLong;
};
• Structs contain all the members in their definition
• Unions only have one of their members contain
information at a time
– For a given union, if mInt = 40 and mChar is then set to be ‘A’,
then the information in mInt is gone
Pointers to Pointers
• We have briefly covered pointers to
pointers. Wouldn’t you rather see
“PersonPtr *pList” instead of “struct
PersonType **pList”?
• Remember, when dereferencing pList to
make sure that enough memory was
allocated and that when you dereference
it, *pList is still a POINTER
Advanced Programming:
Information Hiding at a High Level
• Use multiple files to separate interface from
implementation
– Interface: how to use the functionality provided
– Implementation: how the work gets done
• We can then create a library consisting of the
header file (interface) and the library
(implementation). No one need know how the
library functions, just that it does what was
intended.
• Go over examples in class
Advanced Programming: Modifiers
• Modifiers on variables
– const – variable cannot change
– static – only one copy exists within that file
– extern – defined externally in some file that
#includes where the extern is defined
• Modifers on functions (static vs. non-static)
– Static – only one copy of the function can exist
• No other function may have that name and
argument list
The Basics of Modifiers I: CONST
• There is one time where a const variable is
not quite constant – that is when it is a
pointer:
– 1) const char *pChar = “Hello”; // contents can’t Δ
– 2) char * const pPtr = …; // address can’t Δ
– 3) const char * const pPtr2 = …; // neither can Δ
The 3 Cases of the const Modifier
• Case (1)
– pChar[0] = ‘C’; // illegal – contents can’t change
– pChar = “World”; // legal – points to something else
• Case (2)
– FILE* const pFile = fopen(“Data.dat”, “rb”); // legal
– pFile = NULL; // illegal – pointer can’t change
– fprintf(pFile, “Hello”); // legal – contents can change
• Case (3)
– const FILE* const pFile = fopen(“Data.dat”, “rb”); // legal
– fclose(pFile); // illegal
– fprintf(pFile, “Hello”); // illegal
The Basics of Modifiers II
• Since extern is rarely used, just don’t
worry about it
• The main use of “static variables” is to
ensure that only one copy of a function or
variable exists – frequently fixes the
“function already defined” compiler/linker
error. Statics are frequently used in C++
and significantly less in C.
Next Time
• Algorithm Development I
– What is an algorithm?
– Why are algorithms important?
– Examples of Algorithms
– Introduction to Algorithm Development
– Example of Flushing Out an Algorithm
• Questions
QUESTIONS
???