0% found this document useful (0 votes)
15 views22 pages

Chapter 3

Uploaded by

ngoc26042005
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
15 views22 pages

Chapter 3

Uploaded by

ngoc26042005
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 22

CHAPTER 3.

FUNCTION AND LIBRARIES

- Procedure: A routine that can accept arguments but does not return any values
- Function: A routine that can accept arguments and returns one or more values
- User-defined routine (UDR): A generic term that includes both user-defined
procedures and user-defined functions

If a developer creates the functions and puts all the declarations in a files
Header file (*.h), users need to write just this statement: #include <filename.h>

A library for C/C++ includes:

- Header file (usually has extension of *.h, *.hxx, …, but not necessary)
- Source code file (*.c, *.cpp, *.cxx, …) or destination file (*.obj, *.o, *.lib, *.dll,…)

Passing arguments and returning values are the core basis to create and use functions,
which is crucial to decide the software quality

Pass by reference Pass by value


#include <iostream> #include <iostream>
void swap(std::string &x, std::string &y); void swap(std::string x, std::string y);
int main(){ int main(){
std::string x = "Kool-Aid"; std::string x = "Kool-Aid";
std::string y = "Water"; std::string y = "Water";
swap(x,y); swap(x,y);
std::cout << "X: " << x << '\n'; std::cout << "X: " << x << '\n';
std::cout << "Y: " << y << '\n'; std::cout << "Y: " << y << '\n';
return 0; return 0;
} }
void swap(std::string &x, std::string &y){ void swap(std::string x, std::string y){
std::string temp; std::string temp;
temp = x; temp = x;
x = y; x = y;
y = temp; y = temp;
} }
// X: Water // X: Kool-Aid
// Y: Kool-Aid // Y: Water
Switch values of the X and Y copies
Change “input variables” (access directly in Arguments (func parameters) take only copy of
memory allocation, not via the copy) | Only input variables (actual variables) | Changing
in C++ | Reference argument can be output func prmtrs is only effective to local memory,
(consisting of the result), or both input and does not affect input variables | Function
output parameters can be used to take inputs, cannot
represent the function results (outputs) |
Safe and can avoid side-effects | Not very
efficient as it takes effort to copy data
2-dimensional array as arguments

When to pass a pointer?

- When required to change input variables (access directly to their addresses


not the copies)
- Size of the argument’s data type is large; thus, it can avoid copying large data to
stack
- Passing an array: A must to use pointer or passing address

Types of returning values

- Data types of the returning values can be anything, EXCEPT an ARRAY (directly)
- It can be: Values; Pointers; References
- Never return a pointer or a reference of a local variable
- Never return a pointer or a reference of an argument which has been passed with a
value

Return a pointer
#include <iostream>
int* FindMax(int* p, int n) {
int *pMax = p;
int *p2 = p + n;
while (p < p2) {
if (*p > *pMax)
A function to return the pMax = p;
address of the element ++p;
with the largest value in }
an array return pMax;
}
void main() {
int s[5] = { 1, 2, 3, 4, 5};
int *p = FindMax(s,5);
}
Why do we need to return a pointer or a reference?

- Size of the argument’s data type is large; thus, it can avoid copying large data to
stack
- When it is required to access directly and change output values
- How to return a pointer or a reference
 Assign it to a global variable
 Assign input argument of the function via address or reference
 Should be assigned to a memory allocation which still exists after exiting
function
int* f1(int a) {  Wrong
... This function takes an integer a by value, meaning a is a local
return &a; copy.
} Returning &a (address of a local variable) leads to undefined
behavior because the memory for a is deallocated when the
function returns.
int& f2(int &a) {  Correct
... This function takes an integer by reference, so a refers to a
return a; variable outside the function's scope.
} Returning a by reference is valid since a is not a local variable.

int f3(int &a) {  Correct


... This function takes an integer by reference and returns it by
return a; value.
} Returning a by value is valid as the returned value is a copy of
the referenced integer.
int* f4(int* pa) {  Correct
... This function takes a pointer to an integer and returns the same
return pa; pointer.
} This is valid as the pointer pa itself is not deallocated or
modified.
int f5(int* pa) {  Correct
... This function dereferences the pointer pa and returns the value it
return *pa; points to.
} This is valid as long as pa points to a valid memory location.
int& f6(int* pa) {  Correct
... This function returns the reference to the value that the pointer
return *pa; pa points to.
} This is valid if pa points to a valid memory location.
int& f7(int a) {  Wrong
... This function takes an integer by value and returns it by
return a; reference.
} Returning a (a local variable) by reference leads to undefined
behavior because a will no longer exist after the function returns.
 Correctness: Depends
This function returns a pointer pa.
int* f8() { If pa is a valid pointer that exists outside the function scope
... (e.g., globally or dynamically allocated), it is valid. Otherwise, it
return pa;
can lead to undefined behavior.
} - If pa is a global or dynamically allocated pointer: Correct
- If pa is local: Wrong

Function pointer is a pointer


variable which points to the
address of the function, its value
is the starting address of the
function in the code memory
segment

Function name is the pointer


pointing towards the function

Pointer is a variable

Example of function pointer

#include <stdio.h>
void callback_func(){
printf(“I am a call back function”);}
void f(void (*ptr)){
ptr(); // a call-back function that p point to
}
int main(){
void (*p)() = callback_func;
f(p);}
This is a simple function called
void callback_func() { callback_func that prints a message to the
printf("I am a callback function"); console.
} It does not take any arguments and does
not return a value (void).
The function f takes a function pointer
void f(void (*ptr)()) { as its parameter: void (*ptr)() means ptr
ptr(); // Call the function that is a pointer to a function that takes no
'ptr' points to arguments and returns void.
}
Inside f, the function pointer ptr is used to
call the function it points to (ptr()).
A function pointer p is declared and
initialized to point to the callback_func
function:
int main() { - void (*p)() means p is a pointer to a
void (*p)() = callback_func; //
function that takes no arguments
Declare and initialize a function
pointer
and returns void.
f(p); // - p = callback_func assigns the
Pass the function pointer to 'f' address of the callback_func
} function to p.
The function f is then called, with p passed
as its argument: f(p) passes the pointer p
to f, and inside f, ptr() calls the function
callback_func via the pointer.
Another example of function pointer with -qsort
// An example for qsort and comparator
#include <stdio.h>
#include <stdlib.h>
int compare (const void * a, const void * b) // this is a call-back function
{return (*(int*)a - *(int*)b);}
int main (){
int arr[] = {10, 5, 15, 12, 90, 80};
int n = sizeof(arr)/sizeof(arr[0]), i;
qsort (arr, n, sizeof(int), compare);
for (i=0; i<n; i++)
printf ("%d ", arr[i]);
return 0;
}
Purpose: This is the comparator function used
by qsort. It defines the sorting logic.
Parameters:
- const void* a and const void* b: These are
generic pointers (void*) used to make the
function compatible with any data type.
- *(int*)a and *(int*)b: The void* pointers are
int compare (const void * a, const void * cast to int* to dereference them and
b){ access the integer values.
return (*(int*)a - *(int*)b); Logic: The return value determines the order of
} the two elements:
- Negative: a should come before b.
- Zero: a and b are equal.
- Positive: a should come after b.
Here, the subtraction *(int*)a - *(int*)b computes
the difference between the two integers, which
implicitly defines their order.
int main() {
int arr[] = {10, 5, 15, 12, 90, 80}; arr is an integer array with 6 elements
int n = sizeof(arr) / sizeof(arr[0]),
i; n is the number of elements in the array,
qsort(arr, n, sizeof(int), compare);
calculated as sizeof(arr) / sizeof(arr[0]).
for (i = 0; i < n; i++)
printf("%d ", arr[i]);
return 0;
}
qsort(arr, n, sizeof(int), compare);

Command-line arguments

- C allows users to provide inputs when executing program with command-line


arguments
- Structure of the main function:
int main(void)
int main(int argc, char
*argv[])
- argc argument count and argv argument vector.
- argc is the number of arguments in the command including the program name.
Arguments are separated by space character
- argv is a pointer which points to an array of string; size of the array is argc + 1 as
argv[argc]= NULL

Example of command-line arguments


#include <stdio.h>
/* Print command-line arguments to stdout. */
int main (int argc, char *argv[]) {
int i;
// Loop through the command-line arguments
for (i = 1; i < argc; ++i) // Start from 1 to skip the
program name
printf("%s ", argv[i]); // Print each argument as a
string
printf("\n"); // Print a newline at the end
}
1/ argc (Argument Count):

- argc is an integer that represents the number of arguments passed to the program
via the command line.
- The first argument (argv[0]) is always the name of the program itself.

2/ argv (Argument Vector):

- argv is an array of character pointers (strings) that stores the command-line


arguments.
- argv[0] holds the program name.
- argv[1] to argv[argc-1] hold the additional arguments provided.

Function design and designing a program with multiple functions

- A function library defines:


 A group/set of functions (related to the same topic)
 Data types used in the functions
 A few global variables (limited uses)
- A good library should:
 Implement useful features
 Be simple and easy to use
 Be efficient and highly reusable
 Be complete, consistent and comprehensive
- Bottom-up Design Approach
 Indicate program components without knowing its structure
 Write each component: (With specified interface; Programming and test each
component)
 The components are easier to reuse than that in top-down approach
 They can be combined into a library
 C standard library is an example of bottom-up design
Recursion (It’s possible for a function to call itself)
int factorial(int n){
int product, i;
product = 1; 0! = 1! = 1; for n > 1, n! = n(n-1)!
for (i = n; i > 1; i = i -
1){
product = product * i;
}
The definition of factorial function is recursive
return (product); itself
}

Implementation without loop

char yes_or_no(void){
char answer;
printf (“Please enter 'y' or 'n':”);scanf (“%c”, &answer);
if(answer != 'y' && answer != 'n') answer = yes_or_no();
return answer;
}
When to use recursion?

Some cases, the problem can be solved by transforming to simple cases

Continuously carrying out transformation until a simple operation which is not


recursive is obtained

Recursion summary:

- Recursion is one of the programming techniques


 Its principle is based on the manner that a function is called, and local variables
are used in C
 Every time, a function is called, everything has its new copy
- It is also an approach to solve problems
- It would take time and effort to master this technique
- Recursion is a natural way to work with several data structures

Time/Date

Displaying current time #include <iostream>


#include <time.h> // For working with date
time(0) returns the current and time
time as the number of seconds int main(){
since the Unix Epoch (January time_t ct = time(0); // Get current time
1, 1970) std::string currenttime = ctime(&ct); //
Convert Time to Readable Format
ct stores this time as a time_t std::cout<<currenttime;
object return 0;
}
ctime converts the time_t
value into a human-
readable string representing
the current local time

Time zone
#include <stdio.h>
#include <time.h>
#define PST (-8) // Pacific Standard Time is 8 hours behind UTC
#define CET (1) // Central European Time is 1 hour ahead of UTC
int main () {
time_t raw_time; // Variable type time_t to store current time in sec
struct tm *ptr_ts; // pointer to a tm structure, which holds broken-down
time
time ( &raw_time ); // retrieves current time in sec & stores in raw_time
ptr_ts = gmtime ( &raw_time ); //gmtime() converts raw_time (seconds) into
UTC and stores the result as a struct tm in ptr_ts.
printf ("Time Los Angeles: %2d:%02d\n", ptr_ts->tm_hour+PST, ptr_ts-
>tm_min);
printf ("Time Amsterdam: %2d:%02d\n", ptr_ts->tm_hour+CET, ptr_ts->tm_min);
printf ("Time Hanoi: %2d:%02d\n", ptr_ts->tm_hour+ 7, ptr_ts->tm_min);
return 0;}

Random number
- Return a random number within 0 and
int rand(void); RAND_MAX (inclusive)
- RAND_MAX: 32767
- Seed value of an array created, usually start
void srand(unsigned seed); whenever rand is called

Example of rand/srand number // C program to generate random numbers


srand(seed): #include <stdio.h>
#include <stdlib.h>
- Initializes the random number #include<time.h>
generator with a seed value. int main(void){
// This program will create different
- The seed determines the starting sequence
// of random numbers on every program run
point for the random sequence.
// Use current time as seed for random
- If the seed remains the same, the // generator
srand(time(0));
same sequence of random for(int i = 0; i<5; i++)
printf(" %d ", rand());
numbers will be generated every return 0;
time. }

time(0):
- Returns the current time in
seconds
- Using time(0) ensures the seed is
different each time the program
runs, leading to different random
sequences

String

- String: an array of character


char pet[5] = {'l', 'a', 'm', 'b', '\0'};
printf(“Mary had a little %s.\n”, pet);

- More precise definition: A character array terminates with a null character (the last
element is ‘\0’)

- String is not a data type in C

- Developer must be sure that the


terminated character is null, i.e. ‘\
0’

char pet[5] = {'l', 'a', 'm', 'b', '\


0'};

char pet[5];
Equivalent Initialization
pet[0] = 'l'; pet[1] = 'a'; pet[2] =
'm';

pet[3] = 'b'; pet[4] = '\0';

char pet[5] = "lamb";

char pet[] = "lamb";


Self-assign strings

#include <stdio.h>
int main(){
char str1[10], str2[] = "Saturday";
int i = 0;
while (str2[i] != '\0') {
str1[i] = str2[i];
i = i + 1;
} // Self-assign strings
str1[i] = '\0';
printf("%s",str1);
}

strcpy() function #include <iostream>


#include <cstring> // For strcpy
defined in <string.h> for C and <cstring> for C+ int main() {
+ char source[] = "Hello, world!";
char destination[50];
- Copies the null-terminated string from // Using strcpy to copy the
source to destination. string
- The destination buffer must be large strcpy(destination, source);
enough to hold the source string, std::cout << "Source: " << source
including the null terminator. << std::endl;
- If the destination is not large enough, it std::cout << "Destination: " <<
can lead to buffer overflow, which is a destination << std::endl;
common security vulnerability. return 0;
}

#include <iostream> strlen() function


#include <cstring> // For strlen
int main() { Function to calculate the length of a null-
char str[] = "Hello, world!"; terminated C-style string
std::cout << "Length of the string:
" << strlen(str) << std::endl;
return 0;
Returns the number of characters in the
} string, excluding the null terminator (\0)
#include <iostream> strcat() function
#include <cstring> // For strcat
int main() { Function to concatenate two null-
char str1[50] = "Hello, "; terminated C-style strings
char str2[] = "world!";
strcat(str1, str2); // Concatenate
str2 to str1
Appends the source string to the end of
std::cout << "Concatenated string: the destination string. The destination
" << str1 << std::endl; must have enough space to hold the
return 0; result.
}
Compare 2 strings

1. Array of C-Style Strings #include <iostream>


int main() {
C-style strings are arrays of char fruits[][10] = {"Apple", "Banana",
characters terminated by a null "Cherry"};
character (\0). for (int i=0;i<3;i++) std::cout<<fruits[i]<<
std::endl;
return 0; }
// Strings must fit within size of inner array (10
characters in the example)
// Cannot assign new strings directly to an element,
as C-style strings are not modifiable this way
// To modify or copy strings, use functions like
strcpy (from <cstring>)
2. Array of Pointers to C- #include <iostream>
Style Strings int main() {
Here, fruits is an array of const const char* fruits[] = {"Apple", "Banana",
char*, where each pointer points to "Cherry"};
a string literal for (int i=0;i<3;i++) std::cout<<fruits[i]<<
std::endl;
return 0;}
// This approach is more memory efficient, as the
strings are stored in read-only memory and only
pointers are stored in the array
// The strings are immutable because string literals
are read-only
3. Array of std::string #include <iostream>
Objects #include <string>
int main() {
The recommended way to work std::string fruits[] = {"Apple", "Banana",
with strings in modern C++ is by "Cherry"};
using std::string for (int i = 0; i < 3; i++) {
- Each element is a fully std::cout << fruits[i] << std::endl;
functional std::string object. }
- You can easily modify, return 0;}
assign, and manipulate
strings.
Files in C/C++ 📁 📁 📁

- File is a set of data recorded in memory storage such as harddisk


 Managed by users and operating system (OS)
 Stored in long-term
- File name is a name used to uniquely identify a computer file by users and OS
 It follows naming rule 8.3 in DOS

Why do we need files? File I/O


- Large amount of input/output data - Provide a common interface for all
- Storing data in long-term I/O
- Transfer data to different programs - C language has a close relationship
- Input/output streams are with UNIX OS
simultaneous - Most of C libraries follows UNIX I/O
model which considers all data
streams as files
- Keyboard, screen, serial ports, GPIO
are all accessed via writing/reading
files

Revision of files for compilation


Source files Compiled file (name and extension depend on
- .c file: programs and systems)
functions in C - Object files: files have been compiled and
- .h file: header files waiting for linking
- Actual projects may - Library files: set of functions have been pre-
contain hundreds *.c and compiled
*.h files - Executable files: machine code files have
been linked and is ready to be executed in
computer memory

Header file (*.h) Library


Header files are used to include Files consist of functions which have been
- Type definition (using typedef) built and compiled
- Function declaration - Reduce system dependency
- Constants declaration - Reuse existing source code
- Global variable declaration - Enhance portability

Input/output data stream with file File stdio.h


- Keyboard / Screen are special cases - Input/output function declaration
of input/output data stream (as - Define useful constants (e.g. EOF)
character arrays) - Define FILE structure to represent
- Multiple streams are existing at the file information used in C programs
same time File variables in C are pointers which
- In fact, a buffer is used for data point to FILE structure
stream instead of working directly FILE *myfile;
with variables

Write/Append a txt file using <fstream> library


#include <iostream> #include <stdio.h>
#include <fstream> #include <stdlib.h>
using namespace std; int main() {
int main(){ FILE *newFile;
fstream newFile; newFile = fopen("CaitlynKiramman.txt",
newFile.open("CaitlynKiramman.txt", "w"); // "w" opens file for writing
ios::out); // write text if (newFile != NULL) {
if(newFile.is_open()){ fprintf(newFile, "Caitlyn Kiramman,
newFile << "Caitlyn Kiramman, ilysm");
ilysm"; fclose(newFile);
newFile.close(); }
} newFile = fopen("CaitlynKiramman.txt",
newFile.open("CaitlynKiramman.txt", "a"); // "a" opens file for appending
ios::app); // append text if (newFile != NULL) {
if(newFile.is_open()){ fprintf(newFile, "This is an append
newFile << "This is an append text\ text\n");
n"; fclose(newFile);
newFile.close(); }
} system("pause");
system("pause>0"); return 0;
} }

Read a txt file using <fstream> library


#include <iostream> #include <stdio.h>
#include <fstream> #include <stdlib.h>
#include <string> #include <string.h>
using namespace std; int main() {
int main(){ FILE *newFile;
fstream newFile; char line[256]; // Buffer to store each line
from the file
newFile.open("CaitlynKiramman.txt", newFile = fopen("CaitlynKiramman.txt",
ios::in); // read file in console "r"); // "r" opens file for reading
if(newFile.is_open()){ if (newFile != NULL) {
string line; while (fgets(line, sizeof(line),
while(getline(newFile, line)) newFile) != NULL) {
{ printf("%s", line); // Print the line
cout << line << endl; to the console
} }
newFile.close(); fclose(newFile); // Close the file after
} reading
system("pause>0"); }
} system("pause");
return 0;}

Open a file

- Open a file: create a link between the OS (filename) and the C program (file
variable)
 Function in the library: fopen
 Identify parameters “r” to read the file and “w” to write to the file
- File must be opened before being used
- File stdin/stdout (used by scanf/printf) is opened automatically and linked to the
keyboard and screen respectively

Closing file

- Done once in the program


- Perform at the end of the program
- All the data file must be closed otherwise data will be lost

End of file

- Defined in stdio.h
- #define EOF (a certain negative value)
 Usually -1
 Input/output functions in the library use EOF to indicate the end of file
 Programs can also use EOF
- Attention: EOF is the state, not an input value

Basic file input/output functions

- fopen and fclose: as mentioned in previous slides


- fscanf: is similar to scanf, however the first argument is a file variable
status = fscanf(filepi, “%...”, &var,...);
/* fscanf returns EOF on end of file */
- fprintf: the same as printf, however the first argument is a file variable
- File must be opened before calling fscanf or fprintf

Operations with files


- Once the file is opened, all the operations with it are performed from the beginning
to the end of file
- 4 basis methods to work with file:
 Character by character
 Line by line
 Formatted I/O
 Binary I/O

Write characters Read characters


Functions to write character: Read character functions:
- int fputc(int c, FILE *fp); - int fgetc(FILE *fp);
- int putc(int c, FILE *fp); - int getc(FILE *fp);
- int putchar(int c); - int getchar(void);

putchar(c) is similar to putc(c, stdout) getchar() is similar to getc(stdin)

putc() and fputc() are the same getc() and fgetc() are the same

Returning value: Returning value:


- If succeed, characters are written - If succeed: the next character in the
into the file stream
- If fail: EOF - If fail: EOF
- If end of file: EOF

To differentiate EOF, one can call feof()


or ferror()

A character can be pushed back to the


stream by using ungetc()
int ungetc(int c, FILE *fp);

Read a line Write a line


Read a line by A character array can be written to a file
char *fgets(char *buf, int max, FILE with
*fp); int fputs(const char *str, FILE *fp);

Operations Character \n can be added by developer


- Read maximum of (max-1)
characters from a file Return value:
- Also read \n character - If succeed: zero
- Check both end of file and error - Otherwise: EOF
Returning value:
- If succeed: a pointer points to buf.
Note that fgets() automatically
adds \0 to the end of the string
- If it is the last line of the file: NULL
- If error: NULL

Use feof() and ferror() to identify the


error

Formatting I/O
int fprintf(FILE *fp, const char *format, ...);
int fscanf(FILE *fp, const char *format, ...);

- Similar to printf() and scanf()


- printf() and scanf() can be written as
fprintf(stdout, format, arg1, arg2, );
fscanf(stdin, format, arg1, arg2, );

The fprintf function writes formatted text


fprintf(stdout, format, arg1, arg2, );
to a specified file stream
--------------------------------------
---- Here, stdout (standard output) is the
target stream, meaning the output will be
printed to the console

int a = 10, b = 20; arg1, arg2, etc., are the variables or


fprintf(stdout, "Values: a = %d, b = values to be formatted and printed
%d\n", a, b);
// Same as printf("Values: a = %d, b = Using fprintf with stdout is equivalent to
%d\n", a, b); using printf, but fprintf is more general
because you can direct output to other file
streams (e.g., a file or stderr)
The fscanf function reads formatted input
fscanf(stdin, format, arg1, arg2, ); from a specified file stream
----------------------------------------------------------
---- Here, stdin (standard input) is the source,
meaning the input is read from the console

int x, y; arg1, arg2, etc., are pointers to variables


printf("Enter two integers: "); where the input values will be stored
fscanf(stdin, "%d %d", &x, &y);
printf("You entered: x = %d, y = %d\
n", x, y);
Using fscanf with stdin is equivalent to
using scanf, but fscanf can be used to
read from other file streams as well
Differences Between fprintf/fscanf and printf/scanf
- fprintf and fscanf are general-purpose and can handle any file stream (e.g., a
file, standard input/output, or error stream)
- printf and scanf are shorthand for working specifically with stdout and stdin

Binary I/O

- When reading and writing a binary file, the program does work with the object
directly instead of converting this object into a character array
- Binary I/O includes:
 size_t fread(void *ptr, size_t size, size_t nobj, FILE *fp);
 size_t fwrite(const void *ptr, size_t size, size_t nobj, FILE *fp);
- To write structures to a file
struct Astruct mystruct[10];
fwrite(&mystruct, sizeof(Astruct), 10, fp);

Why Use size_t? #include <stdio.h>


-
Portability: It adjusts automatically int main() {
to the platform's word size, making size_t size = sizeof(int); // size
your code more portable. of an int in bytes
- Safety: Since it's unsigned, it printf("Size of int: %zu bytes\n",
size);
avoids negative sizes and
return 0;
counts, which are logically invalid in }
many contexts.
Best Practices:
- Use size_t for:
 Array indices
 Memory sizes
- Return values from sizeof, strlen,
or file I/O functions

Other operations with file

- C provides other functions to work with file without accessing it in sequence


- 3 basic functions
 long ftell(FILE *fp); // current file position of the // specified stream
 int fseek(FILE *fp, long offset, int from);
 void rewind(FILE *fp);
Purpose: Returns the current position of the file pointer in a given
file stream

Parameters: FILE *fp: A pointer to the file stream


long ftell(FILE *fp)
Return Value:
- The current file position as a long value (in bytes from the
beginning of the file)
- Returns -1L if an error occurs
Purpose: Moves the file pointer to a specific position in the file

Parameters:
- FILE *fp: A pointer to the file stream
- long offset: The number of bytes to move the pointer
- int from: The reference position for the movement, which can
int fseek(FILE *fp, be:
 SEEK_SET: From the beginning of the file
long offset, int from);
 SEEK_CUR: From the current position of the file pointer
 SEEK_END: From the end of the file

Return Value:
- Returns 0 on success
- Returns non-zero on failure
Purpose: Moves the file pointer back to the beginning of the file.

Parameters: FILE *fp: A pointer to the file stream


void rewind(FILE *fp);
Behavior:
- Equivalent to fseek(fp, 0, SEEK_SET)
- Clears the error and EOF flags for the file stream
Building application with file

- By using fopen, fclose, fscanf and fprintf, developers can write many applications
related to file
- Many errors and exceptions can occur when working with files
 A robust application must handle the errors well
 The skills will be acquired gradually

Example: copy file


/* Problem: copy an input file to an
output file */
/* Technique: loop, copying one char at a
time until EOF, files must already be
This code copies the contents of open before this */
one file to another by reading status = fscanf(infilep, “%c”, &ch);
characters one at a time from the while (status != EOF) {
input file using fscanf and writing fprintf(outfilep, “%c”, ch);
them to the output file using fprintf. status = fscanf(infilep, “%c”, &ch);}
printf(“File copied.\n”);
The process continues in a loop until
fclose(infilep);
the end of the file (EOF) is reached.
fclose(outfilep);
After copying, it prints a confirmation
message and closes both files using ------------------------------
fclose. This approach is simple but ---
inefficient for large files, as it processes /* Many C programmers use this style */
one character at a time, making it more ...
suitable for small text files than binary while (fscanf(infilep, "%c", &ch) !=
EOF)fprintf(outfilep, "%c", ch);
or large files.
printf("File copied.\n");
fclose(infilep);
fclose(outfilep);

Example: query database


#include <stdio.h> Purpose: This program processes a file
int main(void) { (db_file) containing records with a person's
FILE *inp, *outp; name (20 characters), SSN (9 characters), and
int age, j; age (an integer). It writes the name and SSN to
char name[20], ssn[9], ch;
another file (result_file) only if the person's age
inp = fopen(“db_file”, “r” );
outp = fopen(“result_file”, “w”);
is greater than 20.
/* loop till the end-of-file */
while (fscanf(inp, “%c”, &name[0]) != File Operations:
EOF){ - Opens db_file for reading ("r") and
/* read name, ssn, age */ result_file for writing ("w").
for (j = 1; j < 20; j++) - Closes both files at the end of the
fscanf(inp, “%c”, &name[j]); program using fclose.
for (j = 0; j < 9; j++) fscanf(inp,
“%c”,&ssn[j]); Record Processing:
fscanf(inp, “%d”, &age); - A while loop reads each record in db_file
/* read line feed character */
until the end-of-file (EOF) is reached.
fscanf(inp, “%c”, &ch);
/* copy name, ssn to output if age - Input Reading:
> 20 */  Reads the first character of the name
if (age > 20) { into name[0] using fscanf.
for (j = 0; j < 20; j++)  Reads the remaining 19 characters of
fprintf(outp, “%c”, name[j]); the name into name[1] to name[19]
for (j = 0; j < 9; j++) using a for loop.
fprintf(outp, “%c, ssn[j]);  Reads the 9-character SSN into ssn[0]
fprintf(outp, ”\n”); to ssn[8] using another for loop.
}
 Reads the integer age.
}
fclose(inp); fclose(outp);
 Reads the newline character after the
return (0); record.
}
Output Writing:
If the person's age is greater than 20:
- Writes all 20 characters of name to
result_file.
- Writes all 9 characters of SSN to
result_file.
- Writes a newline character ("\n") to
separate records in the output file.

End-of-File Handling: The loop terminates


when fscanf returns EOF.

Example: extend tab


This code processes a C source file #include <stdio.h>
(prog.c) and creates a modified version int main(void) {
(tabless-prog.c) by replacing all tab FILE *infilep, *outfilep;
characters (\t) with spaces to align text to char ch;
int column = 0;
the next multiple of 8 columns, preserving
/* Open input and output files */
consistent formatting. It reads the input infilep = fopen("prog.c", "r");
file character by character and handles outfilep = fopen("tabless-prog.c",
specific cases: newline or carriage return "w");
characters reset the column counter and /* process each input character */
are copied as is, while tabs are replaced while (fscanf(infilep, "%c", &ch) !
with spaces to reach the appropriate = EOF){
alignment. All other characters are copied if (ch == '\n' || ch == '\r') {
directly, incrementing the column count. /* end of line: reset column counter */
By maintaining proper alignment and column = 0;
structure, the output file replicates the fprintf(outfilep, "%c",
ch);
content of the input file but without tab
}
characters. else if (ch == '\t') {
/* tab: output one or more spaces, */
/* to reach the next multiple of 8. */
do {
fprintf(outfilep, "%c", '
') ;
column++;
} while ((column % 8) !=
0);
}
else {
/*all others: count it, and copy it
out*/
column ++;
fprintf(outfilep, "%c",
ch);
}
}
fclose(infilep); fclose(outfilep);
return 0;
}

Files in C++

#include <iostream.h>
#include <fstream.h>
ifstream fin; // input
Define a variable: ofstream fout; // output
fstream fio; // input and output
fin.open("file1.txt");
Open/Create a file: fout.open("file2.dat");
fio.open("file3.inf");
ifstream fin("file1.txt"); // input
Declare variables and open/create a ofstream fout("file2.inf");// output
file together fstream fio("file3.dat"); // input and
output

Write data into a file fout << "Caitlyn Kiramman" << endl;
- Similar to cout fout << 23 << endl<< false;
- A file may contain mixed data types,
e.g.:
char name[32];
int age, married;
Read data from a file (similar to cin)
fin.getline(name,32);
fin >> age >> married;
Close a file fin.close();
- Automatically performs when a fout.close();
scope ends fio.close();
- Or call close();

Function overloading in C++

- In C++, it is possible to create multiple functions with the same name, e.g.:
int max(int a, int b);
double max(double a, double b);
double max(double a, double b, double c);
double max(double* seq, int n);
- The purposes of function overloading is
- Simplify function naming (instead of maxInt, maxDouble, maxDouble3,
maxDoubleSequence, …)
- Make it easy for function users who need to remember only one familiar name

Examle: usage of max() functions


int max(int a,int b) return(a>b) ? a : This code defines multiple overloaded
b; max functions to find the maximum
double max(double a, double b) value in different scenarios. The first two
return(a>b) ? a : b; functions handle two int and two double
double max(double a, double b, double
values, respectively, using the ternary
c){ operator to return the larger of the two.
if (a < b) a = b; The third max function compares three
if (a < c) a = c; double values and returns the largest by
return a; sequentially updating the value of a. The
}
fourth function takes an array of double
double max(double *seq, int n) {
int i = 0, kq= seq[0];
values (passed as a pointer) and iterates
while (i < n) { through the array to find and return the
if (kq< seq[i]) kq= seq[i]; maximum value. These functions
++i; showcase function overloading, where the
} same function name is used with different
return kq; parameter types or counts, enabling
} flexibility in determining the maximum
value from various inputs.
int max(int a, int b); The code declares and uses
double max(double a, double b); overloaded max functions to find the
double max(double a, double b, double maximum value between different
c); numbers of arguments, either two int
double max(double* seq, int n);
values, two double values, or a sequence
void main() {
int k = max(5,7);
of double values in an array. The calls in
d = max(d, a[1], a[2]); main illustrate how these functions are
d = max(d, 5); invoked with different parameter types,
} although there’s a minor issue in the last
call where a type mismatch occurs.
It is the compiler’s responsibility to verify and choose the right function amongst those
with the same name!

Principles of function overloading

- Functions with the same name defined in one file / a library or used in the same
program must be different in:
Number of arguments or type of at least one argument (int ≠ short, const int ≠ int,
int ≠ int&, ...)
 They cannot be different only in type of returning value
- Why?
 Compiler need to decide which functions to call
 Based on call syntax (number and type of actual arguments) compiler will
choose the most suitable functions
 Compile can convert type automatically in the most reasonable manner (e.g.:
short=>int, int=> double)

inline function in C++

- Problem: a normal function is useful but not very high efficient, especially if the
implementation code is short
 The procedure of recording program states, allocating memory, copying
arguments, copying returning values, recovering the program states consume
too much time
 If the function code is short, the usefulness cannot compensate for large time
consuming
- Solution in C: Using macro, e.g.
#define max(a,b) a>b?a:b
 Problem: macro is executed by preprocessor, type is not checked, program
cannot differentiate used context thus, it results in undesired effects.
 E.g.: the statement l=max(k*5-2,l); is replaced by l=k*5-2>l?k*5-2:l; //OOPS
- The method of using bracket even make the code harder to read while cannot
solve the weakness completely
- Put the keyword inline at the beginning of function declaration and definition
inline int max(int a, int b) {
return (a > b) ? a : b;
}

- It is different from normal function as:


 “Inline function” is not really a function
 When inline function is called, the call is substituted by the source code defining
the function, it does not carry out function call procedures
E.g.:
l=max(k*5-2,1);

Is replaced by:
int x=k*5-2; // temporary variable
l=(x>1)?x:1; // OK

When to use inline?

- Advantages:
 Useful as a normal function
 As efficient as direct source code, not calling function
 More reliable and safer than using Macro
- Disadvantages:
 If the function is called too many times in the program, the source code will
grow bigger (implementation code appears multiple times in the program)
 Function definition code must be open keep in header file
- Create and use inline function when
 Implementation code of the function is short (just a few line, no loop)
 Speed is the priority rather than memory capacity

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy