1

A want to check if input string is in right format

"%d/%d"

For example, when the input will be

"3/5"
return 1;

And when the input will be

"3/5f"
return 0;

I have idea to do this using regex, but I had problem to run regex.h on windows.

4
  • You will need to provide a bit more details how you tried to use regex and what went wrong when you did. Commented Nov 29, 2022 at 21:02
  • In my experience, there are three general ways: (1) ad-hoc: have your own char * pointer that you advance along the string, using character comparisons and perhaps <ctype.h> or strtol to check for what you're looking for; (2) scanf, and (3) regex. All three have their pluses and minuses. Commented Nov 29, 2022 at 21:06
  • 2
    regex is a bit of overkill for this. Try strtol: char *cp = buf; int lhs = strtol(cp,&cp,10); if (*cp != '/') return 0; ++cp; int rhs = strtol(cp,&cp,10); if (*cp != 0) return 0; return 1; You can also check errno after each call. Commented Nov 29, 2022 at 21:06
  • Or, using ctype.h primitives: int hasdig = 0; for (cp = buf; *cp != 0; ++cp) { if (! isdigit(*cp)) break; hasdig = 1; } if ((*cp != '/') || (! hasdig)) return 0; ++cp; hasdig = 0; for (; *cp != 0; ++cp) { if (! isdigit(*cp)) break; hasdig = 1; } if ((*cp != 0) || (! hasdig)) return 0; return 1; Commented Nov 29, 2022 at 21:10

2 Answers 2

1

How to check if input string is in correct format ... ?

A simple test is to append " %n" to a sscanf() format string to store the offset of the scan, if it got that far. Then test the offset to see if it is at the end of the string.

int n = 0;
int a, b;
//           v---v----- Tolerate optional white spaces here if desired.
sscanf(s, "%d /%d %n", &a, &b, &n);
if (n > 0 && s[n] == '\0') {
  printf("Success %d %d\n", a, b);
} else {
  printf("Failure\n");
}
Sign up to request clarification or add additional context in comments.

3 Comments

I suppose that if you were worried about leading white space before the numbers or trailing white space, you could devise a scheme like this (gruesomely intricate): int a, b; int o1 = 0, o2 = 0, o3 = 0, o4 = 0, o5 = 0; if (sscanf(s, " %n%d/%n %n%d%n %n", &o1, &a, &o2, &o3, &b, &o4, &o5) == 2 && o1 == 0 && o2 == o3 && o4 == o5 && s[o5] == '\0') { …OK… } else { …some problem… } —— but that's pushing the outer limits of sanity. I've never gone to quite that length before!
@JonathanLeffler sometimes we need to. "The only way of discovering the limits of the possible is to venture a little way past them to the impossible.. BTW, the 5 initializations not needed in this case given the == 2.
Oh, that's clever — I hadn't noticed that. Yes, you could skip initializing o1..o5 if you don't use the values after the if statement. I checked the code with printing after (a mild variation on) the if statement, and could have run into problems with uninitialized values in some of the error reporting if the variables were not initialized.
1

It is not completely clear what you mean by the format "%d/%d".

If you mean that the string should be parsed exactly as if by sscanf(), allowing for 2 decimal numbers separated by a /, each possibly preceded by white space and an optional sign, you can use sscanf() this way:

#include <stdio.h>

int has_valid_format(const char *s) {
    int x, y;
    char c;
    return sscanf(s, "%d/%d%c", &x, &y, &c) == 2;
}

If the format is correct, sscanf() will parse both integers separated by a '/' but not the extra character, thus return 2, the number of successful conversions.

Here is an alternative approach suggested by Jonathan Leffler:

#include <stdio.h>

int has_valid_format(const char *s) {
    int x, y, len;
    return sscanf(s, "%d/%d%n", &x, &y, &len) == 2 && s[len] == '\0';
}

If you mean to only accept digits, you could use character classes:

#include <stdio.h>

int has_valid_format(const char *s) {
    int n = 0;
    sscanf(s, "%*[0-9]/%*[0-9]%n", &n);
    return n > 0 && !s[n];
}

3 Comments

Another option, not clearly superior (or inferior), uses the %n conversion specification. int len = 0; return sscanf(s, "%d/%d%n", &x, &y, &len) == 2 && strlen(s) == len; — well, maybe the extra strlen() is a problem, but you could add a space before %n to allow trailing space in the input, and this would work easily whereas adapting the answer to do so would be relatively hard. A lot depends on as yet unspecified requirements. I note that " 3/ -6" would be acceptable with spaces before both the first and second (negative) numbers. It isn't clear whether this matters either.
@JonathanLeffler: I agree... The case of " 3/ -6" is already covered in my answer. There is no need for strlen() as you can test s[len] == '\0' instead of strlen(s) == len. Regarding trailing whitespace, both "%d/%d %c" and "%d/%d %n" allow it easily.
There is an advantage with " %n" over " %c": when the desired format ends with a non-specifier as in sscanf(s, "%gC", &temperature). sscanf(s, "%gC %c", &temperature) == 1 with and without the final C. Although that case does not apply to OP's code, the " %n" suffix performs well in both cases.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.