SYSTEM

LEVEL

PROGRAMMING

System Level Programming 3320 - CS - GSU

Student Evaluation of This Lab >

This page is a supplement to my explanations during the lab. || The materials of this page evolved during a summer semester (7 weeks = 7 labs), matching the level of understanding of the students for this subject and their needs. || The main tasks for each lab was provided by the instructor of the course and not me. || The code snippets provided here are meant to be simple and understandable for beginners. Thus, they are not the most robust approaches and they do NOT of course suggest the best practices. || I tried my best to keep a link to all the online sources that I used, yet I may have forgotten in a case or two. In case you noticed a link is missing, I would appreciate it if you inform me about it.


LAB 1


  1. Insert mode: i

  2. Command mode: Esc

Moving cursor in command mode:

  1. Move forward word by word: w Move backward: b

  2. Move to the top:(Hight) H Move to the bottom:(Low) L Move to the middle:(Middle) M

  3. Move forward through the doc: Ctrl + f Move backward: Ctrl + b

  4. Go the a specific line (e.g. line 5): 5G

Editing commands in command mode:

  1. Add to the end of a word: a

  2. Add to the beginning of a line: I Add to the end of a line: A

  3. Add a new line below: o Add a new line above: O Remove a whole line: dd

  4. Delete a char on the right: x Delete a char on the left: X

  5. Delete a word: dw

Repeat the last command: .



A

Few

keys

for

VI

SED

sed 'pattern/action' <file>

sed 'pattern/action' <file>

sed '/^$/d' companies.txt

sed '1d' companies.txt

sed '1,4d' companies.txt

RegEx

grep 'Atlanta' companies.txt

grep -i 'Atlanta' companies.txt

grep -v 'Atlanta' companies.txt

grep -iv 'atlanta' companies.txt

grep -ivn 'atlanta' companies.txt

grep '^12' companies.txt

grep 'GA.$' companies.txt

grep '..ed' companies.txt

grep '[46]8' companies.txt

grep '[a-z]ing' companies.txt


Useful Online resources:


Want to have fun with RegEx?

Try this ...

Class slides

II : RegEx

Chapter 2-regex.pdf

III : Unix Utilities

Chapter 3.pdf

IV : Unix Shell

Chapter 4.pdf

V : Bourne shell

Chapter 5.pdf


LAB 2



Basics

  • chmod a+x myScript.sh or chmod 755

  • #!/bin/bash

  • # whatever

  • myString="This is my string!"

  • echo "I just wrote ${myString}"

  • listOfFiles=$(ls) or listOfFiles=`ls`

  • echo "${listOfFiles}" or echo "$listOfFiles"

  • thisFile=$(ls -al | grep 'myFile.sh')

  • echo "${thisFile}"

  • Give execution permission to all.

  • This is NOT a comment!

  • This is a comment!

  • A variable with a string,

  • How to call a variable,

  • Use variables to hold a command's output, (with parenthesis or back-ticks)

  • Print the result of the commands using variables.

  • Another variable to hold a command's output

  • print the results


Strings

  • myString="This is my string!"

  • ${#myString}

  • expr index "$Mystring" "s"

  • newString=${STRING:0:4}

  • newString=${STRING:4}

  • My string,

  • Length of a string,

  • Get the position of a char in a string,

  • Get a sub-string by indicating the starting (0) position and the length (4) of the sub-string

  • Get a sub-string by indicating the starting (4) position only. (Length is as large is the remaining string)

What to do:

Extract "Jonny Boy" from a given string.

Copy the code on the right in a .sh file and follow the instruction:

  1. COMMA1 needs an appropriate command to get the position of the first comma,

  2. CHOP1FIELD needs a sub-string of DATARECORD from COMMA1 to the end,

  3. COMMA2 needs a similar command to get the position of the second comma, but in the CHOP1FIELD,

  4. LENGTH needs to know how long Johnny Boy is.

  5. FIRSTNAME is once again a sub-string of CHOP1FIELD from 6 with the length equal to LENGTH.






# Code to extract the First name from the data record

DATARECORD="last=Clifford,first=Johnny Boy,state=CA"

COMMA1=`expr index "$DATARECORD" ','` # 14 position of first comma

CHOP1FIELD=${DATARECORD:$COMMA1} #

COMMA2=`expr index "$CHOP1FIELD" ','`

LENGTH=`expr $COMMA2 - 6 - 1`

FIRSTNAME=${CHOP1FIELD:6:$LENGTH} # Johnny Boy

echo $FIRSTNAME




What to do:

Copy the code on the right in a .sh file and follow the instruction:

  1. Enter your BIRTHDATE as a string

  2. Enter the # of Presents as an integer,

  3. Enter a script to BIRTHDATE, that finds the name of the day associated to a given date! (data -d)

#!/bin/bash


# Change this code

BIRTHDATE=

Presents=

BIRTHDAY=


##################################################

# Testing code - do not change it


if [ "$BIRTHDATE" == "Jan 1 2000" ] ; then

echo "BIRTHDATE is correct, it is $BIRTHDATE"

else

echo "BIRTHDATE is incorrect - please retry"

fi

if [ $Presents == 10 ] ; then

echo "I have received $Presents presents"

else

echo "Presents is incorrect - please retry"

fi


echo "I was born on a $BIRTHDAY"







IF-ELSE


#!/bin/bash


NAME="George"

if [ "$NAME" = "John" ]; then

echo "John Lennon"

elif [ "$NAME" = "George" ]; then

echo "George Harrison"

else

echo "This leaves us with Paul and Ringo"

fi

#!/bin/bash


NUMBER=16

APPLES=16

KING="LUIS"


if [ $NUMBER -gt 15 ] ; then

echo 1

fi

if [ $NUMBER -eq $APPLES ] ; then

echo 2

fi

if [[ ($APPLES -eq 12) || ("$KING" = "LUIS") ]] ; then

echo 3

fi

if [[ $(($NUMBER + $APPLES)) -le 32 ]] ; then

echo 4

fi


LAB 3


LOOPs

A simple while loop with a count-down!



More


This is one of your lab assignments!

  1. What does it print? Why?

  2. Change "-le 4 " to "-le $1". What will be the output now? Why?

COUNT=4

while [ $COUNT -gt 0 ]; do

echo "Value of count is: $COUNT"

COUNT=$(($COUNT - 1))

done



#!/bin/bash

x=1 # initialization x = 1

i=1

while [ $i -le 4 ]

do

x=`expr $x \* $i`

i=`expr $i + 1`

done

echo x=$x

Arrays

  • my_array=(apple banana "Fruit Basket" orange)

  • echo ${my_array[3]}

  • my_array[4]="carrot"

  • echo ${#my_array[@]} # 5

  • echo ${my_array[${#my_array[@]}-1]} # carrot

  • Initialization of an array

  • Accessing an element of an array

  • Adding a new element (at the end)

  • Getting the length of an array

  • Getting access to the last element

This is the second lab assignment!

Write a bash script that can read numbers stored in a file and prints out the average of the numbers. Provide the name of the file as an argument in command line when executing the script.

Example: ./average.sh num.txt should read the numbers stored in num.txt and print out its average.

Read a file, line by line!

#!/bin/bash

filename="$1"

lineNum=1

while read -r line

do

name="$line"

echo "$lineNum - $name"

lineNum=$(($lineNum + 1))

done < "$filename"


Get the numbers only!

numbersOnly=(`egrep -o '[0-9]{1,3}' num.txt`)

Next...

Use you knowledge on:

  • Arrays

  • Operations (expr)

and combine the code we came up with so far


LAB 4


















Class Slides

C Basics.pdf
C Basics - 2.pdf

TASK 1


Start with this:

  1. Copy the code in a file called "test1.c"

  2. Compile it: gcc -o test1 test1.c

  3. Run it: ./test1

  4. Got warning!? Damn! Can you get rid of them all?


[?] What does the function check do?


int main(){

int result = check(12, 55, 100);

printf("Are they both within the range?\t %d\n", &result);

return 0;

}


int check(int x, int y, int k){


if((x >= 0 && x < k) && (y >= 0 && y < k)){

return 1;

}

else{

return 0;

}

return 0;

}

Then:

  • Look the example here that shows how you can read data from user.

  • Modify your last code such that the user can give all 3 arguments of the function check(x,y,k); .


//Example of I/O

int i, j, k;

printf("Let's get 2 integers:\n");

scanf("%d %d", &i, &j);

TASK 2



Add a new function int digit(int a, int n) that returns the n-th digits of the positive integer a .

In 2 steps:

  • Use the example on the right as a starting point. This function only checks if the the given integer a has n-th digit at all!

  • Finds the n-th digit using division operator.

Call the function in the main method and debug it!

Complete this function:

int digit(int a, int n){


float length = 0.0;

//Check validity of n (if n-th digit exists!)

if(a == 0 || a == 1)

length = 1.0;

else

length = log10(a) + 1;


if(length < n){

return -1;

}


// Here you should get the n-th digit

return 0;

}

Undefined reference to 'log' ?

If you are using some maths functions, you may need:

  • #include<math.h>

  • An extra option (linker) when compiling: gcc -o test1 test1.c -lm

Arrays [...]

Initialization

int arr[5] = {1, 2, 3, 4, 5};

int arr[] = {1, 2, 3, 4, 5};

int arr[5];

malloc calloc

What if we walk of the last element?

int arr[5] = {1,2,3,4,5};

printf("%d \n", arr[5]); // <---- ???

Access to Elements

  • printf("%d\n", a[0]);

  • printf("%d\n", *a);

  • printf("%d\n", *(a+1));

  • printf("%d\n", a[1]);

  • printf("%p\n", a);

  • printf("%p\n", &(*a));

as·ter·isk

*a

The value pointed by a

am·per·sand

&b

The address of the variable b

TASK III







Use the method signatures provided on the right, to implement 3 methods as follows:

  1. largestElement returns the largest element of an array.

  2. average returns the average of an array.

  3. nPositiveNum returns the number of positive integers in an array.

int largestElement(int a, int n){


int largest = 0;

//Code to find the largest

return largest;

}


float average(int a, int n){


float avg = 0.0f;

//Code to find the average

return avg;

}


int nPositiveNum(int a, int n){


int counter = 0;

//Code to count all positive integers

return counter;

}


LAB 5


Strings in C

Class slides


C - 13,14,15.pdf

Already knew? Good!

'\0'

is used to terminate strings literals

'\n'

is used to indicate the end of lines

EOF

is a macro (= -1) to indicte the end of files


How many ways you can store "strings"?

char date1[8] = “June 14”;

char date1[] = “June 14”;

char date1[8] = {‘J’, ‘u’, ‘n’, ‘e’, ‘ ’, ‘1’, ‘4’, ‘\0’};

char date1[] = {‘J’, ‘u’, ‘n’, ‘e’, ‘ ’, ‘1’, ‘4’, ‘\0’};


char *str = “June 14”;




<-- Array of chars



<-- a pointer to a string literal


char date1[] = "June 14";

char date2[10] = "May 04";

char *date1Ptr;


date1Ptr = date1;





Source: https://www.cs.bu.edu/teaching/cpp/string/array-vs-ptr/

date1 @2000

----------------------------------

| J | u | n | e | | 1 | 4 | \0 |

----------------------------------


date2 @3000

-----------------------------------------

| M | a | y | | 0 | 4 | \0| | | |

-----------------------------------------


date1Ptr @4000

--------

| 2000 |

--------

Length v.s. Size

They are not the same!

char str1[5] = "Azim";

printf("The string is \"%s\"\n", str1);

printf("It is of length %zu.\n", strlen(str1));

printf("It is of size %zu.\n", sizeof(str1));

Let's experiment!

#include<stdio.h>

#include<string.h>



int main(){


char str1[8] = "June 14";

char str2[] = "June 14";

char str3[8] = {'J', 'u', 'n', 'e', ' ', '1', '4', '\0'};

char str4[] = {'J', 'u', 'n', 'e', ' ', '1', '4', '\0'};

char *str5 = "June 14";

printf("Length of str%d is [%zu].\n", 1, strlen(str1));

printf("Length of str%d is [%zu].\n", 2, strlen(str2));

printf("Length of str%d is [%zu].\n", 3, strlen(str3));

printf("Length of str%d is [%zu].\n", 4, strlen(str4));

printf("Length of str%d is [%zu].\n\n", 5, strlen(str5));

printf("Size of str%d is [%zu].\n", 1, sizeof(str1));

printf("Size of str%d is [%zu].\n", 2, sizeof(str2));

printf("Size of str%d is [%zu].\n", 3, sizeof(str3));

printf("Size of str%d is [%zu].\n", 4, sizeof(str4));

printf("Size of str%d is [%zu].\n", 5, sizeof(str5));

}


(Length + 1) <= (size)












Guess the output!

  1. What is the LENGTH of str2 ?

  2. How about str5 ?

  3. what is the relation between LENGTH and SIZE for str5 ?

int i = 0;

char* str1 = "Azim";

printf("SIZE :[%lu]\n", sizeof(str1));

printf("LENGTH:[%lu]\n", strlen(str1));

for(i = 0; i < sizeof(str1); i++){

printf("[%c] ", str1[i]);

}

printf("\n");

for(i = 0; i < strlen(str1); i++){

printf("[%c] ", str1[i]);

}

printf("\n");

To iterate over the characters of a string, you need strlen() , and not sizeof()




OUTPUT:

SIZE :[8]

LENGTH:[4]

[A] [z] [i] [m] [] [S] [I] [Z]

[A] [z] [i] [m] ^ ^ ^

Be Careful!

To clean the allocated memory, you need sizeof() .

memset(str1, '\0', sizeof(str1));

Read properly!

char str1[30], ch;

int i = -1;

printf("Enter your string:\n");

while(ch != '\n')

{

i++;

ch = getchar();

str1[i] = ch;

}

str1[i] = '\0';



When reading by char:

Always terminate your string with the null terminator '\0' at the last position.

TASK 1 (avg.c)

Get the average size of a word, from the string given by the user

How:

  1. Prepare a simple code that reads user's input. Does it work?

  2. Count the number of spaces. (store it to int spaceCounter)

  3. Keep track of the total number of characters ( i does that for you!)

  4. A simple but meaningful division should get you the average size.

To Be Added later:

  • While reading, get rid of all non-letters such as numbers, punctuations, etc. (Your code doesn't have to be 100% perfect for this part!)


TASK 2 (Symm.c)

Write a program that checks if a given string is "symmetric" or not!


Example:

Was it a car or a cat I saw?

> Symmetric

Madam, I am Adam!

> Not Symmetric

How:

  1. Start with the code on the right! No error?

  2. Complete each commented section once at a time:

    1. Add the reading section and make sure it works.

    2. Complete the 2nd part and print out the result. Is that correct?

    3. Complete the loop. The comment is almost all you need to do.

To Be Added later:

  • Filter the input such that only the letters and digits count. That is, a string like a ba? should be considered symmetric although it does not start with ? . and it has a white-space with no corresponding match!


#include <stdio.h>

#include <string.h>

int main()

{

int first, middle, last;

printf("Enter your string:\n");

/*

READ THE INPUT STRING HERE.

*/

/*

FIND THE POSITION OF THE first, middle, last

CHARACTER IN THE STRING.

*/

/* TIME FOR CHECKING THE SYMMETRY

FOR (first = 0; first < middle; first++)

{

IF (THE FIRST CHAR IS NOT THE SAME AS THE LAST)

{

BOOoOOM! NOT SYMMETRIC!

}

MOVE last, ONE STEP BACK;

}

IF (FIRST IS THE SAME AS THE LAST)

BOOoOOM! SYMMETRIC!

*/

return 0;

}

TASK 3 (SymmP.c)






Write a program very similar to Symm.c that checks the symmetry of a string, but this time, use pointers, instead of numbers.








If you remember how to have access to elements of an array:

*(arr + k) --> the k-th element of the array

then modifying the last program should be fairly easy for you!

*(text + k) --> ASCI code for the character at position k


LAB 6






Some materials for this section are borrowed from:

  • http://www.zentut.com/c-tutorial/c-linked-list/

Remember STRUCT?

STRUCT v.s. TYPEDEF

struct student {

int age;

};

How to call it?

struct student st1;

+++++++++++++++++++++++++++++++++++++++++++++++++++++++

typedef struct student {

int age;

} student;

How to call it?

student st1;


#include <stdio.h>


typedef struct student {

int age;

char* name;

} student;


int main(){


student st1;

st1.age = 20;

st1.name = "Azim";


printf("[%s] passed 3320 when he was [%d]!\n", st1.name, st1.age);


return 0;

}


Which one to use:

OR

st->age <=> (*st).age

Remember Linked Lists?

A Linked List:

is a linear collection of DATA elements, called nodes, each pointing to the next NODE by means of a POINTER.




(Wikipedia > Linkedlist)

Remember Dynamic Memory Allocation?

Dynamic memory allocation:

void *malloc(size_t size);

Usage:

int *ptr = (int *) malloc(10 * sizeof (int));

Allocates 10 cells in memory each of which of the size needed for an int to be stored. (Equivalent to int arr[10];)


If the allocation succeeds, a pointer to the block of memory is returned. This pointer is guaranteed to be suitably aligned to any type (including struct and such), otherwise a NULL pointer is returned. (more? Click here!)

You are responsible to FREE the memory!

void free(void *pointer);

Usage:

free(ptr);

Create a node:



  • Write a method that creates a new node with the give data and the address.

  • Make your method safe (for the case when malloc fails!)

if(newNode == NULL)

{

printf("Error: malloc failed!\n");

exit(0);

}

  • Call this method in your main() and make sure it works fine!

/*

This method creates a new node based on the

the data and the pointer to the next node.

It returns the newly created node (pointer).

*/

node* createNode(int data, node* next)

{

node* newNode = (node*)malloc(sizeof(node));

newNode->data = data;

newNode->next = next;

return newNode;

}

What is the output of this code?

node* node1 = createNode(10, NULL);

node* node2 = createNode(20, node1);


printf("%d\n", node2->next->data);

What is a HEAD?

We have defined a new concept called a NODE,

But

we did NOT define the Linked List!?

How can we have access to its elements then?!

/**

* This method initializes a linked list by

* creating a new node and setting the head

* to point to this node.

*

* It returns a pointer to the head

*/

node* initializeList(node* head, int data)

{

node* newNode = createNode(data,head);

head = newNode;

return head;

}

Append a new node to the end of the list









  1. Check if the list is not empty.

  2. Take a copy of the HEAD and move it all the way to the end of the list. (It should point to the last element of the list!)

  3. Create the new node.

  4. Make the last node point to the new node as its next node.

/**

* This method creates a new node and

* appends it to the end of the list.

*

* It returns a pointer ot the head.

*/

node* append(node* head, int data)

{

if(head == NULL)

return NULL;

node *tmp = head;

while(tmp->next != NULL)

tmp = tmp->next;

node* newNode = createNode(data,NULL);

tmp->next = newNode;

return head;

}

TASK 1: [Search]




To search for a specific data in our linked list, follow these steps:

  1. Check if the head is not NULL.

  2. Iterate over the list and for each node, check if its data is equal to what we are looking for.

    1. if found: return the pointer to the current node.

    2. if not: return NULL.

/**

* This method searches for the first

* occurance of the data 'data', starting

* from 'head'.

*

* In case of success, it returns a pointer

* to the node containing that data, else, it

* returns NULL.

*/

node* search(node* head, int data)

{

/*

* Iterate over the list and for

* each node, check if its data

* is equal to 'data'.

*/

}

TASK 2: [Doodle]



Suppose:

  • you already have a STRUCT defined called _TA (Shown on the right)

  • you have a linked list whose nodes store _TA's.

  • the linked list already has 4 _TA's in it.

  • the head is pointing to the first node. (Head should not be moved during the process.)

Doodle a cool, step-by-step story for the following scenario:

  1. Add me to your linked list, after the 3rd node (before the 4th one).

  2. Search me by my name (i.e. 'Azim') and return my age.


typedef struct _TA {

char* name;

int age;

} _TA;



Remarks,

  1. Your doodle MUST contain all the details we discussed.

  2. Your doodle MUST be on paper. (Not made by any software!)

  3. I want a doodle, not a boring illustration of boxes and arrows.

  4. An excellent doodle may get some good bonus points.


LAB 7







Some material for this section is borrowed from here.


FILES
















CLASS SLIDES



Chapter 13 - File.pdf

STEP 1: OPEN/CLOSE a file

DESCRIPTION:

The fopen() function opens the file whose name is the string pointed to by path and associates a stream with it.

The argument mode points to a string beginning with one of the following sequences (possibly followed by additional characters, as described below):

  • r Open text file for reading. The stream is positioned at the beginning of the file.

  • r+ Open for reading and writing. The stream is positioned at the beginning of the file.

  • w Truncate file to zero length or create text file for writing. The stream is positioned at the beginning of the file.

  • w+ Open for reading and writing. The file is created if it does not exist, otherwise it is truncated. The stream is positioned at the beginning of the file.

  • a Open for appending (writing at end of file). The file is created if it does not exist. The stream is positioned at the end of the file.

  • a+ Open for reading and appending (writing at end of file). The file is created if it does not exist. The initial file position for reading is at the beginning of the file, but output is always appended to the end of the file.

PROTOTYPE:

FILE *fopen(const char *path, const char *mode);









RETURN VALUE:

Upon successful completion fopen() returns a FILE pointer. Otherwise, NULL is returned and errno is set to indicate the error.

Before you start anything, you need to open the file you wish to read from, or write to.

Opening a file can be done for different purposes, therefore different MODEs should be set. For instance if you want to change something in a file, you need to open it with the WRITE permission.




The table on the right (which I copied from here) contains all you need for all different cases.


File Mode (Cheat sheet)

DESCRIPTION:

close() closes the file descriptor fd, so that it no longer refers to any file and may be reused.


NOTE:

Not checking the return value of close() is a common but nevertheless serious programming error.

PROTOTYPE:

int close(int fd);


RETURN VALUE:

close() returns zero on success. On error, -1 is returned, and errno is set appropriately.

STEP 2: ERROR HANDLING

Why error handling?










  • What if your file doesn't exist?

  • What if your file is broken?

  • What if your OPEN command is not appropriate for this type of file?

  • What if ... ?



You wanna learn more about ERRNO? Start from here.

#include <stdio.h>

#include <errno.h> //Need this for error handling

#include <string.h>

#include <unistd.h> //Need this for fclose();


extern int errno;


int main(){


char * fileName = "lab6.c";

FILE * f;

int errnum = 0;

f = fopen(fileName, "r");

if(f == NULL){

errnum = errno;

fprintf(stderr, "errno: %d\n", errno);

perror("perror");

fprintf(stderr, "Error: %s\n", strerror(errnum));

exit(1);

}

else{

fclose(f);

printf("--> Success!\n");

}

return 0;


A Compact and Safe method for Opening a File

if ((f = fopen(fileName,"r")) == NULL){

errnum = errno;

perror("Error opening the file");

exit(1);

}

// Do whatever you want with the file

fclose(f);

STEP 3: READING / WRITING

DESCRIPTION:

The function fread() reads nmemb items of data, each size bytes long, from the stream pointed to by stream, storing them at the location given by ptr.

The function fwrite() writes nmemb items of data, each size bytes long, to the stream pointed to by stream, obtaining them from the location given by ptr.


NOTE:

fread() does not distinguish between end-of-file and error, and callers must use feof(3) and ferror(3) to determine which occurred.

PROTOTYPE:

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);


size_t fwrite(const void *ptr, size_t size, size_t nmemb,

FILE *stream);


RETURN VALUE:

On success, fread() and fwrite() return the number of items read or written. This number equals the number of bytes transferred only when size is 1. If an error occurs, or the end of the file is reached, the return value is a short item count (or zero).

Example codes:

Here I am putting a few simple methods for reading files, line by line, or character by character.







NOTE:

There are more robust methods out there for a safe OPEN/READ/WRITE file manipulation, but it is out of the scope of this lab.

//Reading char by char from a file


#include<stdio.h>

#include<conio.h>



int main()

{

FILE *f;

char ch;

f = fopen("lab6.c", "w");

printf("Enter data!\n");

while( (ch = getchar()) != EOF)

{

putc(ch,f);

}

fclose(f);

fp = fopen("lab6.c", "r");

while( (ch = getc(f)! = EOF)

printf("%c",ch);

fclose(f);



return 0;

}

//Reading from file, in chuncks of size 1024

#include <stdio.h>

#include <string.h>

#include <errno.h>


#define BUFSIZE 1024

int main(){

char buf[BUFSIZE];

FILE *f;

size_t nread;


f = fopen("lab6.c", "r");


if(f){

while((nread = fread(buf, 1, sizeof buf, f)) > 0)

fwrite(buf, 1, nread, stdout);


if(ferror(f)) {

//Do something with the error

return 0;

}

fclose(f);

}

return 0;

}


CODE NOW!








Prepare your code:

  1. Start with the code on the right. (Make sure it works fine.)

  2. Add the error handling we discussed before.

  3. Print each line on the output with the line number.

//Reading line by line, each line of size max 1000 bytes.


#include<stdio.h>

#include <string.h>


int main()

{

FILE *f;

char buf[1000];


f = fopen("lab6.c","r");

if (!f){

return 1;

}

while (fgets(buf, 1000, f) != NULL){

printf("%s", buf);

}

fclose(f);


return 0;

}

TASK

  • Modify your code such that it read a text file like the one on the right, and prints out only the EVEN numbers.

  • Yes, the file contains NUMBERS only.

  • Yes, there is one number in each line.

SAMPLE FILE:

12

44

23

77

1

9

561

234


CHECK LIST for this TASK:

  1. Code runs with no ERROR or WARNING.

  2. You close the file you opened.

  3. Error handling for:OPENING the file is added

  4. Error handling for READING the file is added.

  5. Error handling for CLOSING the file is added.

  6. Even numbers are detected and printed on the output.