2

I need to write two integers (and nothing else) to variables. It does the validation makes sure that none of args is a string and that they are not empty and excepts division by zero, or when i put float as a first arg but when i put float as a second argument it does not makes an exception. How can i solve it using only stdio.h?

#include <stdio.h>

void sum(int a, int b);

void dif(int a, int b);

void prod(int a, int b);

void qut(int a, int b);

int main() {
  int x, z;
  int digits = scanf("%d %d", &x, &z);
  if (digits != 2) {
    printf("n/a\n");
    return 2;
  }
  else {
    sum(x, z);
    dif(x, z);
    prod(x, z);
    qut(x, z);
  }
  return 0;
}

void sum(int a, int b) {

  printf("%d ", a + b);
}

void dif(int a, int b) {

  printf("%d ", a - b);
}

void prod(int a, int b) {

  printf("%d ", a * b);
}
 
void qut(int a, int b) {

  if (a == 0 || b == 0) {
    printf("n/a\n");
  }
  else {
    printf("%d\n", a / b);
  }
}

Sorry, i understand that the code is quiet simple and my question is quiet dumb :) Thx!

v_util
  • 21
  • 2
  • 1
    Don't use `scanf()`. Read a line of input with `fgets()`. Use `strtok()` to split it into tokens. Use `strtol()` to parse each token as an integer, and use the return value to tell if there was anything left over after the integer. – Barmar Jul 06 '22 at 21:38
  • @Barmar thank u! but `strtok()` and `strtol()` are not in `stdio.h`, i can use only this header. my bad - have to clear it in the question, just give me a sec – v_util Jul 06 '22 at 21:43
  • `scanf()` is not really designed for this, but see if you can find something helpful here: https://stackoverflow.com/questions/31633005/validate-the-type-of-input-in-a-do-while-loop-c – Barmar Jul 06 '22 at 21:46
  • @Barmar already checking, thank you again! – v_util Jul 06 '22 at 21:48
  • @Barmar i understand that `scanf` were not designed for this but I HAVE TO do it this way (using only `stdio.h`) because this is a task of my learning quest (sorry for my poor english too) – v_util Jul 06 '22 at 21:53
  • Using only `stdio.h`... The `fgets()` and `sscanf()` are both in that library module. You can read a string, examine it as `int` and as `float`, and use `%n` to get where it stopped scanning. – Weather Vane Jul 06 '22 at 21:57
  • Tell your teacher that we said restrictions on which pieces of the C library you can use are bad pedagogy. – zwol Jul 07 '22 at 01:14
  • @zwol i will do) – v_util Jul 07 '22 at 07:44

2 Answers2

3

As mentioned in the comments, scanf is the WRONG TOOL for this job. scanf is notoriously bad at error handling.

Theoretically it's possible — barely possible — to solve this problem using scanf. By the same token, it's possible to drive a screw into a piece of wood using a hammer. But it's a terrible idea. A woodshop teacher who taught his students to drive screws using a hammer would be fired for incompetence. But for some reason we tolerate this kind of incompetence in teachers of beginning programming.

Normally I don't do homework problems here; normally that's a bad idea, too; normally it makes much more sense to have you, the student, do the work and acquire the learning. In the case of boneheaded assignments like this one, though, I have no qualms about giving you a fully-worked-out solution, so you can get your incompetent instructor off your back and go on to learn something more useful. Here is the basic idea:

  1. Read a line of text (a full line), using fgets.
  2. Parse that line using sscanf, ensuring that it contains a number and a number, and nothing else.
  3. Specifically, we'll use %d to read the first integer, and %d to read the second integer, and then we'll use a third %c to pick up whatever character comes next. If that character is anything other than the \n that marks the end of the line, it indicates that the user has typed something wrong, like a string, or the . that's part of a floating-point number.

This is basically the same as user3121023's solution.

int main()
{
    char line[100];
    int x, z;
    char dummy;

    if(fgets(line, sizeof(line), stdin) == NULL) return 1;
    int digits = sscanf(line, "%d%d%c", &x, &z, &dummy);
    if(digits < 2 || digits > 2 && dummy != '\n') {
        printf("n/a\n");
        return 2;
    }

    ...

See also What can I use for input conversion instead of scanf?

Footnote: The code here has one unfortunate little glitch: If the user types a space after the second number, but before the newline, the code will reject it with n/a. There are ways to fix that, but in my opinion, for this exercise, they're just not worth it; they fall under the "law of diminishing returns". If your users complain, just act like incorrigible software vendors everywhere: remind them that they were supposed to type two numbers and nothing else, and the space they typed after the second number is "something else", so it's THEIR FAULT, and not your bug. :-)

Steve Summit
  • 45,437
  • 7
  • 70
  • 103
  • 1
    *The code here has one unfortunate little glitch: ...* Not too hard: just fail if `dummy` is any non-space character: `if(digits < 2 || (digits > 2 && !isspace(dummy))) ...`. And IMO it's probably worth the extra minute or two to create `if (digits < 2) {...} else if (digits > 2 && !isspace(dummy)) {...}` and provide different error messages. – Andrew Henle Jul 06 '22 at 23:08
  • wow! i thought it should be easier! Now i understand that the easiest way is to use some other libraries and functions (aka right instruments):) thank you for your answer and solution! – v_util Jul 07 '22 at 07:47
0

After scanning for the integers, use a loop to scan for one whitespace character. Break out of the loop on a newline.
For any other character, the scan will return 0.

#include <stdio.h>

void sum(int a, int b);
void dif(int a, int b);
void prod(int a, int b);
void qut(int a, int b);

int main() {
    char ws[2] = ""; // whitespace
    int scanned = 0;
    int x, z;
    int digits = scanf("%d %d", &x, &z);
    if (digits != 2) {
        printf("n/a\n");
        return 2;
    }
    while ( ( scanned = scanf( "%1[ \t\n]", ws))) { // scan for 1 whitespace
        if ( scanned == EOF) {
            fprintf ( stderr, "EOF\n");
            return 1;
        }
        if ( ws[0] == '\n') {
            break;
        }
    }
    if ( scanned != 1 || ws[0] != '\n') {
        printf("n/a\n");
        return 3;
    }
    else {
        sum(x, z);
        dif(x, z);
        prod(x, z);
        qut(x, z);
    }
    return 0;
}

void sum(int a, int b) {
    printf("%d ", a + b);
}

void dif(int a, int b) {
    printf("%d ", a - b);
}

void prod(int a, int b) {
    printf("%d ", a * b);
}

void qut(int a, int b) {
    if (a == 0 || b == 0) {
        printf("n/a\n");
    }
    else {
        printf("%d\n", a / b);
    }
}
xing
  • 2,125
  • 2
  • 14
  • 10