0

I am sorry to bother S.O. with such a general request for information.

I can find plenty of very terminology-heavy definitions of vscanf - but I can't find much in the way of concrete examples which will show what is being returned from the function, other than this quite nice one on the IBM infocenter site:

http://pic.dhe.ibm.com/infocenter/iseries/v7r1m0/index.jsp?topic=%2Frtref%2Fvscanf.htm

However this example is only for a one-line string input, whereas I am trying to do the same thing, but reading from a .txt file with multiple lines.

Do I have to use fgets() to read a line at a time and then use vscanf? Do I have to utilise it inside a function, the way that the IBM infocenter example does, by putting it inside a function vread()?

I am a first-year CS student, but this is not a question for an assignment, I am just trying to do some extra work and expand my knowledge, and we haven't got to vread/vscanf yet.

Should I just stick to using sscanf? My apologies if this is as stupid as that.

P.S. I love learning C. Most fun I have had as a student in my 31 years on this planet, apart from when I did a Shakespeare workshop with some people from the RSC once.

Benjamin R
  • 555
  • 6
  • 25
  • 1
    Welcome to Stack Overflow. Please read the [FAQ] soon. The `vread()` function is not a part of C99 (or POSIX). You can find information about [`vscanf()`](http://pubs.opengroup.org/onlinepubs/9699919799/functions/vscanf.html) at the POSIX web site. The return value is the same as for any other `scanf()` family function; the number of successful conversion-assignments. – Jonathan Leffler Jun 10 '13 at 05:31
  • Oh okay, so it just works like sscanf... Thank you for the link, but is there any way you can dumb it down for me a little bit? I assume you mean the same, "except that instead of being called with a variable number of arguments, they are called with an argument list as defined in the header." – Benjamin R Jun 10 '13 at 05:37
  • 1
    If you don't know how to use variable-length argument lists in the first place, it is unlikely that you should be trying to use `vfscanf()`. I've never needed it in just under 30 years of C programming. I know how to use it, but I've never been in a position where it made sense to do so; indeed, I'm not sure I can devise a scenario where it makes sense. (Incidentally, `vread()` is unknown to Google.) Do you know how to use `vfprintf()`? Do you know how to use `fscanf()`? Synthesizing those two pieces of knowledge into using `vscanf()` et al is basically straight-forward. – Jonathan Leffler Jun 10 '13 at 05:46
  • I do know fscanf(), yes sir. vread() is clearly just the function that the IBM guys/gals used to implement vscanf cleanly, it's actually quite fascinating now that I understand how they have utilised it. I will look up vfprintf to help me understand it. I do apologise if this is a stupid enquiry. – Benjamin R Jun 10 '13 at 05:51
  • 1
    The `vread()` function in the code at the IBM URL is just an illustration function; a vehicle to show one way of using `vscanf()`. The code demonstrates one of the problems; you have to know, somehow, how many values should be converted to know whether there's an error or not. The example `main()` function knows it passed a format that converts 4 values and 4 appropriate pointers, so it is able to check the return from `vscanf()` via `vread()`. There's no benefit in the example code compared with calling `scanf()` directly, but it shows the mechanism that would be needed. – Jonathan Leffler Jun 10 '13 at 05:56

2 Answers2

2

vscanf is like scanf, not sscanf or fscanf. It differs from scanf in that scanf takes a variable number of arguments, whereas vscanf takes a va_list argument that acts as a pointer to a variable argument list. The use of vscanf is rare; it's mostly there for completeness (uses of vprintf are more common). A possible example of a use for vscanf is if you had a large number of scanf calls with different arguments, and on each occasion it takes some error action -- the same error action -- if scanf can't read all its arguments. Then you could write a scanf_and_check_for_error function that takes variable arguments just like scanf does, with the addition of a count argument that is the expected return value of scanf, passes the argument list to vscanf, checks its return value and takes the error action if the return value is wrong. e.g.,

void scanf_and_check(int count, char *fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    int rc = vscanf(fmt, ap);
    if (rc != count)
    {
        ErrorMessageBox("Bad input. This program employs a radical form of the fail-fast principle ... exiting!");
        exit(1);
    }
    va_end(ap);
}
Jim Balter
  • 16,163
  • 3
  • 43
  • 66
0

Without being too unhelpful, I suspect you may be trying the wrong tool for the job. vscanf is intended to be used when developing "front-ends" to the scanf family, and is a very "low-level" tool.

You probably want to use fscanf. In case you really want to use the vscanf logic (with all its va_list ugliness), take a look at vfscanf (linked in your example)

Norwæ
  • 1,575
  • 8
  • 18
  • Not unhelpful at all, sir... Like I say, I know basically nothing. That is actually a very helpful piece of info. It's helping me put together an understanding of what vscanf is, although clearly right now I should just stick with fgets() and sscanf() or just use fscanf()... I might even be able to use fgetc() too. – Benjamin R Jun 10 '13 at 05:46