2

I am looking for a function that checks if a string follows (matches exactly) the pattern of data specified by the additional arguments corresponding to the format string Like this:

/* int strcmpf (char *str1, char *format, ...); */
char *test = "Hello World !"

if(!strcmpf(test, "%s%*s %c", "Hello ", '!')
    return HELLO_HAS_BEEN_SAID;
else
    return PROGRAM_ISNT_POLITE;

Implementing this myself I assume will be very difficult, but such function could be very useful for semantic parsing of content. Before I attempt to write such function myself, I need to know if there is already a library or code snippet that provides implementation of a function like this ?


To be more specific, I need pattern-matching behavior. So test must match exactly the pattern specified by the data corresponding to the format parameter.

Imobilis
  • 1,475
  • 8
  • 29
  • 5
    Implementing such a function is very simple, just use [`vsnprintf`](http://en.cppreference.com/w/c/io/vfprintf) for formatting and then call `strcmp`. – Some programmer dude Aug 05 '16 at 12:39
  • 1
    @JoachimPileborg Quite right, but If I have to put it in a function along a call of `strcmp()` I still need to provide variadic arguments for the function. Which is not "very simple" for everyone don't you agree ? Doesn't seem that practical to me at least.. – Imobilis Aug 05 '16 at 12:43
  • @JoachimPileborg: What now? Where does `"world"` come from in your proposed solution? – Kerrek SB Aug 05 '16 at 12:43
  • 1
    @KerrekSB It doesn't, I only said that creating a functions that formats a string and then uses `strcmp` is easy. If it's not called correctly is another problem. :) – Some programmer dude Aug 05 '16 at 12:45
  • @Malina It's actually very easy if you don't want dynamic buffers to make sure you fit all the formatted string. It's just a few lines of code. – Some programmer dude Aug 05 '16 at 12:47
  • .. and the max buffer size for `snprintf()` can easily be determined: `strlen( test ) + 2` -- the extra byte forces a difference if the stringe became longer – Ingo Leonhardt Aug 05 '16 at 12:48
  • @JoachimPileborg Then there is no such function and I have to write it myself eh ? This is where you go right ? `vsnprintf` is a function that does some of the job now that I see, but clearly not all the job. One still needs to implement variadic arguments. If you say it is easy, then this is soothing (for me). – Imobilis Aug 05 '16 at 12:49
  • 1
    @Malina Variadic arguments are provided by `stdarg.h`. Read a C tutorial of choice on how to do that. On a UNIX-like systems, type `man va_arg` to get this information. – fuz Aug 05 '16 at 12:51
  • 5
    @JoachimPileborg: The way I understand it is that the OP wants pattern matching, e.g. "hello" followed by anything followed by "!". That would be more than just fixed-string comparison. Maybe I misunderstood the OP or your proposed solution? – Kerrek SB Aug 05 '16 at 12:56
  • @KerrekSB Yes you are right, I DO want pattern matching, e.g. "hello" followed by anything followed by "!". printf-alike functions skip to read data with format specifiers like "%*s". I thought it is evident. – Imobilis Aug 05 '16 at 12:58
  • 1
    Well, it was not so clear... ;) – LPs Aug 05 '16 at 12:59
  • @LPs What do you mean it was not so clear ? It follows a very specific printf-specific pattern. – Imobilis Aug 05 '16 at 13:00
  • And it is just an example. That means the function I seek for needs to do that as well. Act as if I were using printf to compare buffer with the matched format arguments – Imobilis Aug 05 '16 at 13:06
  • 4
    What was unclear -- to me, too -- was that you want pattern-matching behavior, as opposed to simply formatting a string and comparing the formatted result to a target string. If you want pattern matching rolled in then I suggest you look to a regex library for that part (and design your wrapper function appropriately for that). – John Bollinger Aug 05 '16 at 13:07
  • Okay finally, to find out a sentence to be very self-explanatory. Sorry. It's just hard to describe that ha-ha. – Imobilis Aug 05 '16 at 13:34
  • Before you ask about anothe special function: The features of the standard library are free to be found. The basic idea is to provide just the necessary, not anything for any purpose. But you can combine funtion calls, generating new function. Just like Unix. – too honest for this site Aug 05 '16 at 13:35
  • @Olaf Yes. Sadly the standard doesn't really define a function like this, and I can really hard be convinced that it is not useful. A stdarg.h appears to be in need here at least – Imobilis Aug 05 '16 at 13:37
  • I guess you *could* use something like `sscanf(test, "Hello%*s !") == ???` or similar, but that would be **very** error prone. Personally I would use actual regex library like others have suggested. – user694733 Aug 05 '16 at 13:38
  • Did you even understand my comment? No, it is not bad. That' why you can write your oown code or use other libraries! What if any crude function anyone wants would be in the standard? – too honest for this site Aug 05 '16 at 13:39
  • Implementing of this function won't be very easy I think. But I will handle it. – Imobilis Aug 05 '16 at 13:40
  • "Pattern matching" matches Regular Expressions. See `man regex`. – alk Aug 05 '16 at 14:20
  • Should your example contain a space between the two strings? Otherwise how would you decide where to split? `%s %*s %c` – Kerrek SB Aug 05 '16 at 14:55
  • It would be easy if it wasn't for the pattern matching. That will make it hard. Regular expression is probably the way to go here. – Some programmer dude Aug 08 '16 at 07:17
  • @KerrekSB the format specifiers serve to ensure there is such data in the string. For example strcmpf("Hello46World", "%s%i%c", "Hello", 46, 'W'); will return 0 (strings are identical) – Imobilis Aug 09 '16 at 09:21
  • `strcmpf("Hello46World", "%s%*s%c", "Hello", 'W');` will return non-zero value as 46 is considered integral data. This is where it differs from other formatting functions. It doesn't care of white spaces it compares with the data it is provided with. – Imobilis Aug 09 '16 at 09:23
  • @Malina: Hm, now you lost me. Until now this sounded like a very sensible idea. I don't know what "integral data" is, though. To me, "hello123" is a perfectly fine string, and I'd be upset if someone told me I couldn't have such a string. – Kerrek SB Aug 09 '16 at 10:55
  • 1
    @JoachimPileborg: It doesn't look harder than the implementation of `scanf`. I actually find the idea quite appealing - you'd use the same scanning algorithm as `scanf`, but instead of storing the data, you perform a comparison operation. – Kerrek SB Aug 09 '16 at 10:55
  • @KerrekSB You understand the idea, but the concept not to a full extent. The proper way to compare this string is with `%s%i` because the string contains a number. If you want to compare without knowing the number `%s%*i` or if you want to compare without providing additional data `%s123` I don't see what is the problem. This function is indeed useful, but Caveat emptor. – Imobilis Aug 09 '16 at 11:26
  • @Malina: Ah OK, so perhaps you really do want full regular expressions. I was thinking that simple scanf-like matching would also be neat, but that doesn't seem to be what you want/need. – Kerrek SB Aug 09 '16 at 11:27
  • I see that you just prefer to stick with scanf-alike scanning algorithm, which is fine, I would get used to it.. but in implementation of such function to perform comparison - it does slightly different and is not very accurate. Besides, people often find trouble with scanf in terms of it scanning-out on whtiespace. – Imobilis Aug 09 '16 at 11:29
  • @KerrekSB Well I intend to write such function anyway. Imminently. Once done one could easily manage to make it behave like scanf when it comes to scanning. He might however, say STOP to himself and leave it as it is, realizing it is _better_ – Imobilis Aug 09 '16 at 11:33

1 Answers1

3

I need to know if there is already a library or code snippet that provides implementation of a function like this

The standard library has no such functionality. Requests for third-party library recommendations are off-topic here, but to the extent that I understand the functionality you want, I am anyway unaware of an existing third-party implementation.

As I said in comments, I suggest that you design the pattern-matching aspect around bona fide regular expressions instead of around printf() or scanf() formats (which are not entirely the same). There are several regular expression libraries available to support that part.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • The problem in explaining arrived from that I relied on people understanding why it is `strcmpf` not `sscanfcmp` I guess. – Imobilis Aug 05 '16 at 14:01
  • The real reason why I need a function like this is to properly interpret gcc's stderr debug information output. That is.. to know where the message is instance, error, warning, line link, file path et cetera :) That way I can highlight the specific information. – Imobilis Aug 05 '16 at 14:04
  • @Malina, for that, you probably don't even need regex. GCC diagnostics consist of four colon (:) -delimited fields, and you can rely on the first three to not themselves contain colons. You can just split the diagnostic text at the (first three) colons and process each piece appropriately. You can split the string with `strtok()`, with `sscanf()`, or in a variety of other ways. – John Bollinger Aug 05 '16 at 14:13
  • If for example I have the gcc message "In function 'main'", interpreting function must evaluate it as "In %*s \'" to make sure it is message saying about the instance 'main' not an error message that includes "In function" for instance. This is why I need such function. So that I can ultimately check what kind of message the compiler throws. – Imobilis Aug 05 '16 at 14:17
  • @Malina: regular expressions. Regex is a much more flexible and expressive mechanism for pattern matching than are format strings. If you don't already know any regex languages then now would be a good time to learn. Regex is the most appropriate tool I can think of for this job. – John Bollinger Aug 05 '16 at 14:21