Skip to content

fgets()

fgets(buffer, sizeof(buffer)-1, ReadFH);

Reads 1 line at a time in a file of words Remember it stops at the enter key \n

  • File pointer keeps track of where we are in the file It moves as we do reads and writes

Two types of access

  • Sequential (VHS)

    • Open a file and just read it line by line
  • Random access (DVD)

    • Allows the reading of records in any order

Two standard library functions in standard c to do this

  • fseek(fp, offset, start);
    • Fp File handle
    • Offset (how many bytes do you wanna move)
    • Start (where are we moving from) must be 0 1 or 2 <- #define for these

ftell(fp);

File handle and tells us where we are

fseek(myFile, 0, 0); <- how we get back to beginning of the file

fseek(Myfile, 21, SEEK_SET); SEEK_SET is defined as 0 SEEK_CUR = 1 SEEK_END = 2

Formatted input and output Sscanf() and sprintf()

sprintf(buffer, “%s %s has student id %s”, first_name, last_name, id); Instead of printing to screen or scanning from screen it puts the stuff into buffer or a char array[];

Takes pieces and ties it together in one string

sscanf(buffer, control_string, args);

This does the opposite from sprintf(); it takes puzzle and rips the pieces out Its like strtok but not as advanced It parses but it looks for white spaces works good for phrases

%*s reads it and then throws away what it reads

Layout of Memory

Higher addresses External Data Segment Command line arguments Environment variables

Lower Addresses Stack Statically allocated variables

        |
        \/

        /\
	|

Heap

Dynamtically allocated variables Uninitialized Data Segment Unitialized global and static variables Initialized data segment Initialized global and static variables

Code Segment Programs source code

Differences between Static vs statically allocated

  • Static
    • Is a storage class
    • Automatically initialized as zero
    • Run for the whole program and dont get reset
  • Statically allocated
    • Like int cat
    • And how we normally do our stuff
    • At the time the program compiled we know that this variable is going to take this much memory
    • (DOES NOT MEAN STATIC STORAGE CLASS)

Stack vs heap

Stack

  • Stores auto variables
  • Nice and neat stack
  • Orderly
  • Stack is used for static memor allocation like int cat;
  • Manges memory for you
  • Variables cannot be resized
  • Access is easier faster and cache friendly
  • Not flexible, allotted memory cannot be changed
  • Faster access allocation and deallocation

Heap

  • Not so nice and stacked up
  • Not orderly and can become fragmented
  • Used for dynamic memory allocation (ask program on fly to allocate it
  • Memory management needs to be done manually
  • Variables can be resized
  • Causes more cache misses because of being dispersed throughout memory
  • Flexible and allotted memory can be altered
  • Slower access allocation and deallocation (not significant)
  • Both are stored in computers RAM

Dynamic Allocation and de-Allocation of memory

Functions for dynamic allocation and deallocation

  • malloc()
  • calloc()
  • Realloc()
  • free()

Must include stdlib.h

malloc()

Void *malloc(size_t size)

One parameter the num of bytes Returns a void pointer which means it can be put into any pointer type Memory is allocated is unitialized

Arrayptr1 = malloc(arraysize*sizeof(int));

Calloc()

Void *calloc(size_t n, size_t size); First parameter Num of items Second Size of each item Returns address of the first byte

Malloc doesnt 0 it when freeing it up Calloc does

Malloc is faster but doesnt zero it

Freeee

Void free(void *ptr);

Free should be used when allocated memory is no longer needing in order to avoid memory leaks

A memory leak is caused when a program fails to release discarded memory it caused impaired performance or failure

Free does NOT set your pointer to null To combat this problem You should Probably set it to NULL

Realloc

Void *realloc(void *ptr, size_t newsize) Takes memory you have and makes it BIGGER

Whether or not itl change the pointer depends sorta

Sometimes realloc will move the address sometimes it wont Its literally the perfect mover no headache except the new memory has trash

Old data is not lost and newly allocated memory is not initialized

If it falls you will get back null and the old memory remains the same

Always adds new stuff to the end of it

How do we move things around? A bit harder to do but possible Linked lists enable this But also make it EASIER

Linked List

Linked list are a linear data structure consists of groups of nodes in a sequence

Nodes

Pieces of a linked list (like array’s cells we say linked lists nodes)

Nodes are just a struct Is going to malloc Contains a pointer within a struct

  • NODES ALWAYS CONTAIN A POINTER

Holds the address of the next node Each node holds it own data But always holds the address of the next node like link in a chain Hence linked list

Not necessarily next to each other in memory (never make assumptions where the nodes are in memory)

Advantages

  • Dynamic: therefore only allocate memory when you need to Insertions and deletions operations are easily implemented Stacks and queues can be easily executed

Disadvantages

  • Memory is wanted due to extra storage needed for pointer No element can be accessed randomly Sequentially accessed like VHS tapes

Single linked list

Only 1 node can see another node Thats why it cant be randomly accessed

How to think of linked list in memory

Heads are just the pointer to the first node

Last one always gets pointed to null (its like null terminating a string)

If you want to add a node to a linked list: Create a new node malloc it And depending on where we wanna add it its easy to do. If you wanna change it to be on the end, we change the null ptr to the new node

Inserting a node

  • You point the node behind,and point the new node to the next one So much easier, no one gets moved only have to change 2 ptrs

Delete a node

  • You have to free the node Then change the ptr to null if its pointing to nothing Just change the ptrs Does not require data to be moved

Not much code involved with linked lists

Head node Code partt

Struct node
{
	Int node_number;
	Struct node *next_ptr; //works because its not nesting a struct inside of itself, its a ptr
};
//creating the head node
Struct node *LinkedListHead;// not a node but a ptr of type node
LinkedListHead = NULL; //MUST SET THE HEAD TO NULL

 //can be lots of other data, you dont need to number the nodes


Struct node *NewNode;
NewNode = malloc(sizeof(struct node));
NewNode->node_number = NodeNumbeToAddl
NewNode->next_ptr = NULL;

If (LinkedListHead == NULL)
{
Linkedlisthead = newnode;
}

Traversing through linked list + displaying node // this is essential

TempPtr = LinkedListHead; //start at the head

While (TempPtr->next_ptr != NULL)
{
    Temptr = temptr->next_ptr
}
//Stops at the last node

While (TempPtr != NULL) //this is different than the one above
//Pasts the last node

Inserting nodes

Struct node *temptr, *Newnode, *preptr;

Prevptr = NULL;
Tempptr = Linkedlist

While (Tempptr != NULL && Tempptr->node_number < nodenumbertoinsert) //node number is example
{
    Prevptr = temptr;
    Tempptr = temptr->next_ptr;
}

if(prevptr == NULL)
{
    Linkedlisthead = newNode;
}
Else
{
   Prevptr->next_ptr = newnode;
}

Put print statement inside of traversal to display a linked list

Display nodes

  • use the (tempptr != NULL) while loop to print the whole list

Deleting node

  • Code for deleting is similar to inserting
Temptr = linkedlisthead; prevptr=  null;
While (tempptr->next_ptr != NULL && temptr->noe_number !- Numberofnodetodelete)
{
	Prevptr = temptpr;
	Temptpr = temptpr->next_ptr
}
if(temptpr->node_number == numberofnodetodelete)
{
   If (temptr == Linkedlisthead)
   {
       Linkedlist head = temptr->next_ptr;
   }
   Else
   {
      prevptr ->next_ptr = temptr->next_ptr;
   }
   free(tempptr);
}
else
{
   printf(“this is not the node you’re looking for\n”);
}

Very similar to inserting.

Counting nodes

Struct node *TEmpPtr;
Int node_count = 0;

Tempptr = linkedlisthead;

while(temptptr != NULL)
{
   Tempptr =tempptr->next_ptr;
   Node_count++;
}

Easiest way to see how your linked list looks is to draw it out after counting how many you have.

Newnode = malloc(sizeof(node));
if(*Linkedlisthead == null)
{
	*Linkedlisthead = Newnode;
}
Else
{
	Tempptr = *Linkedlisthead;
	While ( tempptr->next_ptr != NULL)
	{
		Temptpr = tempptr->next_ptr;
	}

	tempptr->next_ptr = newnode;
}

Typedef structs nodes
Typedef struct node
{
	Int node_number;
	Struct node *next_ptr;
}
Node;

Node *linkedlisthead = NULL;

Passing head of linkedlist is easy

displaylinkedlist(linkedlisthead); That easy

read a file with variable length fields using dynamic memory allocation

Tacobell example

Want to store it without arrays

Typedef struct
{
	Char *category;
	Char *name;
	Char *whatsincluded;
}
TACOBELL;

Int main(int argc, char *argv[])
{
	TACOBELL menu[20] = {};
	Char *token = NULL;
	Char filename[20] = {};
	FILE *FH = NULL;
	Char fileline[200];
	Int menucount = 0;
	Int i;

	strcpy(filename, argv[1]);
	FH = fopen(filename, “r+”);

	If ( FH == NULL)
	{
		printf(“File did not open);
		exit(0);
	}
	
	While ( fgets(fileline, sizeof(fileline)-1, FH) )
	{
		Token = strtok(Fileline, “|”);
		Menu{MenuCount].category = malloc (strlen(token)*sizeof(char)+1); 

        /*because we malloced this space we know tacos is ours */

		strcpy(Menu[MenuCount].category, token);
		
		Token = strtok(NULL, “|”);
		Menu{MenuCount].name = malloc (strlen(token)*sizeof(char)+1);
        strcpy(Menu[MenuCount].name, token); 

        Token = strtok(NULL, “|”);
        Menu{MenuCount].whatsincluded = malloc (strlen(token)*sizeof(char)+1);
        strcpy(Menu[MenuCount].whatsincluded, token); 

        menucount++;

	}
For (i = 0; i<menucount; i++)
{
    printf(“category : %s\n Name       : %s\n what’s included : %s\n\n”, menu[i].category, menu[i].name, menu[i].whatsincluded;

}

Stacks and Queues

Just linked lists with rules

Stack

Stack is a linear data structure that follows a particular order in which the operations are preformed. The order will be LIFO (Last in First Out).

  • LIFO works like a stack of plates.
  • Stacks can be popped(taken out) and pushed( put back in)
  • Operations on stack
    • Push: adds an item to the stack
    • Pop: removes an item from the stack.
    • Peek: returns element of top stack
  • isEmpty returns true if stack is empty, else false
  • A lot of things use stacks, the undo button, is a stack
Typedef struct node
{
	Int node_number:
	Struct node *next_ptr;
}
node:
  • Stack is literally a linked list but with rules
Node *StackTop = NULL; (could call it linkedlisthead but since we have stack rules yknow)

Stacks are meant for push and pop, nothing more

Stack Push

Void push(node **StackTop, int Node_Number)
{
	Node *NewNode = malloc(sizeof(node));
	newnode->node_number = nodenumber;
	newnode->next_ptr = NULL;

	if(*StackTop == NULL)
	{
		*StackTop = Newnode;
	}
	Else
	{
		newnode->next_ptr = *StackTop;
		*Stacktop = newnode;
	}
}

Stack Pop

Void pop(node **STackTop)
{
	Node *Temptr = (*StackTop)->next_ptr;
	
	if(*Stacktop == NULL)
	{
		printf(“Stack is empty\n\n”);
	}
	Else
	{
		free(*StackTop);
		*StackTop = TempPtr;
	}
}