Reputation: 3
I have trouble trying to return the string that is scanned in a function and return the string to the first pointer string argument.
The string is a new thing I just learn this week. I tested passing back arguments as integer and character, and both of them work. The code is as follows. This is just part of the code because the whole project is in 3 files. As the code shows, the string is meant to send as an address (the string does not need a & sign). The function scans the input string, and the string gets sent back as an argument.
To be honest, this is my assignment, using return to send back the string is not an option.
`
char stringValue[7] = { '\0' };
input(stringValue, 4, 6);
printf("The string is %s", stringValue);
void input(char* string, int minimum, int maximum)
{
char inputs[7];
scanf("%[^\n]", inputs);
*string = charInRange;
}
`
When I run it, the printing of the value is random. I tested with other tool, and it said:
"assignment makes from pointer without a cast."
I am sure that the problem is probably the line assigned input to the pointer. I think it's some format error. I tried adding some &, *, or removing them. I spent the whole testing and searching for an answer but no result.
Upvotes: 0
Views: 112
Reputation: 84541
Continuing from my comments, your primary problem in input()
is you read into the array char inputs[7];
with scanf("%[^\n]", inputs);
and then attempt to assign charInRange
(nowhere declared in your code) as the first character in string
. This won't compile.
When you attempt to print stringvalue
back in main, since charInRange
isn't defined (or isn't initialized or is initialized outsize the range for ASCII characters), you get gibberish.
As explained in the comments, the input[]
array isn't necessary. You have already declared storage for stringvalue
in main()
and are passing the address for that storage (the pointer char *string)
to the input()
function. You simply need to read into string
in the input()
function. The input[]
array is unnecessary.
However, before looking at how you can do that, when you are providing a buffer (a character array) for user-input -- Don't Skimp on Buffer Size. When you use scanf()
with "%[ ]"
the user can enter any number of characters beyond you array size, writing beyond the end of your array. This is a favorite exploit by buffer overrun.
If using the "%s"
or "%[ ]"
format specifiers with scanf()
you must provide a field-width modifier to limit the number of characters that can be read. Failure to do so renders scanf()
no safer than gets()
. See Why gets() is so dangerous it should never be used!
This is just one of the scanf()
pitfalls, and one of the reasons why new C programmers are encouraged to take all user-input with fgets()
.
With that said, let's look at how we can write your input()
function to only accept a user-input of between min
and max
chars. As mentioned, whenever you have conditions your input must meet, the approach is the loop continually reading input from the user (your read-loop). Check the length of what the user entered and only if the length is from min
to max
, break
your read-loop and return.
To ensure your read-buffer is sufficiently sized, make it larger than what you anticipate the max string you will accept is. (a lot longer, you have a 4M stack on Linux and a 1M stack on Windows) a 1K buffer is fine. On embedded systems where memory is limited, then adjust the buffer size down. When you need to set constants in your code #define
them, don't just throw Magic Numbers like 4
and 6
in as parameters. You can do that with:
#include <stdio.h>
#include <string.h>
#define INPUTSZ 1024 /* if you need a constant, #define one (or more) */
#define MAXC 6
#define MINC 4
Now you can write your input()
function similar to:
void input (char *string, size_t min, size_t max)
{
/* loop continually until valid input given */
for (;;) {
size_t len; /* length to test against min */
fputs ("\nenter string: ", stdout); /* always prompt for input */
/* take all user-input with fgets (into a larger buffer - don't skimp)
* validate the return of every input function used.
*/
if (!fgets (string, INPUTSZ, stdin)) {
puts ("(user canceled input)"); /* return is NULL, Ctrl+d (z) used */
*string = 0; /* set string as empty-string */
return;
}
len = strcspn (string, "\n"); /* get length of input minus '\n' */
string[len] = 0; /* overwrite '\n' with '\0' */
if (min <= len && len <= max) { /* condition met, break read loop */
break;
}
/* handle invalid input */
fprintf (stderr, "input must be %zu-%zu characters\n", min, max);
}
}
(note: you can save the length while trimming the '\n'
from string
in a single step, e.g. string[(len = strcspn (string, "\n"))] = 0;
, but that was split for readability above. Also note 0
and '\0'
are equivalent. 0
being the ASCII value for the nul-character, see ASCII Table)
And finally your main()
, e.g.
int main (void) {
char stringvalue[INPUTSZ] = "";
input (stringvalue, MINC, MAXC);
if (*stringvalue) {
puts (stringvalue);
}
}
(note: the stringvalue
is only printed if the user didn't cancel by generating a manual EOF
with Ctrl + d (Ctrl + z on windows))
Can you look and determine what line in the input()
function allows you to make the test if (*stringvalue)
? Note *stringvalue
is the same as *(stringvalue + 0)
which is the pointer notation for stringvalue[0]
.
Example Use/Output
Does the code limit input to the proper number of characters?
$ ./bin/inputmaxmin
enter string: 12
input must be 4-6 characters
enter string: 123
input must be 4-6 characters
enter string: 1234567
input must be 4-6 characters
enter string: 1234
1234
What about handling the user canceling input with Ctrl + d?
$ ./bin/inputmaxmin
enter string: one hundred twenty-three
input must be 4-6 characters
enter string: (user canceled input)
Also, you seem a little iffy on pointers. Here are a couple of links that provide basic discussions of pointers that may help. Difference between char pp and (char) p? and Pointer to pointer of structs indexing out of bounds(?)... (ignore the titles, the answers discuss pointer basics)
Look things over and let me know if you have questions.
Upvotes: 4