0

This question is related to: Get number of characters read by sscanf? however, it asks specifically how to wrap the variadic arguments (C++11 variadic templates) to achieve the effect.

I would like to have a function:

int my_sscanf( int& ncharswritten, const char* str, const char* fmt, ... )
{
}

which returns the normal number of format things specified, but furthermore (as a reference argument for example) returns the number of characters written.

As noted in the above link, the suggested solution to know number of characters written is to use the %n at the end of the fmt. The question is how to achieve this in real life without having to add that to fmt manually each time.

Community
  • 1
  • 1
rveale
  • 66
  • 1
  • 10
  • You will need to add `%n` to the format string in some way. Most simply `std::string fmt2 = fmt + "%n"; ... sscanf( ... fmt2.c_str() ... );` – Mats Petersson Feb 12 '16 at 08:35
  • Thanks Mats, the devil is in the detail of how to add the additional required int* argument at the end of the variadic argument list to sscanf(), after adding %n to the end of fmt. – rveale Feb 12 '16 at 08:41

2 Answers2

1

You may use something like:

template <typename...Ts>
int my_sscanf( int& ncharswritten, const char* str, const char* fmt, Ts&&...ts )
{
    return sscanf(std,
                  (fmt + std::string("%n")).c_str(),
                  std::forward<Ts>(ts)...,
                  &ncharswritten);
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • Thanks jarod that's basically what I found, I'll accept your answer. I don't understand the std::forward part of it though, or the Ts&& bit. – rveale Feb 12 '16 at 08:38
  • It is the way to forward argument (preserve constness, rvalue/lvalue, ...). In your case passing by copy should be ok at the argument are pointers (so `Ts*...ts` might even be better). – Jarod42 Feb 12 '16 at 08:43
  • Ah, I see. In the case of sscanf, they are always pointers so I guess I Just got lucky in that case? My example below works for some reason... – rveale Feb 12 '16 at 08:44
0

I solved the question after bugging around a bit:

 template<typename... Args>
  int my_scanf(int& nchars, const std::string& buffer, const char* fmt, Args... args )
  {

    std::string fmtstr = std::string(fmt);
    fmtstr+="%n";
    nchars=-1;

    int nargswritten = std::sscanf(buffer.c_str(), fmtstr.c_str(), args...,  &nchars);

    fprintf( stdout, "I consumed [%d] chars\n", nchars );


    //REV: This won't work if it goes past EOF, so  need to handle how many were written if conspos wasn't filled becuase
    //it hit EOF partway through...
    return (nargswritten-1); //REV: subtracting one because of added %n

  }
rveale
  • 66
  • 1
  • 10