1

I noticed that when reading a string using scanf in C, it is possible for a string to exceed the amount of characters allocated to it. When this happens I usually encounter a segmentation fault or abort. I've made a quick demo below.

char string[50];

scanf("%s", string);
string[49] = '\0';

Now, if a user were to enter something longer than 50 chars, the code would crash. I tried solving this by adding string[49] = '\0' however that does not seem to be fixing the problem. I understand there is an alternative with fgets, however I do not want the user to be able to write spaces.

User9123
  • 675
  • 1
  • 8
  • 20
  • 5
    you can use `scanf("%49s", string);` for only reading 49 characters, this also ends the string with '\0' – Eduardo Pascual Aseff Feb 21 '20 at 15:24
  • Off by 1: "if a user were to enter something longer than 49 chars ...". – chux - Reinstate Monica Feb 21 '20 at 15:29
  • "I do not want the user to be able to write spaces." --> Use `fgets()` and then parse the data from the string. – chux - Reinstate Monica Feb 21 '20 at 15:30
  • This all comes down to user input is evil. How do you want to handle a user entering more than N characters? How about inputs like `"\n"`, `" \n"`, `" leading_trailing_space \n"`, `"in between space\n"`, `" "`? If code does not handle challenging cases well, I hope the user base is trustworthy - else code becomes buggy or a hacker target. Recommenced to stay with `fgets()`. – chux - Reinstate Monica Feb 21 '20 at 15:36

2 Answers2

3

You can limit the size of string read in within scanf itself like so

scanf("%49s", string);
Chris Turner
  • 8,082
  • 1
  • 14
  • 18
  • From @User9123 : "however I do not want the user to be able to write spaces" ? How this solution can prevent/manage this ? – Landstalker Feb 21 '20 at 16:11
  • 1
    @Landstalker the `%s` format doesn't read in spaces - specifying a width doesn't change that – Chris Turner Feb 21 '20 at 16:30
  • ok, but if i enter "12 34", what happend for the part "34" ? (the blanc between 2 and 3 is a space) you will probably lose it... – Landstalker Feb 21 '20 at 16:34
  • @Landstalker the " 34" will stay in the buffer until it is read in or will be lost when the program terminates – Chris Turner Feb 21 '20 at 16:46
  • Ok, but if you call : `strlen, printf` ... on the variable `string` (readed with `scanf("%49s", string);` ) you will have results depending on the content of the string (12) and not on the content that remained in the buffer (truncated part "34"). and this may distort the behavior of the program – Landstalker Feb 21 '20 at 16:54
  • @Landstalker what remains in the buffer isn't important and won't affect the program as all it is doing is reading in a single string – Chris Turner Feb 21 '20 at 17:21
  • Ok, if we assume that what is entered after the space character can be ignored – Landstalker Feb 21 '20 at 17:25
0

Apparently you have two constraints: the size of the string and the content of the string (space character not desired).

I think you have to process the characters one by one in something that looks like this:

In the define part:

#define MAX_CHAR 50

In the code part:

char chr;
int  iNbRead = 0;
char string[MAX_CHAR]="";

while ( ((chr = getchar()) != EOF) && (chr != '\n') && (iNbRead < MAX_CHAR-1))
{
    if (chr == ' ') 
    {
      // do something for space : for example by ignoring it ...
    }
    else
       string[iNbRead++] = chr;
} 

You will have control over both the number of characters entered and the content of the characters entered

Landstalker
  • 1,368
  • 8
  • 9