Skip to main content
Corrected the name of the program
Source Link
200_success
  • 144.2k
  • 22
  • 188
  • 473
  1. Compilation error: This was just carelessness.

    getop.c:31:6: error: conflicting types for 'getOp'
    char getOp(const char *op) {
         ^
    ./calc.h:3:5: note: previous declaration is here
    int getOp(const char *s);
        ^
    1 error generated.
    
  2. Error handling: You treat errors like warnings. If there's an error, I would expect the program to print nothing to stdout, and for the program to exit with a non-zero status code. Error and warning messages should be printed to stderr instead of stdout.

  3. Picky validation: In my opinion, this should successfully evaluate to 1:

    $ ./calcexpr 1
    invalid call
    

    By the way, if you find an insufficient number of command-line arguments, just return early.

    int main(int argc, char *argv[]) {
        if (argc <= 1) {
            fprintf(stderr, "invalid call\n");
            return 1;
        }
    
        while (--argc) {
            …
        }
        printf("%g\n", pop());
        return 0;
    }
    
  4. Mishandling of negative numbers: I would expect the following calculation to yield -1:

    $ ./calcexpr 3 -4 +
    warning: the stack is freewarning: the stack is free-3
    
  5. Unconventional division operator: It is customary to use / for division. I don't know why you use \ instead.

  6. Division-by-zero paranoia: In contrast to integer arithmetic, where division by zero is undefined behaviour, division by zero in IEEE 754 floating point arithmetic should just return infinity. Perhaps you could remove the check for division by zero.

  1. Compilation error: This was just carelessness.

    getop.c:31:6: error: conflicting types for 'getOp'
    char getOp(const char *op) {
         ^
    ./calc.h:3:5: note: previous declaration is here
    int getOp(const char *s);
        ^
    1 error generated.
    
  2. Error handling: You treat errors like warnings. If there's an error, I would expect the program to print nothing to stdout, and for the program to exit with a non-zero status code. Error and warning messages should be printed to stderr instead of stdout.

  3. Picky validation: In my opinion, this should successfully evaluate to 1:

    $ ./calc 1
    invalid call
    

    By the way, if you find an insufficient number of command-line arguments, just return early.

    int main(int argc, char *argv[]) {
        if (argc <= 1) {
            fprintf(stderr, "invalid call\n");
            return 1;
        }
    
        while (--argc) {
            …
        }
        printf("%g\n", pop());
        return 0;
    }
    
  4. Mishandling of negative numbers: I would expect the following calculation to yield -1:

    $ ./calc 3 -4 +
    warning: the stack is freewarning: the stack is free-3
    
  5. Unconventional division operator: It is customary to use / for division. I don't know why you use \ instead.

  6. Division-by-zero paranoia: In contrast to integer arithmetic, where division by zero is undefined behaviour, division by zero in IEEE 754 floating point arithmetic should just return infinity. Perhaps you could remove the check for division by zero.

  1. Compilation error: This was just carelessness.

    getop.c:31:6: error: conflicting types for 'getOp'
    char getOp(const char *op) {
         ^
    ./calc.h:3:5: note: previous declaration is here
    int getOp(const char *s);
        ^
    1 error generated.
    
  2. Error handling: You treat errors like warnings. If there's an error, I would expect the program to print nothing to stdout, and for the program to exit with a non-zero status code. Error and warning messages should be printed to stderr instead of stdout.

  3. Picky validation: In my opinion, this should successfully evaluate to 1:

    $ ./expr 1
    invalid call
    

    By the way, if you find an insufficient number of command-line arguments, just return early.

    int main(int argc, char *argv[]) {
        if (argc <= 1) {
            fprintf(stderr, "invalid call\n");
            return 1;
        }
    
        while (--argc) {
            …
        }
        printf("%g\n", pop());
        return 0;
    }
    
  4. Mishandling of negative numbers: I would expect the following calculation to yield -1:

    $ ./expr 3 -4 +
    warning: the stack is freewarning: the stack is free-3
    
  5. Unconventional division operator: It is customary to use / for division. I don't know why you use \ instead.

  6. Division-by-zero paranoia: In contrast to integer arithmetic, where division by zero is undefined behaviour, division by zero in IEEE 754 floating point arithmetic should just return infinity. Perhaps you could remove the check for division by zero.

Accept emphatic positive numbers
Source Link
200_success
  • 144.2k
  • 22
  • 188
  • 473
  1. Compilation error: This was just carelessness.

    getop.c:31:6: error: conflicting types for 'getOp'
    char getOp(const char *op) {
         ^
    ./calc.h:3:5: note: previous declaration is here
    int getOp(const char *s);
        ^
    1 error generated.
    
  2. Error handling: You treat errors like warnings. If there's an error, I would expect the program to print nothing to stdout, and for the program to exit with a non-zero status code. Error and warning messages should be printed to stderr instead of stdout.

  3. Picky validation: In my opinion, this should successfully evaluate to 1:

    $ ./calc 1
    invalid call
    

    By the way, if you find an insufficient number of command-line arguments, just return early.

    int main(int argc, char *argv[]) {
        if (argc <= 1) {
            fprintf(stderr, "invalid call\n");
            return 1;
        }
    
        while (--argc) {
            …
        }
        printf("%g\n", pop());
        return 0;
    }
    
  4. Mishandling of negative numbers: I would expect the following calculation to yield -1:

    $ ./calc 3 -4 +
    warning: the stack is freewarning: the stack is free-3
    
  5. Unconventional division operator: It is customary to use / for division. I don't know why you use \ instead.

  6. Division-by-zero paranoia: In contrast to integer arithmetic, where division by zero is undefined behaviour, division by zero in IEEE 754 floating point arithmetic should just return infinity. Perhaps you should justcould remove the check for division by zero.

#include <ctype.h>
#include "calc.h"

static int isNumber(const char *s) {
    if (*s == '-' || *s == '+') s++;
    if (*s == '\0') {
        return 0;
    }

    while (isdigit(*s)) s++;

    if (*s == '.') {
        s++;
        while (isdigit(*s)) s++;
    }

    if (*s == 'e' || *s == 'E') {
        s++;
        while (isdigit(*s)) s++;
    }

    return *s == '\0';
}


char getOp(const char *op) {
    return isNumber(op) ? NUMBER : *op;
}
  1. Compilation error: This was just carelessness.

    getop.c:31:6: error: conflicting types for 'getOp'
    char getOp(const char *op) {
         ^
    ./calc.h:3:5: note: previous declaration is here
    int getOp(const char *s);
        ^
    1 error generated.
    
  2. Error handling: You treat errors like warnings. If there's an error, I would expect the program to print nothing to stdout, and for the program to exit with a non-zero status code. Error and warning messages should be printed to stderr instead of stdout.

  3. Picky validation: In my opinion, this should successfully evaluate to 1:

    $ ./calc 1
    invalid call
    

    By the way, if you find an insufficient number of command-line arguments, just return early.

    int main(int argc, char *argv[]) {
        if (argc <= 1) {
            fprintf(stderr, "invalid call\n");
            return 1;
        }
    
        while (--argc) {
            …
        }
        printf("%g\n", pop());
        return 0;
    }
    
  4. Mishandling of negative numbers: I would expect the following calculation to yield -1:

    $ ./calc 3 -4 +
    warning: the stack is freewarning: the stack is free-3
    
  5. Unconventional division operator: It is customary to use / for division. I don't know why you use \ instead.

  6. Division-by-zero paranoia: In contrast to integer arithmetic, where division by zero is undefined behaviour, division by zero in IEEE 754 floating point arithmetic should just return infinity. Perhaps you should just remove the check for division by zero.

#include <ctype.h>
#include "calc.h"

static int isNumber(const char *s) {
    if (*s == '-') s++;
    if (*s == '\0') {
        return 0;
    }

    while (isdigit(*s)) s++;

    if (*s == '.') {
        s++;
        while (isdigit(*s)) s++;
    }

    if (*s == 'e' || *s == 'E') {
        s++;
        while (isdigit(*s)) s++;
    }

    return *s == '\0';
}


char getOp(const char *op) {
    return isNumber(op) ? NUMBER : *op;
}
  1. Compilation error: This was just carelessness.

    getop.c:31:6: error: conflicting types for 'getOp'
    char getOp(const char *op) {
         ^
    ./calc.h:3:5: note: previous declaration is here
    int getOp(const char *s);
        ^
    1 error generated.
    
  2. Error handling: You treat errors like warnings. If there's an error, I would expect the program to print nothing to stdout, and for the program to exit with a non-zero status code. Error and warning messages should be printed to stderr instead of stdout.

  3. Picky validation: In my opinion, this should successfully evaluate to 1:

    $ ./calc 1
    invalid call
    

    By the way, if you find an insufficient number of command-line arguments, just return early.

    int main(int argc, char *argv[]) {
        if (argc <= 1) {
            fprintf(stderr, "invalid call\n");
            return 1;
        }
    
        while (--argc) {
            …
        }
        printf("%g\n", pop());
        return 0;
    }
    
  4. Mishandling of negative numbers: I would expect the following calculation to yield -1:

    $ ./calc 3 -4 +
    warning: the stack is freewarning: the stack is free-3
    
  5. Unconventional division operator: It is customary to use / for division. I don't know why you use \ instead.

  6. Division-by-zero paranoia: In contrast to integer arithmetic, where division by zero is undefined behaviour, division by zero in IEEE 754 floating point arithmetic should just return infinity. Perhaps you could remove the check for division by zero.

#include <ctype.h>
#include "calc.h"

static int isNumber(const char *s) {
    if (*s == '-' || *s == '+') s++;
    if (*s == '\0') {
        return 0;
    }

    while (isdigit(*s)) s++;

    if (*s == '.') {
        s++;
        while (isdigit(*s)) s++;
    }

    if (*s == 'e' || *s == 'E') {
        s++;
        while (isdigit(*s)) s++;
    }

    return *s == '\0';
}


char getOp(const char *op) {
    return isNumber(op) ? NUMBER : *op;
}
Note usability issue
Source Link
200_success
  • 144.2k
  • 22
  • 188
  • 473

Beware, though, of a usability issue with Unix shells, where * and \ have special significance and need to be quoted or escaped.

Beware, though, of a usability issue with Unix shells, where * and \ have special significance and need to be quoted or escaped.

Source Link
200_success
  • 144.2k
  • 22
  • 188
  • 473
Loading