c programming notes - part 2

19
Memory functions Malloc() and free() #include <stdio.h> #include <stdlib.h> void main() { int *nums = malloc(sizeof(int)*5); //Dynamically allocate a contiguous memory space from the heap to store 5 integers. The sizeof() function is used because different computers tore data variables differently. for (int i = 1; i <= 5; i++) { nums[i] = i; printf("%i\n", nums[i]); } free(nums); //frees the memory held by nums return 0; } Memcpy() #include <stdio.h> #include <stdlib.h> #include <string.h> void main() { int nums[] = {1,2,3,4,5}; int *nums2 = malloc(sizeof(int)*5); memcpy(nums2, nums, sizeof(int)*5); //The first parameter is the destination, then the source and finally the amount of memory to copy. for (int i = 0; i < 5; i++) printf("%i\n", nums2[i]); free(nums2); return 0; }

Upload: ratnadeep-bhattacharya

Post on 18-Jan-2016

10 views

Category:

Documents


0 download

DESCRIPTION

C Programming notes

TRANSCRIPT

Page 1: C Programming Notes - Part 2

Memory functions

Malloc() and free()

#include <stdio.h>#include <stdlib.h>

void main(){ int *nums = malloc(sizeof(int)*5); //Dynamically allocate a contiguous memory space from the heap to store 5 integers. The sizeof() function is used because different computers tore data variables differently. for (int i = 1; i <= 5; i++) { nums[i] = i; printf("%i\n", nums[i]); }

free(nums); //frees the memory held by nums

return 0;}

Memcpy()

#include <stdio.h>#include <stdlib.h>#include <string.h>

void main(){ int nums[] = {1,2,3,4,5}; int *nums2 = malloc(sizeof(int)*5); memcpy(nums2, nums, sizeof(int)*5); //The first parameter is the destination, then the source and finally the amount of memory to copy. for (int i = 0; i < 5; i++) printf("%i\n", nums2[i]);

free(nums2);

return 0;}

#include <stdio.h>#include <stdlib.h>#include <string.h>

void main()

Page 2: C Programming Notes - Part 2

{ char myString[] = "Adam likes dogs"; // This is created on the stack which is a RW part of memory. char *name = "Rick"; // This is on the RO data segment. So if we edit this then this will first be copied to the stack and then edited – which is much slower. //memcpy(&myString[0], name, sizeof(char)*4); --- This also works memcpy(myString, name, sizeof(char)*4); printf("%s\n", myString);

return 0;}

Memset()

#include <stdio.h>#include <stdlib.h>#include <string.h>

void main(){ int *nums = malloc(sizeof(int) * 5); memset(nums, 0, sizeof(int) * 5); //memset() sets a value (0) to a certain amount of memory at a certain place in memory.

return 0;}

Memcmp()

#include <stdio.h>#include <stdlib.h>#include <string.h>

void main(){ int nums1[] = {1,2,3,4,5,6}; int nums2[] = {1,2,3,4,5,6}; if (memcmp(nums1, nums2, sizeof(nums1)) == 0) //memcmp() takes two chunks of memory (nums1 and nums2 here) and compare them for a given amount of size. //sizeof(nums1) will not work if it is created in the heap using malloc() or something similar. printf("They are equal\n"); else printf("They are not equal\n"); return 0;}

Realloc()

Page 3: C Programming Notes - Part 2

This function is used to reallocate the amount of memory allocated from something from heap using malloc.

#include <stdio.h>#include <stdlib.h>#include <string.h>

void main(){ char *characters = malloc(sizeof(char) * 10); for (int i =0; i < 5; i++) characters[i] = i + 65; //65 is the numerical value for A. In the first run, i = 0 so A is stored in the first place. In the second run i = 1, so 1+65 = 66 or B is stored and so on. for (int j = 0; j < 5; j++) printf("%c\n", characters[j]);

characters = realloc(characters, sizeof(char) * 5); // realloc() returns a new block of 5 chars at a new location.

free(characters);

return 0;}

Reading from files

All file related programs are in stdio.h.

#include <stdio.h>#include <stdlib.h>#include <string.h>

void main(){ //The following piece of code opens a file and reads the first character FILE *file = fopen("F:\\Studies\\Programming\\My Programming Notes\\Example.txt", "r"); //The fopen() function opens a file in read mode. The other modes are append, write and so on. The mode argument is passed as a string. It creates a file structure in memory and returns a FILE type pointer to that structure. printf("%c\n", fgetc(file)); //fgetc() reads the first character in the file. fclose(file); //Close the file. //In this case, we are going to read the entire file. The reason to close and reopen the file again is make fgetc() read from the beginning again. file = fopen("F:\\Studies\\Programming\\My Programming Notes\\Example.txt", "r"); //The file pointer is simply re-used. char c; do

Page 4: C Programming Notes - Part 2

{ c = fgetc(file); printf("%c", c); } while (c != EOF); //fgetc() returns an EOF constant when it reaches the end of the file. fclose(file);

return 0;}

Fscanf()

#include <stdio.h>#include <stdlib.h>#include <string.h>

/*The file Example2.txt contains the total number of entries at the top. In each line the first number denotes the number of characters in each name, then the name and then a score.*/

//The next structure is designed to hold the data - name and score - from the file in a structure.typedef struct{ char *name; int score;} Entry;

void main(){ FILE *file = fopen("F:\\Studies\\Programming\\My Programming Notes\\Example2.txt", "r"); int entryCount; //This variable is used to decide how much memory needs to be assigned in heap for the structure. fscanf(file, "%i", &entryCount);

Entry *entries = malloc(sizeof(Entry) * entryCount);

for (int i = 0; i < entryCount; i++) //This for loop fills up the structure by reading from the file. { int nameLen; //This variable is used to decide the amount of memory in heap required to hold each name. fscanf(file, "%i", &nameLen);

entries[i].name = malloc(sizeof(char) * (nameLen + 1)); fscanf(file, "%s %i", entries[i].name, &entries[i].score);

printf("%i. %s - %i\n", i+1, entries[i].name, entries[i].score); }

//Memory clean up

Page 5: C Programming Notes - Part 2

fclose(file); for (int i = 0; i < entryCount; i++) free(entries[i].name); free(entries); return 0;}

Fputc() and fputs()

#include <stdio.h>#include <stdlib.h>#include <string.h>

void main(){ FILE *file = fopen("F:\\Studies\\Programming\\My Programming Notes\\WriteTest.txt", "w"); //In the write mode, the file will be created if it doesn't exist. If it exists then it will be overwritten. fputc('G', file); //Writes a single character to the file. fclose(file); return 0;}

#include <stdio.h>#include <stdlib.h>#include <string.h>

void main(){ FILE *file = fopen("F:\\Studies\\Programming\\My Programming Notes\\WriteTest.txt", "w"); fputs("This is good", file); fclose(file); return 0;}

Fprintf()

#include <stdio.h>#include <stdlib.h>#include <string.h>

void main(){ FILE *file = fopen("F:\\Studies\\Programming\\My Programming Notes\\Student.txt", "w"); //The student.txt file got created.

int studentCount; printf("How many students are there?\n"); scanf("%i", &studentCount);

Page 6: C Programming Notes - Part 2

fprintf(file, "%i\n", studentCount);

for (int i = 0; i < studentCount; i++) { char studentName[30] = {0}; float gpa;

printf("What is the student's last name?\n"); scanf("%s", studentName);

printf("What is the student's gpa?\n"); scanf("%f", &gpa);

fprintf(file, "%i\t%s\t%.2f\n", strlen(studentName), studentName, gpa); }

fclose(file); return 0;}

Editing a text file

#include <stdio.h>#include <stdlib.h>#include <string.h>/*In case of editing a file, a new temp file is created and then renamed as the original file, after the original has been removed.*/

//This struct will hold the name and gpa of the passing students.typedef struct{ char *name; float gpa;} student;

void main(){ FILE *originalFile = fopen("F:\\Studies\\Programming\\My Programming Notes\\Student.txt", "r"); FILE *newFile = fopen("F:\\Studies\\Programming\\My Programming Notes\\Student_temp.txt", "w");

int studentCount; fscanf(originalFile, "%i", &studentCount);

student *passingStudents = malloc(sizeof(student) * studentCount); //Creating the passingStudents structure.

int passingCount = 0;

Page 7: C Programming Notes - Part 2

int nameLen; //This for loop reads from the original file and fills the passingStudents structure. for (int i = 0; i < studentCount; i++) { fscanf(originalFile, "%i", &nameLen);

char *name1 = malloc(sizeof(char) * (nameLen + 1)); name1[nameLen] = '\0';

float gpa1;

fscanf(originalFile, "%s %f", name1, &gpa1);

if (gpa1 >= 6.50) { passingStudents[passingCount].name = name1; passingStudents[passingCount].gpa = gpa1;

passingCount++; } }

fprintf(newFile, "%i\n", passingCount); //Add the number of passing students.

for (int i = 0; i < passingCount; i++) //Fill up the new file from the structure. fprintf(newFile, "%i\t%s\t%.2f\n", strlen(passingStudents[i].name), passingStudents[i].name, passingStudents[i].gpa);

fclose(originalFile); fclose(newFile);

remove("F:\\Studies\\Programming\\My Programming Notes\\Student.txt"); rename("F:\\Studies\\Programming\\My Programming Notes\\Student_temp.txt", "F:\\Studies\\Programming\\My Programming Notes\\Student.txt");

return 0;}

Appending text to a file

#include <stdio.h>#include <stdlib.h>#include <string.h>

void main(){

Page 8: C Programming Notes - Part 2

FILE *file = fopen("F:\\Studies\\Programming\\My Programming Notes\\Example.txt", "a"); //It will create the file. fputs(" This is just getting better.", file); fclose(file); return 0;}

Itoa()

#include <stdio.h>#include <stdlib.h>#include <string.h>

void main(){ int num = 53; char str[10] = {0}; itoa(num, str, 10); printf("%s\n", str);

return 0;}

Sprintf()

#include <stdio.h>#include <stdlib.h>#include <string.h>

void main(){ char fstr[30] = {0}; sprintf(fstr, "%i %.2f %c", 67, 45.67, 'r'); //prints to the string fstr and not to the screen printf("%s\n", fstr);

return 0;}

Converting string to number

#include <stdio.h>#include <stdlib.h>#include <string.h>

void main(){ char *c = "582 is a number. 673";

Page 9: C Programming Notes - Part 2

int i = atoi(c); //This function will start reading from wherever c is pointing to and read all the numbers till it hits something that is not a number. Thus 673 is ignored. int j = atoi(&c[17]); //17 is the index in c where 6 is located. printf("%i\t%i\n", i,j);

return 0;}

Time functions

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>

void main(){ time_t currentTime; //Time in C is stored in a time_t struct time(&currentTime); //time() gets the current time of the system and stores in the currentTime struct

printf("%s\n",ctime(&currentTime)); //The right-arrow is used to access individual fields in the struct.

return 0;}

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>

void main(){ time_t currentTime; //Time in C is stored in a time_t struct time(&currentTime); //time() gets the current time of the system and stores in the currentTime struct /*In the next line we convert the struct of type time_t to a struct of type tm. This is done so that we can access the different fields of the struct. The function that does this is the localtime() function. myTime is defined as a pointer because the localtime function returns a pointer.*/ struct tm *myTime = localtime(&currentTime); printf("%i\n",myTime->tm_mon+1); //The right-arrow is used to access individual fields in the struct. C by default starts the month from 0, so the +1 gives the correct month integer. return 0;}

Page 10: C Programming Notes - Part 2

Timing execution time

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>

void main(){ for (int i = 0; i < 10000000; i++);

int ticks = clock(); //clock() measures how many ticks the program executed for. printf("%i\n", ticks); printf("%f\n", (float)ticks/CLOCKS_PER_SEC); //CLOCKS_PER_SEC is a constant that gives ticks per second. return 0;}

Storing functions as variables

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>

//The original function add and mul need to be defined first.int add(int a, int b){ return a + b;}

int mul(int a, int b){ return a*b;}

//Here the first parameter of the printResult function can be any function that has two integer arguments and the arguments of that function.void printResult(int (*someFunction2)(int, int), int arg0, int arg1){ printf("The value is %i\n", someFunction2(arg0, arg1));}

int main(){ //This is how a function is set up as a variable. The first 'int' is the return type of the function. someFunction is the reference name. And this is followed by a list of the type of each argument. int (*someFunction1)(int, int) = add;

Page 11: C Programming Notes - Part 2

printf("The addition is %i\n", someFunction1(6,7));

printResult(mul, 6, 7);

return 0;}

The generic pointer (void *)

It can point to anything – an integer, a float, a struct etc.

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>

typedef struct{ int num, denom; char *name;} fraction;

int main(){ int i = 7; float f = 3.9; fraction fract = {5, 6, "Adam"};

void *myPointer = &i; printf("%i\n", *(int*)myPointer); //Dereferencing void pointers are not allowed because the compiler has no idea what the generic pointer holds. So in this case we are casting it as an int pointer to print out the content.

return 0;}

Generic swap function

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>

//Using generic pointers to create a generic swap function.void genericSwap (void *a, void *b, size_t size){ void *temp = malloc(size); memcpy(temp, a, size);

Page 12: C Programming Notes - Part 2

memcpy(a, b, size); memcpy(b, temp, size); free(temp);}

typedef struct{ int num, denom;}fraction;

int main(){ //Testing the generic swap on structs fraction fract1 = {5, 6}; fraction fract2 = {2, 3};

printf("Before fract1 = %i/%i, fract2 = %i/%i\n", fract1.num, fract1.denom, fract2.num, fract2.denom); genericSwap(&fract1, &fract2, sizeof(fraction)); printf("After fract1 = %i/%i, fract2 = %i/%i\n", fract1.num, fract1.denom, fract2.num, fract2.denom); //Testing the same generic swap function on characters char c1 = 'a'; char c2 = 'b'; printf("%c, %c\n", c1, c2); genericSwap(&c1, &c2, sizeof(char)); printf("%c, %c\n", c1, c2);

return 0;}

Linear Search with Integers

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>

//Searches through an array and returns the index of the element key in the array. Returns -1 if the key is not found.int linearSearch(int *array, int len, int key){ for(int i = 0; i < len; i++) { if (array[i] == key) return i; }

return -1;

Page 13: C Programming Notes - Part 2

}

int main(){ int nums[5] = {5, 8, 19, 45, 23};

printf("%i\n", linearSearch(nums, 5, 19));

return 0;}

Generic Linear Search

#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>

//Since a generic pointer is used, the size needs to be passed as well. And the function required to compare that data type since generic pointers cannot be dereferenced.int glinearSearch(void *array, size_t elemSize, int len, void *key, int(*cmp) (void *a, void*b)){ for(int i = 0; i < len; i++) { void *currentElem = array + (elemSize * i); if (cmp(currentElem, key) == 0) return i; }

return -1;}

typedef struct{ int num, denom;} fraction;

int fractCompare (fraction *f1, fraction *f2) //This function will be passed as int(*cmp) (void * a, void *b). The fraction *f1 and fraction *f2 arguments are alright, since generic pointers are implicitly casted.{ //The fractions are converted to floats so that 1/2 and 8/16 can be evaluated as equal. float f1val = (float)f1->num/(float)f1->denom; //The casting as floats are done to avoid errors of integer division. For example, in integer division, 1/2 = 0. float f2val = (float)f2->num/(float)f2->denom; if (f1val == f2val) return 0; else return 0xBeef;

Page 14: C Programming Notes - Part 2

}

int main(){ fraction fract[5] = { {1,4}, {3,5}, {2,5}, {1,3}, {8,16} }; fraction key = {1,2};

int index = glinearSearch(fract, sizeof(fraction), 5, &key, fractCompare); printf("%i\n", index);

return 0;}

Binary Search Algorithm with Integer Array

The binary search needs the array to be already sorted. But once the array is sorted, it is much faster than linear search.

#include <stdio.h>#include <stdlib.h>#include <string.h>

//The funda of binary search is to break the array down into two parts, compare the key to the middle element of the array. If the key is larger then repeat the process with the right side of the array. If the key is smaller then repeat the process with the left side of the array.int binarySearch(int *array, int len, int key){ int low = 0, high = len - 1, currentIndex; //low points to the starting element and high points to the last element. currentIndex for the moment points to roughly the middle element.

while (low <= high) { currentIndex = (int)(high - low)/2; if(array[currentIndex] = key) return currentIndex; else if (array[currentIndex] > key) high = currentIndex; else if (array[currentIndex] < key) low = currentIndex; } return -1;}

int main(){ int arr[8] = {2, 3, 5, 9, 12, 16, 21, 34}; printf("%i\t%i\n", binarySearch(arr, sizeof(arr), 10), binarySearch(arr, sizeof(arr), 21));}

Page 15: C Programming Notes - Part 2

Generic binary search algorithm

#include <stdio.h>#include <stdlib.h>#include <string.h>

int gbinarySearch(void *array, size_t elemsize, int len, void *key, int(*cmp)(void *a, void*b)){ int low = 0, high = len - 1, currentIndex;

while (low <= high) { currentIndex = (high+low)/2; void *currentElem = array + (currentIndex * elemsize); if (cmp (key, currentElem) == 0) return currentIndex; else if (cmp(key, currentElem) < 0) high = currentIndex; else low = currentIndex; } return -1;}

typedef struct{ int num, denom;} fraction;

int fractCompare (fraction *f1, fraction *f2){ float f1val = (float)f1->num/(float)f1->denom; float f2val = (float)f2->num/(float)f2->denom;

return (f1val - f2val) * 100; //This is a positive value when f1val > f2val and so on. The multiplication by 100 is used because the return type of the function in int.}

int main(){ fraction fracts[6] = {{1,2}, {2,3}, {3,4}, {5,6}, {4,7}, {6,9}}; fraction key = {9,12}; int index = gbinarySearch(fracts, sizeof(fraction), 6, &key, fractCompare); printf("%i\n", index);}

Page 16: C Programming Notes - Part 2

Recursion

Writing a recursive function to add the digits of an integer.

#include <stdio.h>#include <stdlib.h>#include <string.h>

int sumDigits(int);

int main(){ int n = 12346; printf("%i\n", sumDigits(n));}

int sumDigits(int a){ if (a == 0) return 0; //This is the breakout condition of the program. int s, new_num; s = a % 10; //This takes out the last digit. new_num = a / 10; //This creates a new integer without the last digit. return s + sumDigits(new_num);}