I need to compare strings comparing letters and numbers just by letters and appearance of a number in C.
For example strings "first%dsecond%dj"
should be considered equal to any string like "first[number]second[number]j"
.
I tried to do that like this:
char *c_i
int i, j;
if (sscanf(c_i, "first%dsecond%dj", &i, &j) == 2 &&
c_i[strlen(in) - 2] == 'j') {
printf("%s", c_i);
}
but sscanf ignores everything behind the last number so strings like "first%dsecond%dthird%dj"
also give the true value and is printed.
Generally sscanf
cares just about the values of letters before the last specifier and I would like to find something that counts also the letters after, like say a comparer that checks the whole strings and gets any number but number.
Of course I can do that by creating my own char*
scanner, but I would like to avoid this if there is a simpler way.
Variation on @unwind's good answer.
Use "%n"
to record the current position in the scan and "*"
to negate the need for saving to an int
.
n
... The corresponding argument shall be a pointer to signed integer into which is to be written the number of characters read from the input stream so far by this call to thefscanf
function. ... C11 §7.21.6.2 12An optional assignment-suppressing character
*
. §7.21.6.2 3
// return true on match
bool IE_compare(const char *c_i) {
int n = 0;
sscanf(c_i, "first%*dsecond%*dj%n", &n);
return n > 0 && c_i[n] == '\0';
}
Note: The format string can be coded as separate sting literals for alternative reading.
sscanf(c_i, "first" "%*d" "second" "%*d" "j" "%n", &n);
The above will match leading spaces before the number like "first +123second -456j"
as "%d"
allows that. To avoid:
int n1, n2,
int n = 0;
sscanf(c_i, "first%n%*dsecond%n%*dj%n", &n1, &n2, &n);
return n > 0 && !isspace((unsigned char) c_i[n1]) &&
!isspace((unsigned char) c_i[n2]) && c_i[n] == '\0';
The above will match numbers with a leading sign like "first+123second-456j"
as "%d"
allows that. To avoid:
sscanf(c_i, "first%n%*dsecond%n%*dj%n", &n1, &n2, &n);
return n > 0 && isdigit((unsigned char) c_i[n1]) &&
isdigit((unsigned char) c_i[n2]) && c_i[n] == '\0';
// or
int n = 0;
sscanf(c_i, "first%*[0-9]second%*[0-9]j%n", &n);
return n > 0 && c_i[n] == '\0';
What remains somewhat unclear is if the occurrence of a number is required. "...and appearance of a number" implies yes. Should "firstsecondj"
match? The above answers assume no.