0

I have the next code:

#include <stdio.h>
int main(){
    char* a;
    int b;
    if(fscanf(stdin,"%s%d",a,&b)!=2){
        printf("Bad Args!!");
    }
  return 0;
}

when i try to add the next inputs -

F52352354

5F2352354

i get the next output:

For the first one - Bad Arg

For the second Nothing

another thing that makes a trouble is when i try to check about big numbers then the range of int and in the range of double i get that the input is OK.

My question is if there is an elegant way to check the parameters (in C and not at C++) ?

Bizzu
  • 449
  • 3
  • 17
  • 1
    I don't understand what you're asking, but: 1. `a` is uninitialized in the call to `fscanf`. Undefined behavior. 2. Don't use `scanf` for user input. – melpomene Oct 08 '17 at 11:59
  • @melpomene thanks for your answer. 2. what is your proposal for getting input from the user? – Bizzu Oct 08 '17 at 12:03
  • @melpomene Why shouldn't we use `scanf()` ? – J...S Oct 08 '17 at 12:54
  • @J...S It's fundamentally incompatible with user expectations (e.g. that hitting Enter should do something: accept input, or print an error, or anything). It's hard to use correctly. Even if you get it right and detect errors, recovering from those errors is even harder or impossible. – melpomene Oct 08 '17 at 12:56
  • @J...S Case in point: https://stackoverflow.com/q/46631193/1848654 – melpomene Oct 08 '17 at 13:00
  • @melpomene Wouldn't `scanf("%255[^\n]", msgtobesent);` be okay in that case? – J...S Oct 08 '17 at 13:07
  • @J...S No, you'd still have to check the return value. And why bother with complex format strings when you can just use `fgets`? – melpomene Oct 08 '17 at 13:10
  • @melpomene But `fgets()` return value must also be checked, right? It would return `NULL` upon error. – J...S Oct 08 '17 at 13:12
  • @J...S Yes, indeed. – melpomene Oct 08 '17 at 13:13

2 Answers2

2

You made a char pointer. But it's just a pointer and not an array.

If you use a uninitialised pointer, which has some indeterminate (garbage) value, it points to some location which may not even be a location that the program is allowed to access or worse yet could be pointing to another process's memory which would in turn cause error.

Either use dynamic memory allocation like

char *a=malloc(sizeof(char)*100);
if(a==NULL)
{
    perror("Not enough space");
}

which must be deallocated after use with free(a).

Or make a statically allocated array like

char a[100]; 

You seem to expect to read a string and then a number. If the input is a string without numbers and then a number, you could use

scanf("%99[^0-9]%d", a, &b);

The scanf() would read at most 99 characters till it encounters a number, places it in a and the number is stored in b.

As @David pointed out, this wouldn't skip the leading white spaces. If you want to skip the leading white spaces before writing to a, use a space before the %99[^0-9] like

scanf(" %99[^0-9]%d", a, &b);

Check the return value of scanf() to see if scanf() was successful as you did.

Note that if scanf() fails, some characters will still be left in the input buffer and you may want to remove it.

You could do this to consume from input buffer till the next \n

int ch;
while( (ch=getchar())!='\n' && ch!=EOF );

fscanf(stdin, ........) is equivalent to scanf(.........).

J...S
  • 5,079
  • 1
  • 20
  • 35
  • `while((ch = getchar()) != '\n');` --> `while((ch = getchar()) != '\n' && ch != EOF);` to avoid a potential infinite loop. – ad absurdum Oct 08 '17 at 13:47
  • Also note that `"%99[^0-9]%d"` does not skip over leading whitespace characters, while OP's `"%s%d"` does skip over leading whitespace. – ad absurdum Oct 08 '17 at 13:50
  • @DavidBowling Would adding a preceding space like " %99[^0-9]%d" would skip over leading spaces? – J...S Oct 08 '17 at 13:51
  • 1
    You make it sound like "may not even be accessible to the program" is the bad thing, but it's the _best_ possible outcome. Pointing at some of the process's (writable) memory would be much worse! The point is that there is no (appropriate) array, as you also said. – Davis Herring Oct 08 '17 at 13:54
  • @Davis Why is it the best thing? Can you give an example? – J...S Oct 08 '17 at 13:59
  • 1
    @J...S: Because you get a signal and immediately learn that your program is wrong (and even the approximate location of the mistake). Undefined behavior has _many_ worse possibilities than that! – Davis Herring Oct 08 '17 at 16:32
0

I think you have at least 2 problems her. a is a pointer to char, but scanf requires a char array. Also, %s will get as many characters as possible until the input has finished or a space, so following it with a %d means that the %s will get all the input and the %d gets nothing.

Neil
  • 11,059
  • 3
  • 31
  • 56
  • The `%d` will just get the next number. E.g. `foo 123` would be accepted. – melpomene Oct 08 '17 at 12:01
  • Yes, because there is a space between them but ``foo123`` would not put anything in the %d specifier and fail the ``if()``. – Neil Oct 09 '17 at 09:44