Friday, 13 March 2015

Super Simple Linked List In C

When writing code in a high level scripting language like Perl, Ruby or Python it is easy to take for granted what a nice feature it is to have automatic types like arrays or hashs. Variable that you can just dump data in to and pull it back out any way you like. These features were not always there, someone had to write the code to make it to this.

A linked list in C is a way to store values, as many as you like for as much memory as you have. Memory for a variable is created on the fly as needed and stored in a location that knows information about it's neighbour.  A good linked list will have features to let you search, insert, delete from any point, move backwards and forwards in the list and most importantly a good list would protect your code from accidental memory bugs. My example today has non of those features.

This is the bare minimum of a simple linked list. It is a single linked list so you can only move forward. A double linked list lets you move backwards also.
#include<stdio.h>
#include<stdlib.h>

struct DataNode {
 void *Load;
 struct DataNode *Next;
};

struct DataNode *TheFirst = NULL;
struct DataNode *Current = NULL;
struct DataNode *Last = NULL;

void* NewList(void *Load) {
 struct DataNode *Pointer = (struct DataNode*)malloc(sizeof(struct DataNode));
 if(NULL == Pointer) {
  return NULL;
 }
 Pointer->Load = Load;
 Pointer->Next = NULL;

 TheFirst = Last = Current = Pointer;
 return(Pointer);
}

void* Add(void *Load) {
 if(TheFirst == NULL) {
  return (NewList(Load));
 }

 struct DataNode *Pointer = (struct DataNode*)malloc(sizeof(struct DataNode));
 Pointer->Load = Load;
 Pointer->Next = NULL;

 Last->Next = Pointer;
 Current = Last = Pointer;
 return(Pointer);
}

void* First() {
 Current = TheFirst;
 if(Current == NULL) return(NULL);
 return(Current->Load);
}

void* GetNext() {
 struct DataNode *Pointer = Current;

 // Advance to next
 if(Pointer->Next) {
  Current = Pointer->Next;
  return(Current->Load); 
 }
 return(NULL);
}

int DeleteFirst() {
 int Return = 0;
 if(TheFirst) {
  if(TheFirst->Next) {
   Current = TheFirst->Next;
   Return = 1;
  } else {
   Current = NULL;
  }
 }
 free(TheFirst);
 TheFirst = Current;
 return(Return);
}

int main(void) {
 char* ToDoList;
 Add("Pet the dog");
 Add("Feed the fish");
 Add("Let the cat out");
 Add("Do the dishes");
 Add("Gas up the car");
 Add("Watch some TV");
 ToDoList = First();
 while(ToDoList != NULL) {
  printf("%s\n", ToDoList);
  ToDoList = GetNext();
 }
 while(DeleteFirst()) {}
 return 0;
}

Tuesday, 3 March 2015

Instant hash in Perl, just do the splits

Today I needed a Perl script that could create a lot of hash cells fast and the names of the cells will not be know until run time. I did not want to use a for loop, I looked for a better way to do this in less code. When I found the solution I was reminded of some Perl documentation that I read saying that most people think the @ symbol means an array but it does not, it means many. The way this works it when you reference the hash with the @ symbol you can put many values in to many cells in one line of code.

The first split turns the Fields string in to the cell name identifiers, the second split turns the Values string in to the data, putting many data in to many cells named in a hash.



#!/usr/bin/perl

my $Fields = "name:address:phone";
my $Values = "Bob:123 Hill Rd:505-050-4321";
my %Hash;
@Hash{split(/:/, $Fields)} = split(/:/, $Values);

for my $key (keys %Hash) {
 print "$key = '$Hash{$key}'\n";
}