2011 in review

January 7, 2012 at 11:55 am | Posted in Uncategorized | Leave a comment

The WordPress.com stats helper monkeys prepared a 2011 annual report for this blog.

Here’s an excerpt:

The concert hall at the Sydney Opera House holds 2,700 people. This blog was viewed about 14,000 times in 2011. If it were a concert at Sydney Opera House, it would take about 5 sold-out performances for that many people to see it.

Click here to see the complete report.

Bitwise-Shifting in C

December 1, 2011 at 12:11 pm | Posted in Uncategorized | Leave a comment
Tags: , , , ,

In my two and a half years stint with C, I was never able to comprehend what bitwise operator do. A few days back I was searching for top C interview questions and I came across this piece of code:

#include <stdio.h>

int main(void)
{
  printf("%x\n", -1<<4);

  return 0;

}

=============== OUTPUT ====================
/home/arnuld/programs/C $ gcc -ansi -pedantic -Wall -Wextra interview-2.c
/home/arnuld/programs/C $ ./a.out
fffffff0
/home/arnuld/programs/C $

If you change %x to %d, you will get -16 as result, fffffff0 is just hexadecimal representation of it. You see that I am using strict ANSI mode and there are no warnings, program compiles fine and gives output as fine as input. Did you notice something wrong ?

Google for n1256.pdf, draft of the ANSI standard and it will be sufficient for your needs if your need is to become a C programmer following ANSI standard and this is what I do. n1256.pdf in Section 6.5.7 (4) states:

The result of E1 << E2 is E1 left shifted E2 bit positions; vacated bits are filled with zeroes. If E1 has unsigned type, the result is E1x2^E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1x2^E2 is representable in the result type, then that is resulting value; otherwise , the behavior is undefined.

If you pick up a copy of C – A Reference manual by Harbison and Steele 5th editon, lovingly known as H&S5, you will see section 7.6.3 states:

  1. Applying the shift operator >> is not portable when the left operand is negative, signed value and the right operand is nonzero.
  2. The result value of shift operator is undefined if the value of right operand is negative. The result value is also undefined if the valu eof right operand is greater than or equal to the width (in bits) of the value of the converted left operand.
  3. The right operand may be zero, in which case no shift occurs and result value is identical to the value of the left operand
  4. Each operand must be an integral type. The usual unary conversions are performed on each operand and the result is the converted left operand. The result is not an lvalue.

Did you notice how many things you learned by oberving simple one line program ? Almost 5 basic distinctions before you start using bit-shifting in production environment. I have seen programmers in India (both CS engineering students and professionals doing C programming for almost a decade) always trying to srtive for writing bigger and complex programs and almost always avoiding all these small details of how any one of the C’s basic data structues or operators work. They almost hate going into basics. At the same time I observed masters and C experts writing small, terse, succinct and simpler programmes. I follow the masters. Who does not want to become a good C programmer ?

It is proved that this interview code has undefined behavior. (unfortunately it was a MCQ (Multiple Choice Question) and undefined behavior was not one of the options. You can Google for this question and see the answers for yourself ).

The above problem is just half of the story. Ben Bacarisse on comp.lang.c told me the other half of the story. The “%x” inside printf() expects an unisgned int argument but interview questions is passing it a signed value hence causing Undefined Behavior (UB in short). Hence above interview code is broken 2 times. Replacing that printf with printf(“%x\n”, (unsigned)-1<<4); would have fixed both problems. You can see the original discussion at Google groups and Rhinocerus forums and Velocity Reviews Forums using your web browser. Once again they all represent web-inerface to Usenet newsgroup comp.lang.c. I use PAN for reading comp.lang.c. Google for the list of news readeing softwares.

In fact, this another program is god for understanding how bit shifting works. Again I got it from comp.lang.c discussions:

#include <stdio.h>

enum { LIMIT = 16 };

int main(void)
{
  int i;

  for(i = 0; i <= LIMIT; ++i)
    {
      printf("%d is shifted left by %d bits, place %s = %d\n", 100, i, i==1?"":"s", 100<<i);
    }

  return 0;
}

===================== OUTPUT =====================
[arnuld@dune C]$ gcc -ansi -pedantic -Wall -Wextra bitshift.c
[arnuld@dune C]$ ./a.out
100 is shifted left by 0 bits, place s = 100
100 is shifted left by 1 bits, place = 200
100 is shifted left by 2 bits, place s = 400
100 is shifted left by 3 bits, place s = 800
100 is shifted left by 4 bits, place s = 1600
100 is shifted left by 5 bits, place s = 3200
100 is shifted left by 6 bits, place s = 6400
100 is shifted left by 7 bits, place s = 12800
100 is shifted left by 8 bits, place s = 25600
100 is shifted left by 9 bits, place s = 51200
100 is shifted left by 10 bits, place s = 102400
100 is shifted left by 11 bits, place s = 204800
100 is shifted left by 12 bits, place s = 409600
100 is shifted left by 13 bits, place s = 819200
100 is shifted left by 14 bits, place s = 1638400
100 is shifted left by 15 bits, place s = 3276800
100 is shifted left by 16 bits, place s = 6553600
[arnuld@dune C]$

You will see everytime you shift a bit left, result is as if input (100) multiplied by 2. Hence if you shift 2 bits, the output is 100 * 2^2 = 400 which gives you precise idea of what the output will be without even writing a program :) . Now ask yourself (without modifying the program) what right shifting will result in ?


Copyright © 2011 Arnuld Uttre, Village – Patti, P.O – Manakpur, Tehsil – Nangal, Distt. – Ropar, Punjab (INDIA)

Verbatim copying and distribution of this entire article are permitted worldwide, without royalty, in any medium, provided this notice, and the copyright notice, are preserved.

Insertion Sort

September 7, 2011 at 7:03 pm | Posted in Hacking | 2 Comments
Tags: ,

I always had a hard time understanding algorithms, so I tried to understand them and failed to understand them. This cycle repeated for at least 2 years. I always wanted to have solid grounding in algorithms and data structures. After 3 years of working in Phonologies I finally got my head around many programming skills. With that experience in my bag and my frustration of failing everytime from last 2 years, I decided to give algorithms a super-hard try again. I decided I will go hard-headed into algorithms like a man who will eat, sleep, drink and cry algorithms and nothing else. Just dig seep and get my whole body dirty in the process of digging like a labour man. Took me a few months to find out a book that fits my mindset. Its written in a very simple and straighforward manner and even after that I felt a lot of difficulty in understanding first few chapters. And finally I am able to get my head around algorithms. Have read first three chapters and insetion sort is given as an example while selection sort is given an exercise which Iw as able to solve. Here is my take on Insertion Sort, on how I understood it:

This is Insertion Sort from Wikipedia which is similar to Cormen’s book:

for j = 1 to length(A)-1
     key = A[ j ]
      i = j - 1
     while i >= 0 and A [ i ] > key
         A[ i +1 ] = A[ i ]
         i = i -1
     A [i +1] = key

Felt too much confused with this, I tried to understand many times but never did. Did not find anyone explaining in the way I understand, hence I tried to use a C array of integers to understand and came up with this:

  1. Take A = {3,5,2} as array to apply Insertion Sort pseudo code
  2. first 3 lines: j = 1, key = 5, i = 0
  3. while loop will not execute as A[0] = 3 and 3 > 5 is not true A = {3,5,2}
  4. Last line: A = {3,5,2}
  5. Outer loop 2nd turn, first three lines: j = 2, key = 2 , i = 1
  6. After inner while loop, first round A = {3,2,5}, i = 0
  7. After inner while loop, second round A = {3,3,5}, i = -1
  8. Last line: {2,3,5}
  9. Outer Loop finishes array is sorted

I am not a child prodigy hence it took me 3 hours to come up with an array with right elements in place. I did 3 pages of paper work with wrong values and wrong indices before I got them right. (please add 5 more days where I tried really haaaaaaaard to understand from the book). Hard part was not understanding the example of playing cards. Cormen’s book uses playing cards example to show insertion sort (special thanks to the authors as that picture of a hand sorting cards really helped). Real life sorting of playing card is very easy, I have done it a thousand times without thinking. Translating that practical approach into pseudo code was the hard part.


Copyright © 2011 Arnuld Uttre, Village – Patti, P.O – Manakpur, Tehsil – Nangal, Distt. – Ropar, Punjab (INDIA)

Verbatim copying and distribution of this entire article are permitted worldwide, without royalty, in any medium, provided this notice, and the copyright notice, are preserved.

The Way of C++ Problem Solving

August 9, 2011 at 11:36 am | Posted in C++, Hacking | Leave a comment

Many programmers write their programs in C and then save the program with extension .cpp and call it C++ program. I am one of them, except that I don’t call those programs C++ programs. I don’t know have much knowledge of C++, mostly work in C. Over time I have read so many articles and blogposts that I am fully convinced beyond any doubt that C++ and C are two similar looking and very different languages. They were designed with different aims, they have entirely different philosophies about designing a program. Unlike what most programmers say that C anc C++ are brothers, I will say they are not even far distant cousins. C and C++ are 2 persons who belong to different nationality and have different skin color and they speak different languages. To know the true way of C++ I thought of writing a C++ program which reads a file and saves that into a std::string (This is first lesson, use std:: string instead of using namespace std which defeats the aim of namespaces. I posted the discussion my probblem on comp.lang.c++ which you can read on archives like rhinocerus and velocityreviews:

http://www.velocityreviews.com/forums/t752581-reading-a-file-into-std-string.html

http://www.rhinocerus.net/forum/language-c/682219-reading-file-into-std-string.html

I wrote the code as a C Programmer who did some google search and read a few pages of Stroustrup. Red Floyd posted a true C++ version. You see how much the difference in thinking, Red Floyd’s code is much superior than mine. You can easily conclude that C++ what you know or what your colleagues know is not really true C++. This program made me think harder about my learning and experience as a computer programmer. Solving problems in C++ is really vastly different from the way we do it in C. Don’t write C code and save the file with extension .cpp. If you want to write C code then please save the file as .c Lessons learned

#include <iostream>
#include <fstream>
#include <string>


int main()
{
  std::string my_contents, tmp_contents;
  std::ifstream my_file("reference.cpp");
  if(!my_file)
    {
      std::cerr << "Error Opening file" << std::endl;
      exit(EXIT_FAILURE);
    }

   while(my_file)
    {
     std::getline(my_file, tmp_contents);
     my_contents += tmp_contents;
     my_contents += "\n";
    }

  std::cout << "String contents are: "<< "\n"
	    << my_contents << std::endl;

  my_file.close();


  return 0;
}

 

#include <iostream>
#include <fstream>
#include <string>


int main()
{
  std::ifstream my_file("reference.cpp");
  if(!my_file)
    {
      std::cerr << "Error Opening file" << std::endl;
      exit(EXIT_FAILURE);
    }

  /* This was posted by "redfloyd" on comp.lang.c++ */
  std::string my_contents(std::istreambuf_iterator<char>(my_file.rdbuf()), (std::istreambuf_iterator<char>()));

  std::cout << "String contents are: "<< "\n"
	    << my_contents << std::endl;
  return 0;
}

 


Copyright © 2011 Arnuld Uttre, Village – Patti, P.O – Manakpur, Tehsil – Nangal, Distt. – Ropar, Punjab (INDIA)

Verbatim copying and distribution of this entire article are permitted worldwide, without royalty, in any medium, provided this notice, and the copyright notice, are preserved.

Queue using doubly linked-list

June 13, 2011 at 7:31 pm | Posted in Hacking | Leave a comment

Here is what I implemented as Queue using doubly linked-list. Short name will be FIFO (First-In-First-Out). remove_element() was corrected by Ike Naar on comp.lang.c and hence I included his version (better than mine) as remove_element_2() . Learning algorithms and data structures is always a tough thing to do but thats the only way to become a good programmer :)

NOTE: A Queue is used for adding elemnts at tail and removing them from head. Its not a good idea to remove elements from anywhere except head. Do not use use dequeu_anywhere() in production code as it is perfectly capable of causing efficiency issues in your software. Richard Heathfield once said, they are not for practical use but good for learning, as a mental exercise.

/* A Queue (FIFO)  implementation using doubly-linked list. All operations are based on page 70, section 2.4 "Data Structures and 
 *   Algorithms by Aho, Hopcraft and Ullman".
 *
 * VERSION 0.0
 *
 */

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

enum { VAL_SUCC = 0, VAL_ERR = 1};

struct dlqueue
{
  int num;
  struct dlqueue* next;
  struct dlqueue* prev;
};


struct dlqlist
{
  struct dlqueue* head;
  struct dlqueue* tail;
};



int enqueue(struct dlqlist*, int);
int dequeue(struct dlqlist*);
struct dlqueue* front(struct dlqlist*);
void makenull(struct dlqlist*);
int empty(struct dlqlist*);
void print_queue(struct dlqlist* );


int dequeue_anywhere(struct dlqlist*s , int numd);
void remove_element(struct dlqlist* s, struct dlqueue* d);


int main(void)
{
  struct dlqlist* s = malloc(1 * sizeof *s);
  if(NULL == s)
    {
      fprintf(stderr,"IN: %s @%d: Out of Memory\n", __FILE__, __LINE__);
      return EXIT_FAILURE;
    }
  else
    {
      s->head = s->tail = NULL;
    }

  enqueue(s, 10);
  enqueue(s, 11);
  enqueue(s, 12);
  enqueue(s, 13);
  print_queue(s);

  dequeue_anywhere(s,12);
  printf("\n\n----------------------------\n");
  print_queue(s);

  /*
  dequeue(s);
  printf("\n\n----------------------------\n");
  print_queue(s);

  dequeue(s);
  printf("\n\n----------------------------\n");
  print_queue(s);


  dequeue(s);
  printf("\n\n----------------------------\n");
  print_queue(s);
  */
  return EXIT_SUCCESS;
}



/* Adds an element to tail of Queue */
int enqueue(struct dlqlist* s, int i)
{
  int ret;
  if(NULL == s)
    {
      fprintf(stderr, "IN: %s @ %d: Invalid Args\n", __FILE__, __LINE__);
      ret = VAL_ERR;
    }
  else if(NULL == s->head && NULL == s->tail)
    {
      struct dlqueue* p = malloc(1 * sizeof *p);
      if(NULL == p)
	{
	  fprintf(stderr,"IN: %s @%d: Out of Memory\n", __FILE__, __LINE__);
	  ret = VAL_ERR;
	}
      else
	{
	  p->num = i;
	  p->prev = p->next = NULL;

	  s->head = s->tail = p;
	  ret = VAL_SUCC;
	}
    }
  else if(NULL == s->head || NULL == s->tail)
    {
      fprintf(stderr, "IN: %s @%d: Serious error.", __FILE__, __LINE__);
      fprintf(stderr,"List one of the list's head/tail is null while other is not\n");
      ret = VAL_ERR;
    }
  else
    {
      struct dlqueue* p = malloc(1 * sizeof *p);
      if(NULL == p)
	{
	  fprintf(stderr,"IN: %s @%d: Out of Memory\n", __FILE__, __LINE__);
	  ret = VAL_ERR;
	}
      else
	{
	  p->num = i;
	  p->prev = p->next = NULL;

	  s->tail->next = p;
	  p->prev = s->tail;
	  s->tail = p;
	  ret = VAL_SUCC;
	}
    }

  return ret;
}



int dequeue(struct dlqlist* s)
{
  int ret;
  if(NULL == s)
    {
      fprintf(stderr, "IN: %s @ %d: Invalid Args\n", __FILE__, __LINE__);
      ret = VAL_ERR;
    }
  else if(NULL == s->head && NULL == s->tail)
    {
      printf("Nothing to Dequeue()\n");
      ret = VAL_SUCC;
    }
  else if(NULL == s->head || NULL == s->tail)
    {
      fprintf(stderr, "IN: %s @%d: Serious error.", __FILE__, __LINE__);
      fprintf(stderr,"List one of the list's head/tail is null while other is not\n");
      ret = VAL_ERR;
    }
  else
    {
      struct dlqueue* p = s->head;
      if(NULL == s->head->next && NULL == s->tail->next) /* if last element */
	{
	  s->head = s->tail = NULL;
	}
      else
	{
	  s->head = s->head->next;
	}

      free(p);
      ret = VAL_SUCC;
    }

  return ret;
}


int dequeue_anywhere(struct dlqlist*s , int numd)
{
  int ret;
  if(NULL == s)
    {
      fprintf(stderr, "IN: %s @ %d: Invalid Args\n", __FILE__, __LINE__);
      ret = VAL_ERR;
    }
  else if(NULL == s->head && NULL == s->tail)
    {
      printf("Nothing to Dequeue()\n");
      ret = VAL_SUCC;
    }
  else if(NULL == s->head || NULL == s->tail)
    {
      fprintf(stderr, "IN: %s @%d: Serious error.", __FILE__, __LINE__);
      fprintf(stderr,"List one of the list's head/tail is null while other is not\n");
      ret = VAL_ERR;
    }
  else
    {
      struct dlqueue* p = s->head;
      for(; p; p = p->next)
	{
	  if(numd == p->num)
	    {
	      remove_element(s,p);
	    }
	}
      ret = VAL_SUCC;
    }

  return ret;
}


void remove_element(struct dlqlist* s, struct dlqueue* d)
{
  if(NULL == d->next && (NULL == s->head->next && NULL == s->tail->next)) /* only one element in queue */
    {
      s->head = s->tail = NULL;
    }
  else if((NULL == d->next) && d->prev) /* removing tail */
    {
      s->tail = d->prev;
      d->prev->next = NULL;
    }
  else if(d->next && (NULL == d->prev)) /* removing head */
    {
      s->head = d->next;
      s->head->prev = NULL;
    }
  else /* removing from center or somewhere */
    {
      d->prev->next = d->next;
      d->next->prev = d->prev;
    }

  free(d);
}

void remove_element_2(struct dlqlist* s, struct dlqueue* d)
{
  if(NULL == d->next)
    {
      s->tail = d->prev;
    }
  else
    {
      d->next->prev = d->prev;
    }

  if(NULL == d->prev)
    {
      s->head = d->next;
    }
  else
    {
      d->prev->next = d->next;
    }

  free(d);


}


void print_queue(struct dlqlist* s)
{
  if(NULL == s)
    {
      fprintf(stderr, "IN: %s @ %d: Invalid Args\n", __FILE__, __LINE__);
     }
  else if(NULL == s->head && NULL == s->tail)
    {
      printf("Nothing to print\n");
    }
  else if(NULL == s->head || NULL == s->tail)
    {
      fprintf(stderr, "IN: %s @%d: Serious error.", __FILE__, __LINE__);
      fprintf(stderr,"List one of the list's head/tail is null while other is not\n");
    }
  else
    {
      struct dlqueue* p = s->head;
      while(p)
	{
	  printf("num = %d\n", p->num);
	  p = p->next;
	}
    }
}

 


Copyright © 2011 Arnuld Uttre, Village – Patti, P.O – Manakpur, Tehsil – Nangal, Distt. – Ropar, Punjab (INDIA)

Verbatim copying and distribution of this entire article are permitted worldwide, without royalty, in any medium, provided this notice, and the copyright notice, are preserved.

Next Page »

Blog at WordPress.com. | Theme: Pool by Borja Fernandez.
Entries and comments feeds.

Follow

Get every new post delivered to your Inbox.