Home > Blockchain >  How can I get certain things out of a string
How can I get certain things out of a string

Time:09-16

I wanted to write an algorithm that takes an input which contains the name of a certain item and its price, and a dash between them. The output is supposed to state the name of the item and its price. I would also like to know how can I separate the input into two strings, one being the name, and the other being the price, since I can't really come up with anything.

int getprice(char item[]);
void printitem(char item[]);
    
int main()
{
    char item[40];
    int i, j, len;
    int price = 0;

    fgets(item, 40, stdin);

    price = getprice(item);
    printitem(item);

    return 0;
}
    
int getprice(char item[])
{
    int i = 0;
    int price = 0;
    int len = strlen(item);
    int temp;

    for (i = 0; i < len; i  )
    {
        if ((item[i] >= '0') && (item[i] <= '9'))
        {
            break;
        }
        i  ;
    }

    for (i; i < len; i  )
    {
        temp = item[i] - '0';
        price = price * 10;
        price = price   temp;
    }

    printf("price is: %u\n", price);
    return price;
}

void printitem(char item[])
{
    int i = 0;
    int len = strlen(item);

    for (i = 0; i < len; i  )
    {
        if (item[i] != '-') 
        {
            printf("%c", item[i]);
        }
        else // if '-' is encountered the next char is checked if it stops or if it needs to keep going
        {
            i  ; //the for loop increments by itself
            if (item[i] == ' ') //if there is a space after '-' that means we printed the whole thing
            {
                break;
            }
            i--; //if it needs to keep going
            printf("-");
        }
    }
}
Input:Chocolate-Chip Cookie - 30
Output:Item: Chocolate-Chip Cookie
       Price: 30
actual Output: Item: Chocolate-Chip Cookie
               Price: 262

Why is the output price wrong, and is there a better way of doing it?

CodePudding user response:

Well, right away, I see that you're incrementing i twice each time through this loop, probably not what you want:

for(i=0;i<len;i  )  // <- First increment
{
    if((item[i] >= '0') && (item[i] <= '9'))
    {
        break;
    }
    i  ;            // <- Second increment
}

The i here is unnecessary:

for(i;i<len;i  )
 // ^ does nothing

You can print some values in your price-calculation loop to see what's going on:

for(i;i<len;i  )
{
printf("price = %d, item[i] = %d, new price = %d\n",
    price, item[i], price * 10   (item[i] - '0'));
temp = item[i] - '0';
price = price * 10;
price = price   temp;
}
$ ./test
Chocolate-Chip Cookie - 30
price = 0, item[i] = 51, new price = 3
price = 3, item[i] = 48, new price = 30
price = 30, item[i] = 10, new price = 262   <-- Hmm
price is: 262

The issue is that fgets is adding the \n (the return you press after the input) to the string and you're interpreting it as part of the price.

CodePudding user response:

Seems to me that this can be simplified somewhat. Omitting error checking for clarity, you could do something like this:

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

int main() { 
    char input[] = "Chocolate-Chip Cookie - 30";

    char *sep = strstr(input, " - ");

    int len = sep-input;
    printf("Item: '%.*s'\nPrice: '%s'\n", len, input, sep   3);
}

Result:

Item: 'Chocolate-Chip Cookie'
Price: '30'

CodePudding user response:

Why is the output price wrong?

Code attempts to change "30\n" rather than "30" into the value 30.

is there a better way of doing it?

int getprice(const char *item){  // add const
  // Look for a non-digit
  while ((*item < '0' || *item > '9') && *item) {
    item  ;
  }
  if (*item == 0) {
    // No digit found, maybe add error message
    return 0;
  }

  int price=0;
  while (*item >= '0' && *item <= '9') {  // Loop while a digit
    price = price*10   (*item - '0');
    item  ;
  }

  printf("price is: %d\n", price);  // %d not %u
  return price;
}

CodePudding user response:

Another way (that you can use to parse anything from any string), is to use a pair of pointers to walk-the-string setting a begin and end pointer at the start and end of each segment of the string you want and then copy those portions of the string to separate storage.

A short example (with comments) would be:

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

#define NUMC   32       /* if you need a constant, #define one (or more) */
#define MAXC 1024
#define DELIM " - "

int main (void) {
    
    /* read buffer, buffers for item, price and begin, end pointers */
    char buf[MAXC], item[MAXC], price[NUMC], *p_begin = buf, *p_end;
    size_t len;
    
    fputs ("input: ", stdout);              /* prompt */
    if (!fgets (buf, MAXC, stdin)) {        /* read/validate input */
        return 0;
    }
    
    if (!(p_end = strstr (buf, DELIM))) {   /* locate start of delim */
        fputs ("error: invalid input format.\n", stderr);
        return 1;
    }
    
    memcpy (item, p_begin, p_end - p_begin);    /* copy item */
    item[p_end - p_begin] = 0;                  /* nul-terminate item */
    
    p_begin = p_end   strlen(DELIM);    /* set begin to start of price */
    len = strcspn (p_begin, "\n");      /* get length of price */
    memcpy (price, p_begin, len);       /* copy to price */
    price[len] = 0;                     /* nul-terminate price */
    
    /* output results */
    printf ("\nitem  : '%s'\nprice : '%s'\n", item, price);
}

Example Use/Output

./bin/split_price-item
input: Chocolate-Chip Cookie - 30

item  : 'Chocolate-Chip Cookie'
price : '30'

Now, your delimiter must remain " - ", but you can easily pass that as a parameter instead of using a constant (up to you). Let me know if you have any questions.

  • Related