#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <ctype.h>
#include <string.h>
#include <errno.h>


/* Position exactly to integer beginning */
/* e.g. if you have: "str-str-3str "     */
/* the returning pointer will point to:  */
/* "-3str".                              */
const char* getNumberPos(const char* str)
{
   const char* curChar = str;
   /* Iterate through part of integer is there. */
   while (   '\0' != curChar
          && !(isdigit(*curChar) || '+' == *curChar || '-' == *curChar))
   {
      ++curChar;
   }
   /* Check if the sign is part of an integer, */
   /* if not use this function recursive!      */
   if ('+' == *curChar || '-' == *curChar)
   {
      const char* nextChar = curChar + 1;
      if (   '\0' != *nextChar
          && !isdigit(*nextChar))
      {
         ++curChar;
         curChar = getNumberPos(curChar);
      }
   }
   return curChar;
}

/* Extended strtol function */
long my_strtol(const char* str, char** endptr, int base)
{
   const char* curChar = getNumberPos(str);
   return strtol(curChar, endptr, base);
}


int main()
{
   /* Loop index */
   int idx;

   /* Declare and initialize char arrays. */
   char array[]      = { "3" };
   char arrayI[]     = { "    3   " };
   char arrayII[]    = { "   -3   " };
   char arrayIII[]   = { "str 3   " };
   char arrayIV[]    = { "str-3   " };
   char arrayV[]     = { "    3str" };
   char arrayVI[]    = { "   -3str" };
   char arrayVII[]   = { "str-3str" };
   char arrayVIII[]  = { "s-r-3str" };

   /* Save each array in one array for iteration purposes. */
   const char* const arrays[] = { array,
                                  arrayI,
                                  arrayII,
                                  arrayIII,
                                  arrayIV,
                                  arrayV,
                                  arrayVI,
                                  arrayVII,
                                  arrayVIII };
   /* Get size of that array. */
   const int arraysSize = sizeof(arrays) / sizeof(char*);

   /* atoi(): Does not detect errors! */
   for (idx = 0; idx < arraysSize; ++idx)
   {
      int integer = atoi(arrays[idx]);

      printf("%d: atoi with \"%s\" %*s to integer: %+d\n",
             idx,
             arrays[idx],
             8 - strlen (arrays[idx]),
             "",
             integer);
   }
   printf("\n");

   /* sscanf(): Error detection by using the matched item count. */
   for (idx = 0; idx < arraysSize; ++idx)
   {
      int integer = 0;
      int itemCount = sscanf(arrays[idx], "%d", &integer);

      printf("%d: sscanf with \"%s\" %*s to integer: %+d | itemCount = %d",
             idx,
             arrays[idx],
             8 - strlen (arrays[idx]),
             "",
             integer,
             itemCount);

      if (0 == itemCount)
      {
         printf(" --> Error!");
      }
      printf("\n");
   }
   printf("\n");

   /* strtol(): Error detection by using errno and returned end pointer. */
   for (idx = 0; idx < arraysSize; ++idx)
   {
      char*     endPtr  = NULL;
      ptrdiff_t ptrDiff = 0;
      errno             = 0;
      /* You have to check if the long can be stored in the int, not done here! */
      int integer = (int) strtol(arrays[idx], &endPtr, 10);
      ptrDiff = endPtr - arrays[idx];

      printf("%d: strtol with \"%s\" %*s to integer: %+d | errno =  %d, StartPtr = %p, EndPtr = %p, PtrDiff = %ld",
             idx,
             arrays[idx],
             8 - strlen (arrays[idx]),
             "",
             integer,
             errno,
             (void*) arrays[idx],
             (void*) endPtr,
             ptrDiff);

      if (0 != errno || 0 == ptrDiff)
      {
         printf(" --> Error!");
      }
      printf("\n");
   }
   printf("\n");

   /* my_strtol: Same as strtol here. */
   for (idx = 0; idx < arraysSize; ++idx)
   {
      char*     endPtr  = NULL;
      ptrdiff_t ptrDiff = 0;
      errno             = 0;
      /* You have to check if the long can be stored in the int, not done here! */
      int integer = (int) my_strtol(arrays[idx], &endPtr, 10);
      ptrDiff = endPtr - arrays[idx];

      printf("%d: my_strtol with \"%s\" %*s to integer: %+d | errno =  %d, StartPtr = %p, EndPtr = %p, PtrDiff = %ld",
             idx,
             arrays[idx],
             8 - strlen (arrays[idx]),
             "",
             integer,
             errno,
             (void*) arrays[idx],
             (void*) endPtr,
             ptrDiff);

      if (0 != errno || 0 == ptrDiff)
      {
         printf(" --> Error!");
      }
      printf("\n");
   }

   return 0;
}