Calculating the Volume of a Box












0














I've been studying more C using C Programming: A Modern Approach: A Modern Approach 2nd Edition by K.N. King as well as reading the comp.lang.c FAQ and the CodeReview section here on StackExchange to improve my C skills. I would like your feedback on this recent program I wrote to calculate the volume of a box. It uses ncurses, currently just featuring text input/output but I am planning on expanding on that as I learn more about how to use ncurses.



Specifically, I would like to know thoughts on the following:



1- I am currently using an approach of getnstr(n, len) -> temporary buffer -> conversion to string. I have implemented this to prevent buffer overflow attacks. Is my approach a good way to check this? From what I've read, I saw that scanf() family of functions isn't the best choice for scanning input, so I have used advice I previously received here to implement a solution.



2- Is my approach to "error handling" a good one? Besides gracefully restarting the program (I know that would be a better approach), is this errno assignment a good practice, or is there a preferred way to do this in C? I saw a few examples online when I searched this, most people used something similar yet others used raise and some used longjmp/setjmp. I know there may be multiple right ways of doing this, but what would be preferred?



3- my_strto64 is implemented for conversion to uint64_t, is this function safe? Can it be improved in any way? This function is a slightly modified version of one I received as feedback from previous code which I had received as an answer to a previous Code Review on here.



4- Is this checking for overflows on multiplication properly? Currently I'm just checking the return value of sprintf - unsure if this is enough or if it can be implemented better.



5- Should calloc be used, or malloc, or the stack-based allocation functions such as calloca or alloca? Which is a better choice in this scenario?



Would appreciate your feedback on the points above and/or anything else you find that can be improved in my code. I always learn a lot from all of you knowledgeable folks here. Thank you!



#include <stdlib.h>
#include <ncurses.h>
#include <stdint.h>
#include <inttypes.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>

#define DECSTR_UINT64_MAX_LENGTH 20

int my_strto64(uint64_t *dest, const char *input_str);

int main(void) {
char tmp_str[DECSTR_UINT64_MAX_LENGTH + 1]; // for input prior to parsing (+1 for NUL)
uint64_t height, width, length;
// length + 1 (NUL character)
char* total_string = calloc(DECSTR_UINT64_MAX_LENGTH + 1, 1);

if (!total_string) {
errno = ENOMEM;
perror("Unable to allocate memory");
return errno;
}

initscr();
printw("--- Volume Calculator --n");
printw("Enter length: ");
getnstr(tmp_str, DECSTR_UINT64_MAX_LENGTH);
if(!my_strto64(&length, tmp_str)) {
errno = EIO;
perror("Unable to scan length");
return errno;
}

printw("Enter width: ");
getnstr(tmp_str, DECSTR_UINT64_MAX_LENGTH);
if(!my_strto64(&width, tmp_str)) {
errno = EIO;
perror("Unable to scan length");
return errno;
}

printw("Enter height: ");
getnstr(tmp_str, DECSTR_UINT64_MAX_LENGTH);
if(!my_strto64(&height, tmp_str)) {
errno = EIO;
perror("Unable to scan length");
return errno;
}

int return_value = sprintf(total_string, "Total: %" PRIu64, height * length * width);
// sprintf returns a negative value if it fails, so check it
if (return_value < 0) {
errno = EIO;
perror("Cannot multiply height * length * width");
return errno;
}
printw(total_string);

free(total_string);

refresh();
getch();
endwin();
return 0;
}

/**
* Converts input_str to uint64_t -> returns 0 on success
* Adapted from: https://codereview.stackexchange.com/a/206773/78786
*/
int my_strto64(uint64_t *dest, const char *input_str) {
char *endptr;
errno = 0;
unsigned long long parsed_long_long = strtoull(input_str, &endptr, 10);
#if ULLONG_MAX > UINT64_MAX
if (y > UINT64_MAX) {
uint64_t *dest = UINT64_MAX;
errno = ERANGE;
return errno;
}
#endif
*dest = (uint64_t) parsed_long_long;
if (errno == ERANGE) {
return errno;
}

// `strtou...()` function wraps with `-`
// lets return an error if its negative
if (*dest && strchr(input_str, '-')) {
*dest = 0;
errno = ERANGE;
return errno; // negative, we don't want it
}

if (input_str == endptr) {
errno = EDOM;
return errno; // unsuccessful at converting, still *char
}

while (isspace((unsigned char) *endptr)) endptr++;

if (*endptr) {
errno = EIO;
return errno; // contains invalid characters
}

return (int) parsed_long_long;
}








share



























    0














    I've been studying more C using C Programming: A Modern Approach: A Modern Approach 2nd Edition by K.N. King as well as reading the comp.lang.c FAQ and the CodeReview section here on StackExchange to improve my C skills. I would like your feedback on this recent program I wrote to calculate the volume of a box. It uses ncurses, currently just featuring text input/output but I am planning on expanding on that as I learn more about how to use ncurses.



    Specifically, I would like to know thoughts on the following:



    1- I am currently using an approach of getnstr(n, len) -> temporary buffer -> conversion to string. I have implemented this to prevent buffer overflow attacks. Is my approach a good way to check this? From what I've read, I saw that scanf() family of functions isn't the best choice for scanning input, so I have used advice I previously received here to implement a solution.



    2- Is my approach to "error handling" a good one? Besides gracefully restarting the program (I know that would be a better approach), is this errno assignment a good practice, or is there a preferred way to do this in C? I saw a few examples online when I searched this, most people used something similar yet others used raise and some used longjmp/setjmp. I know there may be multiple right ways of doing this, but what would be preferred?



    3- my_strto64 is implemented for conversion to uint64_t, is this function safe? Can it be improved in any way? This function is a slightly modified version of one I received as feedback from previous code which I had received as an answer to a previous Code Review on here.



    4- Is this checking for overflows on multiplication properly? Currently I'm just checking the return value of sprintf - unsure if this is enough or if it can be implemented better.



    5- Should calloc be used, or malloc, or the stack-based allocation functions such as calloca or alloca? Which is a better choice in this scenario?



    Would appreciate your feedback on the points above and/or anything else you find that can be improved in my code. I always learn a lot from all of you knowledgeable folks here. Thank you!



    #include <stdlib.h>
    #include <ncurses.h>
    #include <stdint.h>
    #include <inttypes.h>
    #include <stdio.h>
    #include <errno.h>
    #include <string.h>
    #include <ctype.h>
    #include <limits.h>

    #define DECSTR_UINT64_MAX_LENGTH 20

    int my_strto64(uint64_t *dest, const char *input_str);

    int main(void) {
    char tmp_str[DECSTR_UINT64_MAX_LENGTH + 1]; // for input prior to parsing (+1 for NUL)
    uint64_t height, width, length;
    // length + 1 (NUL character)
    char* total_string = calloc(DECSTR_UINT64_MAX_LENGTH + 1, 1);

    if (!total_string) {
    errno = ENOMEM;
    perror("Unable to allocate memory");
    return errno;
    }

    initscr();
    printw("--- Volume Calculator --n");
    printw("Enter length: ");
    getnstr(tmp_str, DECSTR_UINT64_MAX_LENGTH);
    if(!my_strto64(&length, tmp_str)) {
    errno = EIO;
    perror("Unable to scan length");
    return errno;
    }

    printw("Enter width: ");
    getnstr(tmp_str, DECSTR_UINT64_MAX_LENGTH);
    if(!my_strto64(&width, tmp_str)) {
    errno = EIO;
    perror("Unable to scan length");
    return errno;
    }

    printw("Enter height: ");
    getnstr(tmp_str, DECSTR_UINT64_MAX_LENGTH);
    if(!my_strto64(&height, tmp_str)) {
    errno = EIO;
    perror("Unable to scan length");
    return errno;
    }

    int return_value = sprintf(total_string, "Total: %" PRIu64, height * length * width);
    // sprintf returns a negative value if it fails, so check it
    if (return_value < 0) {
    errno = EIO;
    perror("Cannot multiply height * length * width");
    return errno;
    }
    printw(total_string);

    free(total_string);

    refresh();
    getch();
    endwin();
    return 0;
    }

    /**
    * Converts input_str to uint64_t -> returns 0 on success
    * Adapted from: https://codereview.stackexchange.com/a/206773/78786
    */
    int my_strto64(uint64_t *dest, const char *input_str) {
    char *endptr;
    errno = 0;
    unsigned long long parsed_long_long = strtoull(input_str, &endptr, 10);
    #if ULLONG_MAX > UINT64_MAX
    if (y > UINT64_MAX) {
    uint64_t *dest = UINT64_MAX;
    errno = ERANGE;
    return errno;
    }
    #endif
    *dest = (uint64_t) parsed_long_long;
    if (errno == ERANGE) {
    return errno;
    }

    // `strtou...()` function wraps with `-`
    // lets return an error if its negative
    if (*dest && strchr(input_str, '-')) {
    *dest = 0;
    errno = ERANGE;
    return errno; // negative, we don't want it
    }

    if (input_str == endptr) {
    errno = EDOM;
    return errno; // unsuccessful at converting, still *char
    }

    while (isspace((unsigned char) *endptr)) endptr++;

    if (*endptr) {
    errno = EIO;
    return errno; // contains invalid characters
    }

    return (int) parsed_long_long;
    }








    share

























      0












      0








      0







      I've been studying more C using C Programming: A Modern Approach: A Modern Approach 2nd Edition by K.N. King as well as reading the comp.lang.c FAQ and the CodeReview section here on StackExchange to improve my C skills. I would like your feedback on this recent program I wrote to calculate the volume of a box. It uses ncurses, currently just featuring text input/output but I am planning on expanding on that as I learn more about how to use ncurses.



      Specifically, I would like to know thoughts on the following:



      1- I am currently using an approach of getnstr(n, len) -> temporary buffer -> conversion to string. I have implemented this to prevent buffer overflow attacks. Is my approach a good way to check this? From what I've read, I saw that scanf() family of functions isn't the best choice for scanning input, so I have used advice I previously received here to implement a solution.



      2- Is my approach to "error handling" a good one? Besides gracefully restarting the program (I know that would be a better approach), is this errno assignment a good practice, or is there a preferred way to do this in C? I saw a few examples online when I searched this, most people used something similar yet others used raise and some used longjmp/setjmp. I know there may be multiple right ways of doing this, but what would be preferred?



      3- my_strto64 is implemented for conversion to uint64_t, is this function safe? Can it be improved in any way? This function is a slightly modified version of one I received as feedback from previous code which I had received as an answer to a previous Code Review on here.



      4- Is this checking for overflows on multiplication properly? Currently I'm just checking the return value of sprintf - unsure if this is enough or if it can be implemented better.



      5- Should calloc be used, or malloc, or the stack-based allocation functions such as calloca or alloca? Which is a better choice in this scenario?



      Would appreciate your feedback on the points above and/or anything else you find that can be improved in my code. I always learn a lot from all of you knowledgeable folks here. Thank you!



      #include <stdlib.h>
      #include <ncurses.h>
      #include <stdint.h>
      #include <inttypes.h>
      #include <stdio.h>
      #include <errno.h>
      #include <string.h>
      #include <ctype.h>
      #include <limits.h>

      #define DECSTR_UINT64_MAX_LENGTH 20

      int my_strto64(uint64_t *dest, const char *input_str);

      int main(void) {
      char tmp_str[DECSTR_UINT64_MAX_LENGTH + 1]; // for input prior to parsing (+1 for NUL)
      uint64_t height, width, length;
      // length + 1 (NUL character)
      char* total_string = calloc(DECSTR_UINT64_MAX_LENGTH + 1, 1);

      if (!total_string) {
      errno = ENOMEM;
      perror("Unable to allocate memory");
      return errno;
      }

      initscr();
      printw("--- Volume Calculator --n");
      printw("Enter length: ");
      getnstr(tmp_str, DECSTR_UINT64_MAX_LENGTH);
      if(!my_strto64(&length, tmp_str)) {
      errno = EIO;
      perror("Unable to scan length");
      return errno;
      }

      printw("Enter width: ");
      getnstr(tmp_str, DECSTR_UINT64_MAX_LENGTH);
      if(!my_strto64(&width, tmp_str)) {
      errno = EIO;
      perror("Unable to scan length");
      return errno;
      }

      printw("Enter height: ");
      getnstr(tmp_str, DECSTR_UINT64_MAX_LENGTH);
      if(!my_strto64(&height, tmp_str)) {
      errno = EIO;
      perror("Unable to scan length");
      return errno;
      }

      int return_value = sprintf(total_string, "Total: %" PRIu64, height * length * width);
      // sprintf returns a negative value if it fails, so check it
      if (return_value < 0) {
      errno = EIO;
      perror("Cannot multiply height * length * width");
      return errno;
      }
      printw(total_string);

      free(total_string);

      refresh();
      getch();
      endwin();
      return 0;
      }

      /**
      * Converts input_str to uint64_t -> returns 0 on success
      * Adapted from: https://codereview.stackexchange.com/a/206773/78786
      */
      int my_strto64(uint64_t *dest, const char *input_str) {
      char *endptr;
      errno = 0;
      unsigned long long parsed_long_long = strtoull(input_str, &endptr, 10);
      #if ULLONG_MAX > UINT64_MAX
      if (y > UINT64_MAX) {
      uint64_t *dest = UINT64_MAX;
      errno = ERANGE;
      return errno;
      }
      #endif
      *dest = (uint64_t) parsed_long_long;
      if (errno == ERANGE) {
      return errno;
      }

      // `strtou...()` function wraps with `-`
      // lets return an error if its negative
      if (*dest && strchr(input_str, '-')) {
      *dest = 0;
      errno = ERANGE;
      return errno; // negative, we don't want it
      }

      if (input_str == endptr) {
      errno = EDOM;
      return errno; // unsuccessful at converting, still *char
      }

      while (isspace((unsigned char) *endptr)) endptr++;

      if (*endptr) {
      errno = EIO;
      return errno; // contains invalid characters
      }

      return (int) parsed_long_long;
      }








      share













      I've been studying more C using C Programming: A Modern Approach: A Modern Approach 2nd Edition by K.N. King as well as reading the comp.lang.c FAQ and the CodeReview section here on StackExchange to improve my C skills. I would like your feedback on this recent program I wrote to calculate the volume of a box. It uses ncurses, currently just featuring text input/output but I am planning on expanding on that as I learn more about how to use ncurses.



      Specifically, I would like to know thoughts on the following:



      1- I am currently using an approach of getnstr(n, len) -> temporary buffer -> conversion to string. I have implemented this to prevent buffer overflow attacks. Is my approach a good way to check this? From what I've read, I saw that scanf() family of functions isn't the best choice for scanning input, so I have used advice I previously received here to implement a solution.



      2- Is my approach to "error handling" a good one? Besides gracefully restarting the program (I know that would be a better approach), is this errno assignment a good practice, or is there a preferred way to do this in C? I saw a few examples online when I searched this, most people used something similar yet others used raise and some used longjmp/setjmp. I know there may be multiple right ways of doing this, but what would be preferred?



      3- my_strto64 is implemented for conversion to uint64_t, is this function safe? Can it be improved in any way? This function is a slightly modified version of one I received as feedback from previous code which I had received as an answer to a previous Code Review on here.



      4- Is this checking for overflows on multiplication properly? Currently I'm just checking the return value of sprintf - unsure if this is enough or if it can be implemented better.



      5- Should calloc be used, or malloc, or the stack-based allocation functions such as calloca or alloca? Which is a better choice in this scenario?



      Would appreciate your feedback on the points above and/or anything else you find that can be improved in my code. I always learn a lot from all of you knowledgeable folks here. Thank you!



      #include <stdlib.h>
      #include <ncurses.h>
      #include <stdint.h>
      #include <inttypes.h>
      #include <stdio.h>
      #include <errno.h>
      #include <string.h>
      #include <ctype.h>
      #include <limits.h>

      #define DECSTR_UINT64_MAX_LENGTH 20

      int my_strto64(uint64_t *dest, const char *input_str);

      int main(void) {
      char tmp_str[DECSTR_UINT64_MAX_LENGTH + 1]; // for input prior to parsing (+1 for NUL)
      uint64_t height, width, length;
      // length + 1 (NUL character)
      char* total_string = calloc(DECSTR_UINT64_MAX_LENGTH + 1, 1);

      if (!total_string) {
      errno = ENOMEM;
      perror("Unable to allocate memory");
      return errno;
      }

      initscr();
      printw("--- Volume Calculator --n");
      printw("Enter length: ");
      getnstr(tmp_str, DECSTR_UINT64_MAX_LENGTH);
      if(!my_strto64(&length, tmp_str)) {
      errno = EIO;
      perror("Unable to scan length");
      return errno;
      }

      printw("Enter width: ");
      getnstr(tmp_str, DECSTR_UINT64_MAX_LENGTH);
      if(!my_strto64(&width, tmp_str)) {
      errno = EIO;
      perror("Unable to scan length");
      return errno;
      }

      printw("Enter height: ");
      getnstr(tmp_str, DECSTR_UINT64_MAX_LENGTH);
      if(!my_strto64(&height, tmp_str)) {
      errno = EIO;
      perror("Unable to scan length");
      return errno;
      }

      int return_value = sprintf(total_string, "Total: %" PRIu64, height * length * width);
      // sprintf returns a negative value if it fails, so check it
      if (return_value < 0) {
      errno = EIO;
      perror("Cannot multiply height * length * width");
      return errno;
      }
      printw(total_string);

      free(total_string);

      refresh();
      getch();
      endwin();
      return 0;
      }

      /**
      * Converts input_str to uint64_t -> returns 0 on success
      * Adapted from: https://codereview.stackexchange.com/a/206773/78786
      */
      int my_strto64(uint64_t *dest, const char *input_str) {
      char *endptr;
      errno = 0;
      unsigned long long parsed_long_long = strtoull(input_str, &endptr, 10);
      #if ULLONG_MAX > UINT64_MAX
      if (y > UINT64_MAX) {
      uint64_t *dest = UINT64_MAX;
      errno = ERANGE;
      return errno;
      }
      #endif
      *dest = (uint64_t) parsed_long_long;
      if (errno == ERANGE) {
      return errno;
      }

      // `strtou...()` function wraps with `-`
      // lets return an error if its negative
      if (*dest && strchr(input_str, '-')) {
      *dest = 0;
      errno = ERANGE;
      return errno; // negative, we don't want it
      }

      if (input_str == endptr) {
      errno = EDOM;
      return errno; // unsuccessful at converting, still *char
      }

      while (isspace((unsigned char) *endptr)) endptr++;

      if (*endptr) {
      errno = EIO;
      return errno; // contains invalid characters
      }

      return (int) parsed_long_long;
      }






      c console integer





      share












      share










      share



      share










      asked 9 mins ago









      Faraz

      270110




      270110



























          active

          oldest

          votes











          Your Answer





          StackExchange.ifUsing("editor", function () {
          return StackExchange.using("mathjaxEditing", function () {
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          });
          });
          }, "mathjax-editing");

          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "196"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: false,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210300%2fcalculating-the-volume-of-a-box%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown






























          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Code Review Stack Exchange!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          Use MathJax to format equations. MathJax reference.


          To learn more, see our tips on writing great answers.





          Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


          Please pay close attention to the following guidance:


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f210300%2fcalculating-the-volume-of-a-box%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          404 Error Contact Form 7 ajax form submitting

          How to know if a Active Directory user can login interactively

          TypeError: fit_transform() missing 1 required positional argument: 'X'