4

I wrote a short example code to illustrate my problem

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

unsigned parseAndCompareDouble(const char* inSTR, const char* inF, const char * expect, const char * outF){
    unsigned e = 0;
    char buffer[2000];
    double a = 0;
    if( 1 != sscanf_s( inSTR, inF, &a, sizeof(double) ) ) e += 1;
    if( (int) strlen(expect) != sprintf_s(buffer, 2000, outF, a) ) e += 1;
    if( 0 != strcmp(expect, buffer) ) e += 1;
    return e;
}

unsigned main( void )
{
    unsigned e = 0;
    const char * universalFormat = "X/%lf";

    e += parseAndCompareDouble("X/100", universalFormat, "X/100", "X/%3.0lf");
    e += parseAndCompareDouble("     X/100\r\n", universalFormat, "X/100", "X/%3.0lf");
    e += parseAndCompareDouble("     X/99\r\n", universalFormat, "X/99", "X/%2.0lf");
    e += parseAndCompareDouble("     X / 99 ", universalFormat, "X/99", "X/%2.0lf");
    e += parseAndCompareDouble("X/99", universalFormat, "X/99", "X/%2.0lf");
    e += parseAndCompareDouble("     \"X/100\"\r\n", universalFormat, "X/100", "X/%3.0lf");  

    if( 0 != e ){ printf( "%2u errors occured\n", e ); }
    else{ printf( "all pass\n", e ); }
    return e;
}

I am looking for a universalFormat that lets my example fixture pass the test. I tried to fiddle around with %*s but I just don't get it rigth. I am missing some concept.

Can someone provide the universalFormat that fits this example and explain how to get there.

Johannes
  • 6,490
  • 10
  • 59
  • 108
  • 1
    I assume an "unnecessary" character is everything that's not in `expect`. What about a function that creates a new string that removes all the unnecessary characters from `inStr`? You would then call scanf on the new string. – user2233706 May 22 '13 at 16:37
  • @user2233706 your assumption is correct. I need to verify the content and read it multiple times. This will be part of a very limited math parser that needs to build and distinguish a known set of functiontypes. I will later rely on some characters to help me verify that i have the correct function. The functionformat is always whitespace + " + functiondata + " + whitespace. – Johannes May 22 '13 at 22:27

1 Answers1

6

You can use the following format:

const char * universalFormat = "%*[^/]/%lf";

The %*[^/] tells scanf to ignore everything that isn't a /. I am assuming your sscanf_s function will understand it, although I am unable to verify that myself. Here's the working program (slightly modified).


Daniel Fischer has brought to my attention that the sscanf_s and sprintf_s functions are defined in Annex K of C Standard 2011 (C11). I raised a question about its relation to conformance.


Knowing that "X /" is in the string is of importance for me.

It seems you are trying to use sscanf to parse free-form input, which is not really its forte. If you are willing to change your parsing code, you can use the modified version of the format string to accomplish this:

const char * universalFormat = "%[^/]/%lf";

Now, your parsing code will need to be updated to read in the string corresponding to the %[^/] specifier, and then you can do some simple scanning on it to make sure it meets your requirements.

char xbuffer[2000];
const char *xp;
/*...*/
if( 2 != sscanf_s( inSTR, inF, xbuffer, sizeof(xbuffer), &a, sizeof(a) ) ) e += 1;
if( (xp = strrchr(xbuffer, 'X')) == 0 || strcspn(xp, "X \t") != 0 ) e += 1;
Community
  • 1
  • 1
jxh
  • 69,070
  • 8
  • 110
  • 193
  • 2
    Those seem to be the (optional) functions from Annex K of the standard. (glibc for example doesn't implement them [yet?], so they're not quite portable.) If they are, they understand the same formats as the `_s`-less versions. – Daniel Fischer May 22 '13 at 18:13
  • +1 For your response, thx. I will try this tomorrow and accept afterwards. Knowing that '"X /"' is in the string is of importance for me. Also knowing that there is nothing else afterwards. I assume your answer will get me started here. – Johannes May 22 '13 at 22:12
  • @user315052 validated :) - thx, the picture is a little bit clearer now. – Johannes May 23 '13 at 09:24