开发者

solving expression in a buffer

开发者 https://www.devze.com 2023-03-17 06:17 出处:网络
I\'m trying to create a function (in C) to solve an addition that is placed in a buffer variable. So far it works for equations that result in single-digit numbers, however if the result is more than

I'm trying to create a function (in C) to solve an addition that is placed in a buffer variable. So far it works for equations that result in single-digit numbers, however if the result is more than one digit, it causes problems.. For example, if I place 2+3+5+2 in the buffer, outputs 102, not 12. Can anyone point out where my errors are and how I can fix them?

Here's my code:

char buffer[50];

void *adder(void)
{
    int bufferlen;
    int value1, value2;
    int startOffset, remainderOffset;
    int i;
    char result[10];
    while (1) 
    {
        startOffset = remainderOffset = -1;
        value1 = value2 = -1;

        bufferlen = strlen(buffer);
        for (i = 0; i < bufferlen; i++) {
            if(value1 == -1)
            {
                if(isNumeric(buffer[i]))
                {
                    value1 = string2int(&buffer[i]);
                    startOffset = i;
                }
            }
            else
            {
                if(buffer[i] == 43)
                {
                    if(isNumeric(buffer[i+1]))
                    {
                        value2 = string2int(&buffer[i+1]);
                        remainderOffset = i+1;
                    }
                }
            }

            if(value1 != -1 && 开发者_如何转开发value2 != -1)
            {
                int k=0;
                int j=0;
                int2string((value1 + value2),result);
                /* print out the number we've found */
                fprintf(stdout, "Re:%s\n", result);
                int resultlen = strlen(result);
                for(k=startOffset; k < bufferlen; k++)
                {
                    if(j < resultlen)
                    {
                        buffer[k] = result[j];
                        j++;
                    }
                    else
                    {
                        /* shift the remainder of the string to the left */
                        printf("A1-Buffer:%s\nk=%i\n", buffer, k);
                        if(j > 0)
                        buffer[k] = buffer[k+2];
                        else
                        buffer[k] = buffer[k+2];
                        printf("A2-Buffer:%s\n", buffer);
                        i = i - remainderOffset;
                        startOffset = remainderOffset = -1;
                        value1 = value2 = -1;   
                    }
                }
            }
        }
    break;
    }

}

Edit: Ah, sorry, forgot about the extra functions. This function is for a school assignment and the isNumeric() and String2int() are exactly the same as isdigit() and atoi() and were given to us to use in the function.

Edit 2: After the numbers are added, the result has to be added back into the buffer in the expressions place like so: (2+3) -> (5) the reason is that eventually more functions will be written to handle multiplication, division, etc. This is where my main frustration lies - putting the result in place of the expression and shifting the buffer left the proper amount.


char buffer[50];

Why 50 bytes? Why not 100? You should accept a pointer as an argument instead of relying on a global. Also, buffer is not a descriptive name.

void *adder(void)

The function does not return a void *; it has no return value. You might consider

/* return value of expression */
int evaluate_add_expression( char const *in_string )

or

/* return status code */
int evaluate_add_expression( char const *in_string, int *out_value ) 

Next, you declare a number of variables without initializing them. Move the declarations into the loop and include initializations with the declarations, i.e. int value1 = -1, value2 = -1; Of course, those names are also not descriptive at all.

            if(buffer[i] == 43)

The value '+' is a better way to represent the plus character than the magic number 43.


If I were you, I'd avail myself of the sscanf function.

int evaluate_add_expression( char const *in_string, int *sum ) {
    int addend;
    size_t offset, offset_delta;

    if ( sscanf( in_string, " %d %zn", sum, &offset ) != 1 ) return 1;

    while ( sscanf( in_string + offset, "+ %d %zn", &addend, &offset_delta ) == 1 ) {
        * sum += addend;
        offset += offset_delta;
    }

    return in_string[ offset ] != '\0'; /* check that all input was consumed */
}

This works fine and is about 15% as long.


Note that

 if(j > 0)
     buffer[k] = buffer[k+2];
 else
     buffer[k] = buffer[k+2];

executes the same code regardless of the value of j. Also note that j can never be negative in your code anyway.

You are going out of bounds on your buffer array. Your loop counter i is being incremented by one at the end of each loop but you are also doing

i = i - remainderOffset;

multiple times in the k loop. Surely that must give you a negative i?

Also, when you shift the buffer back with

 buffer[k] = buffer[k+2];

the loop takes k up to bufferLen so k+2 is out of bounds here too.

I'm not sure why you shift everything back by a fixed amount of two positions anyway? Surely that assumes you just added a single digit number?

Think about these issues and you'll start to see where you are going wrong. I would agree with others that if you can leverage existing code then do so.

Edit: In response to your comment

I assume it's part of the assignment to store the result in the buffer? If not then just keep track of it in an integer and everything simplifies enormously. If the assignment says you have to update the buffer with intermediate results then note the following:

Suppose the two numbers at the start of the current buffer position are called A and B and that A is a two digit number and B a three digit number. There are two possible outcomes in terms of the amount of storage you need for the result, R. Either it is

AA+BBB+remainder -> RRR+remainder

or

AA+BBB+remainder -> RRRR+remainder

This means that you have a variable shift depending on how many digits the result has so, yes, you could base it on resultLen (but it isn't resultLen itself). Note that if you shift back you need to fill the gaps you leave at the end of the buffer with some suitable character or keep track of where the real end of the buffer now is.

Rather than shift the remainder backwards I would keep it where it is and write the result in the correct place before it (unless your assignment explicitly asks you to shift it backwards of course). So you take

AA+BBB

and convert it to either

...DDD

or

..DDDD

where the dots represent the characters we are no longer interested in. The characters there won't matter as long as you've updated the starting index on each iteration of the while loop (get rid of the i loop). If you know the number of digits that A, B and R have this shouldn't be too difficult for you to work out. Finally, break out of the while loop when the starting index hits bufferLen.

0

精彩评论

暂无评论...
验证码 换一张
取 消