Software Engineering

How to Filter a Number in C


The challenge

The number has been mixed up with the text. Your goal is to retrieve the number from the text, can you return the number back to its original state?

Task

Your task is to return a number from a string.

Details

You will be given a string of numbers and letters mixed up, you have to return all the numbers in that string in the order they occur.

The solution in C

Option 1:

long long filter_string(const char *s) {
  long long n=0;
  char c;
  while( (c=*s++) ){
    if ( c>='0' && c<='9' ) n = 10*n + c-'0';
  }
  return n;
}

Option 2:

#include <ctype.h>

long long filter_string(const char *value) {
  long long ret = 0;
  
  for (const char *p = value; *p; p++) {
    if (isdigit(*p)) ret = ret * 10 + *p - '0';
  }      

  return ret;
}

Option 3:

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

long long filter_string(const char *value) {
   long long l = 0;
   char* ptr;
   char* s = calloc(strlen(value) + 1, 1);
   char* r = s;
   while(*value) {
     if(isdigit(*value)) *s++ = *value;      
     value++;    
   }
  l = strtol(r, &ptr, 10);   
  return l;
}

Test cases to validate our solution

#include <criterion/criterion.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void do_test(const char *value, long expected);

Test(solution_test, fixed_tests)
{
    do_test("123", 123);
    do_test("a1b2c3", 123);
    do_test("aa1bb2cc3dd", 123);
}
Test(solution_test, random_tests)
{
    srand(time(NULL));
  
    #define randomLetter() (rand() % 26 + 'a')
    #define randomValue()  (llabs(((long long)rand() << 32) + rand()))
  
    for (int trial = 1; trial <= 50; trial++)
    {
        long long expected = randomValue();
        char num[20], value[500] = {0};
        sprintf(num, "%lld", expected);
        for (int i = 0, j = 0; num[i]; i++)
        {
            for (int k = rand() % 5 + 1; k; k--)
                value[j++] = randomLetter();
            value[j++] = num[i];
            for (int k = rand() % 5 + 1; k; k--)
                value[j++] = randomLetter();
        }
        do_test(value, expected);
    }
}