1

I have an input string in the format: name1@float1 name2@float2 ... nameN@floatN. It's always delimited by '@' and ' '.

Example:

ash@19.96 ram@12.3 driver@10.2

It should display the name of the person having the smallest values.
How can it be solved?

Output:

driver
Akira
  • 4,385
  • 3
  • 24
  • 46
ashwanth s
  • 105
  • 1
  • 1
  • 10
  • 2
    You need to be more specific. Do you know the number of strings? Will this be input or in a string buffer? Will the delimeter be always @? Will the string before contain only characters? – Ajay Brahmakshatriya Aug 10 '17 at 06:36
  • Actually the question does not specify the number of inputs we need to calculate it and the following will be the input to the question, @ is the delimiter for each case specified above. – ashwanth s Aug 10 '17 at 06:41
  • separate the main string to substrings with delimiter `' '` and later divide this substrings further with delimiter `@` which gives names and numbers(take double array here). Find the highest number index and display the corresponding name from name array) . Use your own piece of code to separate using delimiter. Also, you can even solve it without taking two arrays (one for name and other for doubles). It depends on how you write your code (time vs space) – infinite loop Aug 10 '17 at 07:12

3 Answers3

1

The following code implements a getSubstrSmallestNumber() function which uses the strtok() function which changes the input buffer. If you don't want that you can first copy the string. The good point about changing the input buffer is that no memory allocation is needed for the found sub string. The strtok() writes a null terminator '\0' where the specified delimiter is found if it's called.

The getSubstrSmallestNumber() function can called with specific delimiters, here '@' and ' '. Each number will be converted to double with strtod() and checked if it smaller than before. If it's smaller the corresponding token will be saved. After the while loop finished (if strtok() found no more tokens) the saved token (smallest double) will be returned.

Note that the code does no error checking this should be considered to be implemented as well.

Full code:

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

char* getSubstrSmallestNumber(char* input, char* numberDelimiter, char* strDelimiter)
{
   char* tokenStr;
   double minNumber = DBL_MAX;
   char* minToken = NULL;

   for (tokenStr = strtok(input, numberDelimiter);
        tokenStr != NULL;
        tokenStr = strtok(NULL, numberDelimiter))
   {
      char* numberStr = strtok(NULL, strDelimiter);
      double number = strtod(numberStr, NULL);

      if (number < minNumber)
      {
         minNumber = number;
         minToken = tokenStr;
      }
   }

   return minToken;
}

int main()
{
   char input[] = "ash@19.96 ram@12.3 driver@10.2";

   printf("<%s>\n", getSubstrSmallestNumber(input, "@", " "));

   return 0;
}

Output:

<driver>

I put '<' and '>' around the string in the printf() call to show that the returned string by getSubstrSmallestNumber() is really just driver and nothing more like a space for example.

Andre Kampling
  • 5,476
  • 2
  • 20
  • 47
1

You can combone the strtok and sscanf functions to solve your problem.

For first, you have to tokenize your string using ' ' (white-space) as delimiter, then extract the number from each token to find the token with smallest number. Every time you find a token with smaller number than the current, extract the name from that token and store the new possibly smallest number. Here is an example:

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

int main() {
    char str[] = "ash@19.96 ram@12.3 driver@10.2";
    char result[256] = { 0 };

    char *token, *sep_ptr;
    float value, min = FLT_MAX; /* set 'min' to the maximum of float */

    /* tokenize 'str' and walk through the tokens */
    for(token = strtok(str, " "); token != NULL; token = strtok(NULL, " ")) {
        value = FLT_MAX;

        /* process the current token if it contains a '@' character */
        if(sep_ptr = strchr(token, '@')) {
            sscanf(sep_ptr, "@%f", &value); /* extract value */

            /* check if the new number is smaller than current 'min' */
            if(value < min) {
                strcpy(result, (*sep_ptr = '\0', token)); /* extract name */
                min = value;
            }
        }
   }

   puts(result);
   return 0;
}

The (*sep_ptr = '\0', token) part of the code above simply replaces the '@' character to null character before performing the copy from token to result. (The mentioned expression uses the comma operator.)

Akira
  • 4,385
  • 3
  • 24
  • 46
0

You can use strrok available in C string library and for parsing float you can use atof function but the atof function seems to be unreliable in some cases, though. In that case you can write your own implementation according to your needs.

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

#define SIZE 1000

int main() {
    char input[SIZE], smallest[SIZE], name[SIZE];
    const char s[2] = "@";
    char *token;
    float val = FLT_MAX;

    while(scanf("%s", input) != EOF) {

        token = strtok(input, s);
        strcpy(name, token);

        token = strtok(NULL, s);
        float curVal = atof(token);

        if(curVal < val) {
            val = curVal;
            strcpy(smallest, name);
        }
    }

    printf("Smallest value : %s\n", smallest);
    return 0;
}

When i tested it seemed to show correct output:

~/Documents/src : $ ./a.out 
ram@12.3
driver@10.2
ash@19.96
Smallest value : driver

Hope that helps!

Rohan Kumar
  • 5,427
  • 8
  • 25
  • 40