// timings.c ... time some string functionality in C

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <time.h> 
#include <string.h> 

#define MAX_LEN 200

char coutc[MAX_LEN + 1];

char outcoutc[MAX_LEN + 1];

void ctoupper(char *inlower) {
  coutc[0] = '\0';
  for (int i=0; i<strlen(inlower); i++) {
    *(coutc + i + 1) = '\0';
    if (*(inlower + i) >= 'a' && *(inlower + i) <= 'z') {
      *(coutc + i) = *(inlower + i) + ('A' - 'a');
    } else {
      *(coutc + i) = *(inlower + i);
    }
  }
}

void ptoupper(char *inlower, char **outc) {
 *outc = malloc(strlen(inlower) + 1);	
 if (outc != NULL) {
  *(*outc + 0) = '\0';
  for (int i=0; i<strlen(inlower); i++) {
    *(*outc + i + 1) = '\0';
    if (*(inlower + i) >= 'a' && *(inlower + i) <= 'z') {
      *(*outc + i) = *(inlower + i) + ('A' - 'a');
    } else {
      *(*outc + i) = *(inlower + i);
    }
  }
 }
}


int main() {
  char name[MAX_LEN + 1], *ucname;
  clock_t ticks_before, ticks_after; 
  double diffsc;
  int i, j = -1, igoes = 60000;
  char key[2] = "a";

  printf("\n\nC string functions timings ...\n\nPlease enter a string to work with: ");
  scanf("%[^\n]s", &name);

  // ptoupper()
  ticks_before = clock();
  for (i=0; i<igoes; i++) {
    ptoupper(name, &ucname);
  }
  ticks_after = clock();
  diffsc = (double)(ticks_after - ticks_before) / CLOCKS_PER_SEC;
  printf("\nUppercase via ptoupper() is %s %lf (average %E seconds per call)\n", ucname, diffsc, (diffsc / (double)igoes)); 

  // ctoupper()
  ticks_before = clock();
  for (i=0; i<igoes; i++) {
    ctoupper(name);
  }
  ticks_after = clock();
  diffsc = (double)(ticks_after - ticks_before) / CLOCKS_PER_SEC;
  printf("\nUppercase via ctoupper() is %s %lf (average %E seconds per call)\n", coutc, diffsc, (diffsc / (double)igoes)); 

  printf("\n\n---------------------------------------------------------------\n\n");

  // strcpy()
  ticks_before = clock();
  for (i=0; i<igoes; i++) {
    strcpy(outcoutc, name);
  }
  ticks_after = clock();
  diffsc = (double)(ticks_after - ticks_before) / CLOCKS_PER_SEC;
  printf("\nString copy via strcpy() is %s %lf (average %E seconds per call)\n", outcoutc, diffsc, (diffsc / (double)igoes)); 

  // strncpy()
  ticks_before = clock();
  for (i=0; i<igoes; i++) {
    strncpy(outcoutc, name, (strlen(name) + 1));
  }
  ticks_after = clock();
  diffsc = (double)(ticks_after - ticks_before) / CLOCKS_PER_SEC;
  printf("\nString copy via strncpy() is %s %lf (average %E seconds per call)\n", outcoutc, diffsc, (diffsc / (double)igoes)); 

  // sprintf()
  ticks_before = clock();
  for (i=0; i<igoes; i++) {
    sprintf(outcoutc, "%s", name);
  }
  ticks_after = clock();
  diffsc = (double)(ticks_after - ticks_before) / CLOCKS_PER_SEC;
  printf("\nString copy via sprintf() is %s %lf (average %E seconds per call)\n", outcoutc, diffsc, (diffsc / (double)igoes)); 

  // memcpy()
  ticks_before = clock();
  for (i=0; i<igoes; i++) {
    memcpy(outcoutc, name, (strlen(name) + 1));
  }
  ticks_after = clock();
  diffsc = (double)(ticks_after - ticks_before) / CLOCKS_PER_SEC;
  printf("\nString copy via memcpy() is %s %lf (average %E seconds per call)\n", outcoutc, diffsc, (diffsc / (double)igoes)); 

  // memmove()
  ticks_before = clock();
  for (i=0; i<igoes; i++) {
    memmove(outcoutc, name, (strlen(name) + 1));
  }
  ticks_after = clock();
  diffsc = (double)(ticks_after - ticks_before) / CLOCKS_PER_SEC;
  printf("\nString copy via memmove() is %s %lf (average %E seconds per call)\n", outcoutc, diffsc, (diffsc / (double)igoes)); 

  printf("\n\n---------------------------------------------------------------\n\n");

  // strchr()
  ticks_before = clock();
  for (i=0; i<igoes; i++) {
    ucname = strchr(name, 'a');
  }
  ticks_after = clock();
  diffsc = (double)(ticks_after - ticks_before) / CLOCKS_PER_SEC;
  printf("\nString find first occurrence via strchr() is %s %lf (average %E seconds per call)\n", ((!ucname) ? "not found" : "found"), diffsc, (diffsc / (double)igoes)); 

  // strpbrk()
  ticks_before = clock();
  for (i=0; i<igoes; i++) {
    ucname = strpbrk(name, key);
  }
  ticks_after = clock();
  diffsc = (double)(ticks_after - ticks_before) / CLOCKS_PER_SEC;
  printf("\nString find first occurrence via strpbrk() is %s %lf (average %E seconds per call)\n", ((!ucname) ? "not found" : "found"), diffsc, (diffsc / (double)igoes)); 

  // strstr()
  ticks_before = clock();
  for (i=0; i<igoes; i++) {
    ucname = strstr(name, "a");
  }
  ticks_after = clock();
  diffsc = (double)(ticks_after - ticks_before) / CLOCKS_PER_SEC;
  printf("\nString find first occurrence via strstr() is %s %lf (average %E seconds per call)\n",  ((!ucname) ? "not found" : "found"), diffsc, (diffsc / (double)igoes)); 

  printf("\n\n---------------------------------------------------------------\n\n");


}
