1

With C programming language,

I'm trying to read and store a string input to a char array which has fixed size[11].

When I type characters more than 10, the rest of the characters are sent to the next scanf.

So my question is,

  1. Is there any way to limit the size of input can be typed?

  2. Or, is there any way to cut off the rest of the characters when the input exceeds the size of a char array, not sending to the next scanf?

  3. Or, should I just know how many characters to type?

  4. Or, should I create conditions to prevent this issue?

int main(void)
{
    char phoneNum[11];
    char password[11];

    printf("Enter the phone Number: ");
    scanf("%10s", phoneNum);

    printf("Enter the password: ");
    scanf(" %10s", password);

    printf("\n\n");
    //Display
    printf("Phone number: %s\n", phoneNum);
    printf("Password : %s\n", password);

    return 0;
}

/*
What I tried: 
-input: 
 Enter the phone Number: 123-456-7890
 Enter the password:    // This part has been skipped.

-output:
 Phone number: 123-456-78
 Password: 90


What I expected:
-input:
 Enter the phone Number: 123-456-7890
 Enter the password: asdf12386945648

-output:
 Phone number: 123-456-78
 Password: asdf123869
*/
Kaitlyn
  • 21
  • 2
  • Use something other than `scanf()` for this. E.g. read the whole line with `fgets()` or `getline()`, then use `strtok()` to split it at whitespace, and `strncpy()` to copy from each token to the destination array with a size limit. – Barmar Oct 25 '19 at 21:20
  • You are right up against the limits of `scanf`. When it stops reading, for any reason (like because it hit the character count), it always leaves all the unread input on the input stream, for the next part of your format string to read, whether you want it to or not. – Steve Summit Oct 25 '19 at 21:31
  • You might be able to consume unread input using a cleverly-inserted `%*s` or `%*[...]` specifier. (The `*` means to scan over but *not* assign to a variable.) – Steve Summit Oct 25 '19 at 21:31
  • Two general rules: (a) `scanf` is basically a toy. You can use it for well-defined inputs, but if you want graceful handling of "illegal" inputs (like, the user was only supposed to type 10 characters, but wantonly typed more) it's generally difficult-to-impossible to implement that graceful handling within `scanf`. To do better, you're usually better off using something other than `scanf`. (b) Those length specifiers are best thought of as being there to limit overflow of the destination array, *not* to limit the user's input to some exact value you thought was right. (More in next comment.) – Steve Summit Oct 25 '19 at 21:33
  • It's best to think of `%s` as meaning "read an arbitrary-length string" (although that ends up being incredibly dangerous), and `%##s` as meaning "read an arbitrary-length string, but don't overflow this hopefully-big-enough but ultimately fixed-size array I allocated." If what you want to say is "Yo, user, you are *not* allowed to type an arbitrary-length string, you are allowed to type up to N characters and *that's it*", `scanf` by itself is not a good tool for this job. You're better off reading an arbitrary-length string and then, as a second step, calling `strlen` and complaining. – Steve Summit Oct 25 '19 at 21:36

1 Answers1

2

Is there any way to limit the size of input can be typed?

No, code cannot prevent a user from typing. Instead code can limit the amount of input saved and potentially consume or exit with too much input.

Or, is there any way to cut off the rest of the characters when the input exceeds the size of a char array, not sending to the next scanf?

Yes. Good not to send it to the next input function. Deal with your problems here. A simple solution is

int read_input(char *destination, size_t sz) {
  if (sz > INT_MAX) sz = INT_MAX;
  if (fgets(destination, sz, stdin) == NULL) return EOF;
  size_t len = strlen(destination);
  if (len > 0 && destination[len-1] == '\n') { // lop off potential \n
    destination[--len]  = '\0';
  }
  if (len + 1 == sz) {  // if more input ...
    // let us consume it and toss it.
    int ch;
    while ((ch = fgetc(stdin)) != '\n' || ch != EOF) {
      ;
    }
    // Input exceeds expectations, take evasive action.
    // Maybe print an error message and try again?
    // For now, let us just exit.
    fprintf("Input too long\n");
    exit(EXIT_FAILURE);
  }
  return (int) len;
}    

Or, should I just know how many characters to type?

User input is evil - expect the worst. Recommend to allow 2x the max legitimate input. Beyond that, something bad is up.

Or, should I create conditions to prevent this issue?

Cannot prevent, only cope with errant or nefarious input.


Tip: be generous in expected input size. 11 is too small for phoneNum[]. Allow input to handle 2x of what you might expect, say 30, then qualify input. Insane input lengths are an attack.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256