Calculating the Volume of a Box
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
add a comment |
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
add a comment |
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
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
c console integer
asked 6 mins ago
Faraz
270110
270110
add a comment |
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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