330 likes | 457 Views
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)
E N D
CEG 221Lesson 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
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; }; Side By Side: Unions and Structs • 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