How to take ints from user using fgets in C?
45,685
Solution 1
First of all, a definition like
char* height, width, depth;
make height
a pointer to char
and the rest two as char
s.
Secondly (not much relevant here, but in general, important), You did not allocate memory to the pointers you want to use (if at all).
If you have a fixed input length decided as 10
, you can simply make all the three variables as array ans use the names directly, like
#define VAL 10
char height[VAL] = {0};
char width[VAL] = {0};
char depth[VAL] = {0};
and then
fgets(height, 10, stdin);
finally, consider using strtol()
over atoi()
for better error handling.
Solution 2
Simple solution of your problem.
#include <stdio.h>
#include <stdlib.h>
int volumn(int a, int b, int c){
return a*b*c;
}
int main(){
char height[10];
char width[10];
char depth[10];
printf("Please enter size of object:\n");
fgets(height, 10, stdin);
fgets(width, 10, stdin);
fgets(depth, 10, stdin);
int valheight = atoi(height);
int valwidth = atoi(width);
int valdepth = atoi(depth);
printf("\nThe volumn is %i\n", volumn(valheight, valwidth, valdepth));
return 0;
}
Author by
johnwj
Updated on July 09, 2022Comments
-
johnwj almost 2 years
I'm a beginner at C. I'm trying to write a program that computes the volume based on user's input of 3 integers using
fgets()
, and I'm struggling to understand why my code is not working.#include <stdio.h> #include <stdlib.h> int volumn(int a, int b, int c); int main(int argc, char* argv[]){ char* height, width, depth; fgets(&height, 10, stdin); fgets(&width, 10, stdin); fgets(&depth, 10, stdin); printf("\nThe volumn is %d\n", volumn(atoi(&height), atoi(&width), atoi(&depth))); return 0; } int volumn(int a, int b, int c){ return a * b * c; }
EDIT: I'm getting the following errors/warnings when I run the code above:
goodbyeworld.c:8:11: warning: incompatible pointer types passing 'char **' to parameter of type 'char *'; remove & [-Wincompatible-pointer-types] fgets(&height, 10, stdin); ^~~~~~~ /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/stdio.h:238:30: note: passing argument to parameter here char *fgets(char * __restrict, int, FILE *); ^ goodbyeworld.c:12:48: warning: incompatible pointer types passing 'char **' to parameter of type 'const char *'; remove & [-Wincompatible-pointer-types] printf("\nThe volumn is %d\n", volumn(atoi(&height), atoi(&width), a... ^~~~~~~ /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/stdlib.h:132:23: note: passing argument to parameter here int atoi(const char *); ^ 2 warnings generated.
-
Anders over 8 yearsHello and welcome to Stack Overflow! Could you be a bit more precise about how it's not working? Is it compiling? Do you get any error messages? If it runs, what happends when it runs? Please edit your question.
-
user3629249 over 8 yearsAlways, when compiling, enable all the warnings (for gcc, at a minimum use:
-Wall -Wextra -pedantic
) then fix the warnings. With the posted code you would see two warnings: 1) unused variable 'argc' 2) unused variable 'argv[]' along with the warnings you are already seeing.
-
-
Admin over 8 yearsI'd consider the missing allocation very relevant here, too
-
Sourav Ghosh over 8 years@FelixPalmen as OP's passing
&height
, the whole thing is wrong, anyway. :) -
Admin over 8 yearsIndeed, but just fixing that issue, the segfault is next ;)
-
Sourav Ghosh over 8 years@FelixPalmen that's why I switched to arrays. :)
-
Admin over 8 yearsI never found
scanf()
of any use for real-world interactive input (and I assume that is what OP wants to do here) -
Coffee'd Up Hacker over 8 years@FelixPalmen I fail to see how
fgets
is anymore "interactive" thanscanf
-
Admin over 8 yearsusing
fgets()
, you can react on unexpected input properly, something happening quite often in the interactive case. -
Coffee'd Up Hacker over 8 yearsDon't both only return once a newline/EOF is encountered? If so, I still don't see how
fgets
is any better. Get the input, and do whatever you want to validate it after. Withscanf
you can at least specify what kind of data you're expecting, making validation much simpler. -
Admin over 8 yearsMaybe simpler in some cases, but much less flexible, because it won't give you access to the original input. I'd always go with some other solution, e.g.
strtol()
like suggested in the other answer. -
Coffee'd Up Hacker over 8 yearsJust use a
%s
then. Besides, conversions add unnecessary execution time, and converting something like "I'd like it to be 10" withstrtol
wouldn't give you what you'd expect anyway, while the%d
withscanf
allows it to fail and prompt again. -
johnwj over 8 yearsHow do I use strtol() to convert height to an int? I tried atoi(height), and it did not work.
-
Jongware over 8 years@tbee: how in the world could a simple
atoi(height)
not work?? -
johnwj over 8 years@Jongware I was running atoi(&height). Oops. atoi(height) does work.
-
Admin over 8 yearsThis makes even less sense now.
%s
IS a conversion, of course it takes time, and it's utterly pointless when you want nothing other than that string. -
user3629249 over 8 yearswhen calling scanf(), always check the returned value (not the parameter value) to assure the operation was successful. When using the format specifier '%s', always include a length modifier, so the user cannot overrun the input buffer.
-
user3629249 over 8 years@Jongware, an atoi() can fail when the string pointed to by the parameter has no leading numeric value(s) for instance "abcedf" or " 123"
-
Coffee'd Up Hacker over 8 years@FelixPalmen My point is
%s
gives you more or less the same behavior asfgets
, minus the forced newline. And no,%s
is not a conversion, it's more of a type check,scanf
fails if the input doesn't match the specifiers. Withfgets
, you have to get the string, which is one action, and then you have to convert it, which is another action, which may or may not throw an error because the input may or may not be a value convertible to a long. -
Coffee'd Up Hacker over 8 years@user3629249 I had hoped that the use of
%10s
was implied by my use of%10d
in my answer. -
Admin over 8 yearsFor the term conversion, see
scanf(3)
. And no, an operation is not more efficient, just because you use one big library functions with tons of bells and whistles instead of 2 much simpler ones that even give you a lot more control. I rest my case,scanf()
is a bad idea, at least for interactive input. -
Coffee'd Up Hacker over 8 years@FelixPalmen So your argument is semantics. My point is
fgets
requires at least two actions, one of which is an explicit type conversion which the programmer has to take separate care to check against errors, meaning even more work and more code, more slow and more bloat. Whilescanf
, with or without a type conversion (because it doesn't always do a conversion), does all of this simultaneously, simplifying everything, without sacrificing anything. You've failed to show howfgets
is any better for "interactivity", or generally, better in any other way. -
Coffee'd Up Hacker over 8 years@FelixPalmen All of this is moot anything, as OP has their answer. They seem fine with an
fgets
andstrtol
mix.