Thread: issue trying to store math equation answers in readline()

  1. #1
    Registered User
    Join Date
    Mar 2023
    Posts
    33

    issue trying to store math equation answers in readline()

    So I decided to try and make a command line calculator, but discovered that I don't understand memory management and buffering well enough to parse out an expression like this:

    5 + (4 * 1)

    it would be really interesting to make a command line version of the graphical calculators that can do that, something different from bc and python.

    So, I've settled just for making a really simple calculator as a project to help me understand C better. This version works:

    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    #include<clearBuff.h>
    
    int main()
    {
      while(1)
      {
        char operator;
        long double number1, number2, answer;
    
        printf("Number: ");
        scanf("%Lf", &number1);
    
        clearBuff();
    
        printf("Operator (+, -, *, /, or ^): ");
        scanf("%c", &operator);
    
        clearBuff();
    
        printf("Number: ");
        scanf("%Lf", &number2);
    
        clearBuff();
    
        switch(operator)
        {
          case '+':
            answer = number1 + number2;
            break;
          case '-':
            answer = number1 - number2;
            break;
          case '*':
            answer = number1 * number2;
            break;
          case '/':
            answer = number1 / number2;
            break;
          case '^':
            answer = pow(number1, number2);
            break;
          default:
            puts("Invalid operator, only +, -, *, /, or ^ are accepted.");
            return 1;
        }
    
        printf("%Lf\n", answer);
      }
    }
    However, I don't think something like this is very useful at all without being able to press the up arrow and cycle through previous answers so that larger values don't have to be re-typed.

    It's possible to use the readline library as a history aspect for what you enter, but i was wondering if it was possible to pass my "answer" (which might have to be a pointer or a node in a linked list instead of a variable), but it doesn't do anything, gcc gives no errors but pressing the up button just generates ansi jibberish:

    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    #include<clearBuff.h>
    #include<readline/readline.h>
    #include<readline/history.h>
    
    int main()
    {
      while(1)
      {
        long double *input;
        char operator;
        long double number1, number2, answer;
    
        printf("Number: ");
        scanf("%Lf", &number1);
    
        clearBuff();
    
        printf("Operator (+, -, *, /, or ^): ");
        scanf("%c", &operator);
    
        clearBuff();
    
        printf("Number: ");
        scanf("%Lf", &number2);
    
        clearBuff();
    
        switch(operator)
        {
          case '+':
            answer = number1 + number2;
            break;
          case '-':
            answer = number1 - number2;
            break;
          case '*':
            answer = number1 * number2;
            break;
          case '/':
            answer = number1 / number2;
            break;
          case '^':
            answer = pow(number1, number2);
            break;
          default:
            puts("Invalid operator, only +, -, *, /, or ^ are accepted.");
            return 1;
        }
    
        printf("%Lf\n", answer);
    
        using_history();
        input = readline(&answer);
    
        if (*input)
          add_history(input);
      }
    }
    i was also wondering if there were any good alternatives to the readline library, as it probably wasn't designed to do this.
    Last edited by C_me_run; 11-18-2023 at 07:40 PM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    My first suggestion would be to separate input from conversion.

    You read a whole line, and then you analyse it.
    This is mostly because if you want to try to parse anything like "5 + (4 * 1)" using just scanf, you're in for a bad time.

    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    
    int parse(char *line) {
        char operator;
        long double number1, number2, answer;
        if ( sscanf(line, "%Lf %c %Lf", &number1, &operator, &number2) == 3 ) {
            switch(operator)
            {
              case '+':
                answer = number1 + number2;
                break;
              case '-':
                answer = number1 - number2;
                break;
              case '*':
                answer = number1 * number2;
                break;
              case '/':
                answer = number1 / number2;
                break;
              case '^':
                answer = pow(number1, number2);
                break;
              default:
                puts("Invalid operator, only +, -, *, /, or ^ are accepted.");
                return 1;
            }
            printf("%Lf\n", answer);
        } else {
            printf("I didn't understand\n");
            return 1;
        }
        return 0;
    }
    
    int main()
    {
        char buff[BUFSIZ];
        while(fgets( buff, BUFSIZ, stdin ))
        {
            if ( parse(buff) ) {
                break;
            }
        }
    }
    Replacing fgets with readline should be simple from this point.

    If you want to push your answer into the history, you need to convert it to a string.
    Code:
    char str_answer[100];
    sprintf(str_answer,"%99Lf",answer);
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Mar 2023
    Posts
    33
    Quote Originally Posted by Salem View Post
    My first suggestion would be to separate input from conversion.

    You read a whole line, and then you analyse it.
    This is mostly because if you want to try to parse anything like "5 + (4 * 1)" using just scanf, you're in for a bad time.

    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<math.h>
    
    int parse(char *line) {
        char operator;
        long double number1, number2, answer;
        if ( sscanf(line, "%Lf %c %Lf", &number1, &operator, &number2) == 3 ) {
            switch(operator)
            {
              case '+':
                answer = number1 + number2;
                break;
              case '-':
                answer = number1 - number2;
                break;
              case '*':
                answer = number1 * number2;
                break;
              case '/':
                answer = number1 / number2;
                break;
              case '^':
                answer = pow(number1, number2);
                break;
              default:
                puts("Invalid operator, only +, -, *, /, or ^ are accepted.");
                return 1;
            }
            printf("%Lf\n", answer);
        } else {
            printf("I didn't understand\n");
            return 1;
        }
        return 0;
    }
    
    int main()
    {
        char buff[BUFSIZ];
        while(fgets( buff, BUFSIZ, stdin ))
        {
            if ( parse(buff) ) {
                break;
            }
        }
    }
    Replacing fgets with readline should be simple from this point.

    If you want to push your answer into the history, you need to convert it to a string.
    Code:
    char str_answer[100];
    sprintf(str_answer,"%99Lf",answer);
    That is an illustration of how the larger idea could possibly work, and thank you, but I am mostly concerned with how to pass the converted string to readline properly, and where exactly the best place is to call "using_history()". I'm still completely in the dark in terms of understanding how that mechanism could work beyond standard input. Any other keymapping or history storage alternative would work to, but i don't know of any. Readline pretty much enables you to recall your keyboard input in the exact same way that bash terminals do, which is neat.

    A command line calculator that parses entire mathematical expressions using typed PEMDAS is a large project and doesn't appear to have been done yet. Chances are slim that I will get there first but it helps to just to break big problems down first.

  4. #4
    Registered User
    Join Date
    Dec 2017
    Posts
    1,633
    A command line calculator that parses entire mathematical expressions using typed PEMDAS is a large project and doesn't appear to have been done yet.
    bc is an arbitrary-precision command-line calculator:
    $ bc<<<'((3 + 4) * 12 + 5) * (8 - 2)'
    534
    $ bc<<<'scale=9; 1234/765' # scale sets the number of positions after the decimal point
    1.613071895
    $ bc<<<'p = 1; for (i = 2; i <= 100; ++i) p *= i; p' # 100 factorial
    93326215443944152681699238856266700490715968264381 621468592963895217\
    59999322991560894146397615651828625369792082722375 825118521091686400\
    0000000000000000000000

    As for the GNU history library:
    GNU History Library
    A little inaccuracy saves tons of explanation. - H.H. Munro

  5. #5
    Registered User
    Join Date
    Mar 2023
    Posts
    33
    Quote Originally Posted by john.c View Post
    bc is an arbitrary-precision command-line calculator:
    $ bc<<<'((3 + 4) * 12 + 5) * (8 - 2)'
    534
    $ bc<<<'scale=9; 1234/765' # scale sets the number of positions after the decimal point
    1.613071895
    $ bc<<<'p = 1; for (i = 2; i <= 100; ++i) p *= i; p' # 100 factorial
    93326215443944152681699238856266700490715968264381 621468592963895217\
    59999322991560894146397615651828625369792082722375 825118521091686400\
    0000000000000000000000

    As for the GNU history library:
    GNU History Library
    Yes I'm very familiar with bc and a bunch of other bash utilities, yet it's a programming language and not really a calculator.

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    > but I am mostly concerned with how to pass the converted string to readline properly
    So create a test program containing only readline and add_history
    You're allowed to edit more than one program at once. Your expression evaluator is just in the way of understanding readline.

    Start with something simple like
    Code:
    int main ( ) {
        add_history("foo");
        add_history("bar");
        char *input = readline("Say something ");
    }
    Do you see any history?

    Add further examples of the things you want to be able to do.

    GNU Readline Library - Programming with GNU Readline

    When you're confident you understand how it works, then you can apply it to your main program.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Mar 2023
    Posts
    33
    Quote Originally Posted by Salem View Post
    > but I am mostly concerned with how to pass the converted string to readline properly
    So create a test program containing only readline and add_history
    You're allowed to edit more than one program at once. Your expression evaluator is just in the way of understanding readline.

    Start with something simple like
    Code:
    int main ( ) {
        add_history("foo");
        add_history("bar");
        char *input = readline("Say something ");
    }
    Do you see any history?

    Add further examples of the things you want to be able to do.

    GNU Readline Library - Programming with GNU Readline

    When you're confident you understand how it works, then you can apply it to your main program.
    Yes, you are right, once i understand the entire readline function (and everything else it needs to work), then there would a solution.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Need help with math equation.
    By syahidfz in forum C Programming
    Replies: 6
    Last Post: 02-04-2015, 05:25 AM
  2. Math equation help!!
    By alex33zebras in forum C Programming
    Replies: 2
    Last Post: 09-27-2011, 03:31 PM
  3. Cubic equation program not giving me right answers
    By face_master in forum C++ Programming
    Replies: 8
    Last Post: 08-24-2006, 05:42 PM
  4. A math equation
    By dizolve in forum A Brief History of Cprogramming.com
    Replies: 8
    Last Post: 12-17-2002, 12:56 PM
  5. why different answers for this equation
    By james_nkh in forum C Programming
    Replies: 2
    Last Post: 05-21-2002, 12:29 PM

Tags for this Thread