-2

The point of this program is to ensure valid input of two integers between 0 to 2 with a space in between (and strictly nothing else), and then to assign the result of these two integers to variables. For some reason this isn't allowed.

Very basic typecasting has me confused. The print statement %i and %i never runs! I can't see why, even though I've put braces around the part that has "success" labelled. I've tried quite a few things.

#include <stdio.h>
#include <string.h>

int main(void)
{
    int row, column;
    char buffer[100];

    }

    printf("enter 2 values of row | column format \n");
    
    fgets(buffer,100,stdin);
    sscanf(buffer,"%c %c",&row, &column);
    printf("%i %i", row,column);

// only accepts integers between 0 and 2 inclusive
 
    if ((((int)row >=48) && ((int)row <= 50 )) && ((int)column >= 48) && ((int)column <= 50))
        {
        
        printf("success\n");
        printf("%i and %i", atoi(row), atoi(column));

        }
        
    else
        printf("fail\n");


    return 0;
}
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
superbo9y
  • 13
  • 3
  • 4
    `%c` expects a pointer to a `char`, but you're passing a pointer to an `int` – ikegami Dec 13 '22 at 02:49
  • sscanf(buffer,"%d %d",&row, &column); printf("%d %", row,column); may be what you want. – MZM Dec 13 '22 at 02:52
  • But what if i want e.g.`num1 = atoi(row) and num2 = atoi(column)`. Im not sure why thats not allowed – superbo9y Dec 13 '22 at 02:56
  • Maybe because that's nowhere close to the argument type `atoi` even needs. The name , `a` as in "ascii" to `i`, as in integer. The function expects a string consisting of digit characters, eventually coming to a non-digit char and/or terminator. You've providing *none* of that with two `int` arguments, and the compiler should be screaming said-same at you. I also find things like `(int)row` completely perplexing. `row` is already an `int`, so what did you expect casts like that to accomplish besides consuming text in your source code? – WhozCraig Dec 13 '22 at 03:02
  • @WhozCraig Its for a tic tac toe game. The input strictly accepts two integers from 0-2 and nothing else. I wanted to validate this in a separate code editor. – superbo9y Dec 13 '22 at 03:10
  • This can _not_ compile. You have an extraneous `}` right after `char buffer[100];` – Craig Estey Dec 13 '22 at 03:17

2 Answers2

1

Good that OP it trying to validate input.


To accept 2 int:

char dummy;  // Used to detect text after the 2 digits
if (sscanf(buffer,"%d %d %c", &row, &column, &dummy) != 2) {
  puts("Input is not 2 ints");
}

Then test the range

if (row < 0 || row > 2 || column < 0 || column > 2) {
  puts("Outside 0 to 2 range");
}

Additional code needed to detect out-of-range text for an int. Something like the below which limits input to 1 digit each for the int and records the scan offset between the two int to insure some white-space.

int n1, n2;
if (sscanf(buffer,"%1d%n %n%1d %c", &row, &n1, &n2, &column, &dummy) != 2 || n1 == n2) {
  puts("Input is not 2 ints");
}

Save time

Enable all compiler warnings. A good compiler will complain about sscanf(buffer,"%c %c",&row, &column); - "%c" expects an char *, not int *.

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

Move away from the scanf() family of functions. They are the cause of so many SO questions...

The following should be simple to understand. When you wake up I'd be happy to elaborate on anything you might find perplexing.

#include <stdio.h>
#include <string.h>

int main( void ) {
    printf("enter 2 values of row | column format \n");
    
    char buf[ 100 ];
    fgets( buf, 100, stdin );

    if( buf[3] == '\n' // fgets leaves LF in the buffer
    &&  ('0' <= buf[0] && buf[0] <= '2' )   // limit ASCII digit
    &&  buf[1] == ' '                       // single space between
    &&  ('0' <= buf[2] && buf[2] <= '2' )   // limit ASCII digit
    ) {
        int row = buf[0] - '0', col = buf[2] - '0';
        printf( "success\n%i and %i", row, col );
    } else
        puts( "fail" );

    return 0;
}
Fe2O3
  • 6,077
  • 2
  • 4
  • 20
  • This accepts `"1 2 3\n"` which should fail, yet rejects `"1\t2\n"`, `" 1 2\n"`, `"1 2\n"`, which should be acceptable as should `"1 2 "`, `"1 2"`. – chux - Reinstate Monica Dec 13 '22 at 06:10
  • @chux-ReinstateMonica How so? Did you compile and run it? Quoting the OP: "input of two integers between 0 to 2 with a space in between (and **strictly nothing else**)" Please explain... – Fe2O3 Dec 13 '22 at 06:35
  • Fair enough about it rejecting `"1 2 3\n"`, yet the progression of tests should advance from index 0 to index 3 to avoid testing against a potential unassigned element as with `"1\n"`. – chux - Reinstate Monica Dec 13 '22 at 10:45
  • @chux-ReinstateMonica You've got a point, but... I'm content in that the buffer is big enough (not stepping out of bounds) AND each of the first 4 bytes is tested to conform to specifications. Putting the buf[3] test first was an aesthetic choice for the appearance of the code... `:-)` – Fe2O3 Dec 13 '22 at 11:01
  • FWIW, it is the test of `'0' <= buf[0] && buf[0] <= '2'` that blinded my review to the existence of the prior line's test as testing out of order risks [trouble](https://stackoverflow.com/q/11962457/2410359). – chux - Reinstate Monica Dec 13 '22 at 11:10
  • @chux-ReinstateMonica I appreciate your feedback. Thank you. Apart from "aesthetics", following `fgets()` as this does, initially confirming buf[3] to be LF is analogous to checking the length of input (kinda) before proceeding with other particular - and thorough - checks of the input. Another option would be to present the user with the 9 choices/combinations ( printf() )and accept only 1-9 as input... Simpler for everyone... `:-)` – Fe2O3 Dec 13 '22 at 20:14