473,378 Members | 1,721 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

Question about va_list

I've got following program encapsuled fscanf, however, it doesn't
work.
I'm sure that the content format in "a.txt" is OK, the content would
be correctly read if using fscanf directly, what's wrong with my
program? Thanks for help!

int vsscanf( FILE* fp, const char *fmt, ... )
{
va_list arglist;
va_start( arglist, fmt );
return fscanf(fp, fmt, arglist);
}

int main()
{
FILE* fp = fopen( "C:\\a.txt", "r" );
if( fp == 0 )
{
printf( "%s\n", "Open File Error!" );
exit(-1);
}

char buffer[128];
char buffer2[128];
memset( buffer, 0, 128 );
vsscanf( fp, "%s\n", buffer );
printf( "%s\n", buffer );

return 1;
}
Jan 7 '08 #1
8 2747
Fred wrote:
I've got following program encapsuled fscanf, however, it doesn't
work.
I'm sure that the content format in "a.txt" is OK, the content would
be correctly read if using fscanf directly, what's wrong with my
program? Thanks for help!

int vsscanf( FILE* fp, const char *fmt, ... )
{
va_list arglist;
va_start( arglist, fmt );
return fscanf(fp, fmt, arglist);
}
A few problems:
- no va_end
- wrong argument list to fscanf after fmt.
It just /may/ happen by chance and in some compilers that it would work,
e.g. if va_list is a bunch on stack, and fp and fmt passed in registers.
But in most cases it won't.

However, what you have as a type of vsscanf seems to exist already under
the name of fscanf...
Presumably, you wanted to write the opposite, like
int vfscanf(FILE *fp, const char *fmt, va_list arglist);
That is accomplished easily - by modifying a source of your fscanf().
But why would you need it?

- Ark
Jan 7 '08 #2
Fred <hn********@gmail.comwrites:
I've got following program encapsuled fscanf, however, it doesn't
work.
You say "it doesn't work". How exactly doesn't it work? What results
did you get, what did you expect, and how did they differ?

Recommended reading:
<http://www.catb.org/~esr/faqs/smart-questions.html>.
I'm sure that the content format in "a.txt" is OK, the content would
be correctly read if using fscanf directly, what's wrong with my
program? Thanks for help!
It's difficult to be certain, because you didn't show us your complete
program. Presumably you have #include directives for at least
<stdio.hand <stdarg.h>. You *should* also have #includes for
<string.hand <stdlib.h>.
int vsscanf( FILE* fp, const char *fmt, ... )
{
va_list arglist;
va_start( arglist, fmt );
return fscanf(fp, fmt, arglist);
}

int main()
Slightly better: "int main(void)".
{
FILE* fp = fopen( "C:\\a.txt", "r" );
if( fp == 0 )
{
printf( "%s\n", "Open File Error!" );
exit(-1);
Minor quibble: "exit(-1)" is non-portable. The only portable
arguments to exit() are 0, EXIT_SUCCESS, and EXIT_FAILURE.
}

char buffer[128];
char buffer2[128];
You never use this.
memset( buffer, 0, 128 );
Why the memset?
vsscanf( fp, "%s\n", buffer );
printf( "%s\n", buffer );

return 1;
See "Minor quibble" above. Why not "return 0;"?
}
The real problem is that you're trying to pass a va_list to fscanf().
In this particular call, the format argument is "%s\n", which means
the third argument should be a char*, not a va_list.

You're probably looking for vfscanf(). What you're trying to do in
this program is equivalent to just calling fscanf() directly, but
presumably you're going to do some more stuff in your vsscanf().

Incidentally, fscanf() with a "%s" format is potentially dangerous,
unless you can be sure that the input won't overflow your buffer.
(scanf() with a "%s" format is even more dangerous, since you
generally don't have complete control over what will appear on stdin.)

--
Keith Thompson (The_Other_Keith) <ks***@mib.org>
[...]
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Jan 7 '08 #3
On Jan 7, 2:57 pm, Keith Thompson <ks...@mib.orgwrote:
Fred <hn.ft.p...@gmail.comwrites:
I've got following program encapsuled fscanf, however, it doesn't
work.

You say "it doesn't work". How exactly doesn't it work? What results
did you get, what did you expect, and how did they differ?

Recommended reading:
<http://www.catb.org/~esr/faqs/smart-questions.html>.
I'm sure that the content format in "a.txt" is OK, the content would
be correctly read if using fscanf directly, what's wrong with my
program? Thanks for help!

It's difficult to be certain, because you didn't show us your complete
program. Presumably you have #include directives for at least
<stdio.hand <stdarg.h>. You *should* also have #includes for
<string.hand <stdlib.h>.
int vsscanf( FILE* fp, const char *fmt, ... )
{
va_list arglist;
va_start( arglist, fmt );
return fscanf(fp, fmt, arglist);
}
int main()

Slightly better: "int main(void)".
{
FILE* fp = fopen( "C:\\a.txt", "r" );
if( fp == 0 )
{
printf( "%s\n", "Open File Error!" );
exit(-1);

Minor quibble: "exit(-1)" is non-portable. The only portable
arguments to exit() are 0, EXIT_SUCCESS, and EXIT_FAILURE.
}
char buffer[128];
char buffer2[128];

You never use this.
memset( buffer, 0, 128 );

Why the memset?
vsscanf( fp, "%s\n", buffer );
printf( "%s\n", buffer );
return 1;

See "Minor quibble" above. Why not "return 0;"?
}

The real problem is that you're trying to pass a va_list to fscanf().
In this particular call, the format argument is "%s\n", which means
the third argument should be a char*, not a va_list.

You're probably looking for vfscanf(). What you're trying to do in
this program is equivalent to just calling fscanf() directly, but
presumably you're going to do some more stuff in your vsscanf().

Incidentally, fscanf() with a "%s" format is potentially dangerous,
unless you can be sure that the input won't overflow your buffer.
(scanf() with a "%s" format is even more dangerous, since you
generally don't have complete control over what will appear on stdin.)

--
Keith Thompson (The_Other_Keith) <ks...@mib.org>
[...]
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Thanks for help. Maybe I'm not making myself clear. vfscanf() seems to
be a GNU extension, however, I'm under win32. I've searched MSDN and
find solutions like following:

void vfscanf_c( FILE* fp, u_int argNum, const char *format, ...)
{

#define SCANF_MAX_ARGS 10
va_list arglist;
void *args[SCANF_MAX_ARGS];
u_int numScanned;

if( argNum SCANF_MAX_ARGS )
throw "Too much args!";

va_start( arglist, format );
{
for ( u_int i=0; i<argNum; i++ )
{
args[i] = va_arg( arglist, void* );
}
}
va_end( arglist );

numScanned = fscanfWrapper( fp, argNum, format, args );

if( numScanned != argNum )
throw "Fscanf args Error!";

}

u_int fscanfWrapper( FILE* fp, u_int argNum, const char*format, void**
p )
{
#define ADD_ARGS_1 p[0]
#define ADD_ARGS_2 ADD_ARGS_1, p[1]
#define ADD_ARGS_3 ADD_ARGS_2, p[2]
#define ADD_ARGS_4 ADD_ARGS_3, p[3]
#define ADD_ARGS_5 ADD_ARGS_4, p[4]
#define ADD_ARGS_6 ADD_ARGS_5, p[5]
#define ADD_ARGS_7 ADD_ARGS_6, p[6]
#define ADD_ARGS_8 ADD_ARGS_7, p[7]
#define ADD_ARGS_9 ADD_ARGS_8, p[8]
#define ADD_ARGS_10 ADD_ARGS_9, p[9]

switch ( argNum )
{
case 0: return 0;
case 1: return fscanf( fp, format, ADD_ARGS_1 );
case 2: return fscanf( fp, format, ADD_ARGS_2 );
case 3: return fscanf( fp, format, ADD_ARGS_3 );
case 4: return fscanf( fp, format, ADD_ARGS_4 );
case 5: return fscanf( fp, format, ADD_ARGS_5 );
case 6: return fscanf( fp, format, ADD_ARGS_6 );
case 7: return fscanf( fp, format, ADD_ARGS_7 );
case 8: return fscanf( fp, format, ADD_ARGS_8 );
case 9: return fscanf( fp, format, ADD_ARGS_9 );
case 10: return fscanf( fp, format, ADD_ARGS_10 );
default:
throw "Too much args in fscanf!";
return -1;
}
}

There're some C++ characteristic there, let's neglectthem and just
focus on the method. I've run some test and find it just fine.
Jan 7 '08 #4
Fred wrote:
....
Thanks for help. Maybe I'm not making myself clear. vfscanf() seems to
be a GNU extension, however, I'm under win32. I've searched MSDN and
find solutions like following:
No, vfscanf() is part of the C standard library. I'm not sure whether it
was part of C90, but it's specified in section 7.19.6.9 of the current
standard.
Jan 7 '08 #5
James Kuyper <ja*********@verizon.netwrites:
Fred wrote:
...
>Thanks for help. Maybe I'm not making myself clear. vfscanf() seems to
be a GNU extension, however, I'm under win32. I've searched MSDN and
find solutions like following

No, vfscanf() is part of the C standard library. I'm not sure whether it
was part of C90, but it's specified in section 7.19.6.9 of the current
standard.
It was not in C90 (the vprintf family were, but for some reason not
the vscanf family) and so it is probably not available with MS
compilers (the OP seems to MS-based).

--
Ben.
Jan 7 '08 #6
Fred <hn********@gmail.comwrites:
On Jan 7, 2:57 pm, Keith Thompson <ks...@mib.orgwrote:
>Fred <hn.ft.p...@gmail.comwrites:
I've got following program encapsuled fscanf, however, it doesn't
work.
<snip>
int vsscanf( FILE* fp, const char *fmt, ... )
{
va_list arglist;
va_start( arglist, fmt );
return fscanf(fp, fmt, arglist);
}
<snip>
>You're probably looking for vfscanf(). What you're trying to do in
this program is equivalent to just calling fscanf() directly, but
presumably you're going to do some more stuff in your vsscanf().
<snip>
>--
Keith Thompson (The_Other_Keith) <ks...@mib.org>
[...]
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
Please don't quote sigs (the bits after the "-- "). In fact, try to
remove as much quoted text as possible to leave a message that stands
on its own (for example, I've left the gist of your question and Keith
Thompson's key point intact but removed as much of the rest as I can).
Thanks for help. Maybe I'm not making myself clear. vfscanf() seems to
be a GNU extension, however, I'm under win32.
No, vfscanf is standard C. It is, however, only in the latest
standard (C99) and MS have decided not to implement this. One
solution is to switch to a compiler and C library that supports it.
If that is too troublesome, you could try to find a C99 library (or at
least one with vfscanf) that works with your compiler. Posting in an
MS programming group might help you find one.
I've searched MSDN and find solutions like following

void vfscanf_c( FILE* fp, u_int argNum, const char *format, ...)
{

#define SCANF_MAX_ARGS 10
va_list arglist;
void *args[SCANF_MAX_ARGS];
u_int numScanned;

if( argNum SCANF_MAX_ARGS )
throw "Too much args!";

va_start( arglist, format );
{
for ( u_int i=0; i<argNum; i++ )
{
args[i] = va_arg( arglist, void* );
}
}
va_end( arglist );

numScanned = fscanfWrapper( fp, argNum, format, args );

if( numScanned != argNum )
throw "Fscanf args Error!";

}

u_int fscanfWrapper( FILE* fp, u_int argNum, const char*format, void**
p )
{
#define ADD_ARGS_1 p[0]
#define ADD_ARGS_2 ADD_ARGS_1, p[1]
#define ADD_ARGS_3 ADD_ARGS_2, p[2]
#define ADD_ARGS_4 ADD_ARGS_3, p[3]
#define ADD_ARGS_5 ADD_ARGS_4, p[4]
#define ADD_ARGS_6 ADD_ARGS_5, p[5]
#define ADD_ARGS_7 ADD_ARGS_6, p[6]
#define ADD_ARGS_8 ADD_ARGS_7, p[7]
#define ADD_ARGS_9 ADD_ARGS_8, p[8]
#define ADD_ARGS_10 ADD_ARGS_9, p[9]

switch ( argNum )
{
case 0: return 0;
case 1: return fscanf( fp, format, ADD_ARGS_1 );
case 2: return fscanf( fp, format, ADD_ARGS_2 );
case 3: return fscanf( fp, format, ADD_ARGS_3 );
case 4: return fscanf( fp, format, ADD_ARGS_4 );
case 5: return fscanf( fp, format, ADD_ARGS_5 );
case 6: return fscanf( fp, format, ADD_ARGS_6 );
case 7: return fscanf( fp, format, ADD_ARGS_7 );
case 8: return fscanf( fp, format, ADD_ARGS_8 );
case 9: return fscanf( fp, format, ADD_ARGS_9 );
case 10: return fscanf( fp, format, ADD_ARGS_10 );
default:
throw "Too much args in fscanf!";
return -1;
}
}

There're some C++ characteristic there, let's neglectthem and just
focus on the method. I've run some test and find it just fine.
Yuck. If it suits you, then fine, but it would break on at least one
machine I've used.

--
Ben.
Jan 7 '08 #7
Fred wrote:
On Jan 7, 2:57 pm, Keith Thompson <ks...@mib.orgwrote:
>Fred <hn.ft.p...@gmail.comwrites:
>>I've got following program encapsuled fscanf, however, it doesn't
work.
You say "it doesn't work". How exactly doesn't it work? What results
did you get, what did you expect, and how did they differ?

Recommended reading:
<http://www.catb.org/~esr/faqs/smart-questions.html>.
>>I'm sure that the content format in "a.txt" is OK, the content would
be correctly read if using fscanf directly, what's wrong with my
program? Thanks for help!
It's difficult to be certain, because you didn't show us your complete
program. Presumably you have #include directives for at least
<stdio.hand <stdarg.h>. You *should* also have #includes for
<string.hand <stdlib.h>.
>>int vsscanf( FILE* fp, const char *fmt, ... )
{
va_list arglist;
va_start( arglist, fmt );
return fscanf(fp, fmt, arglist);
}
int main()
Slightly better: "int main(void)".
>>{
FILE* fp = fopen( "C:\\a.txt", "r" );
if( fp == 0 )
{
printf( "%s\n", "Open File Error!" );
exit(-1);
Minor quibble: "exit(-1)" is non-portable. The only portable
arguments to exit() are 0, EXIT_SUCCESS, and EXIT_FAILURE.
>> }
char buffer[128];
char buffer2[128];
You never use this.
>> memset( buffer, 0, 128 );
Why the memset?
>> vsscanf( fp, "%s\n", buffer );
printf( "%s\n", buffer );
return 1;
See "Minor quibble" above. Why not "return 0;"?
>>}
The real problem is that you're trying to pass a va_list to fscanf().
In this particular call, the format argument is "%s\n", which means
the third argument should be a char*, not a va_list.

You're probably looking for vfscanf(). What you're trying to do in
this program is equivalent to just calling fscanf() directly, but
presumably you're going to do some more stuff in your vsscanf().

Incidentally, fscanf() with a "%s" format is potentially dangerous,
unless you can be sure that the input won't overflow your buffer.
(scanf() with a "%s" format is even more dangerous, since you
generally don't have complete control over what will appear on stdin.)

Thanks for help. Maybe I'm not making myself clear. vfscanf() seems to
be a GNU extension, however, I'm under win32. I've searched MSDN and
find solutions like following:

void vfscanf_c( FILE* fp, u_int argNum, const char *format, ...)
{

#define SCANF_MAX_ARGS 10
va_list arglist;
void *args[SCANF_MAX_ARGS];
u_int numScanned;

if( argNum SCANF_MAX_ARGS )
throw "Too much args!";

va_start( arglist, format );
{
for ( u_int i=0; i<argNum; i++ )
{
args[i] = va_arg( arglist, void* );
}
}
va_end( arglist );

numScanned = fscanfWrapper( fp, argNum, format, args );

if( numScanned != argNum )
throw "Fscanf args Error!";

}

u_int fscanfWrapper( FILE* fp, u_int argNum, const char*format, void**
p )
{
#define ADD_ARGS_1 p[0]
#define ADD_ARGS_2 ADD_ARGS_1, p[1]
#define ADD_ARGS_3 ADD_ARGS_2, p[2]
#define ADD_ARGS_4 ADD_ARGS_3, p[3]
#define ADD_ARGS_5 ADD_ARGS_4, p[4]
#define ADD_ARGS_6 ADD_ARGS_5, p[5]
#define ADD_ARGS_7 ADD_ARGS_6, p[6]
#define ADD_ARGS_8 ADD_ARGS_7, p[7]
#define ADD_ARGS_9 ADD_ARGS_8, p[8]
#define ADD_ARGS_10 ADD_ARGS_9, p[9]

switch ( argNum )
{
case 0: return 0;
case 1: return fscanf( fp, format, ADD_ARGS_1 );
case 2: return fscanf( fp, format, ADD_ARGS_2 );
case 3: return fscanf( fp, format, ADD_ARGS_3 );
case 4: return fscanf( fp, format, ADD_ARGS_4 );
case 5: return fscanf( fp, format, ADD_ARGS_5 );
case 6: return fscanf( fp, format, ADD_ARGS_6 );
case 7: return fscanf( fp, format, ADD_ARGS_7 );
case 8: return fscanf( fp, format, ADD_ARGS_8 );
case 9: return fscanf( fp, format, ADD_ARGS_9 );
case 10: return fscanf( fp, format, ADD_ARGS_10 );
default:
throw "Too much args in fscanf!";
return -1;
}
}

There're some C++ characteristic there, let's neglectthem and just
focus on the method. I've run some test and find it just fine.
I'm confused. You've got some example C++ code which can be trivially
translated into C. You say that you find it just fine. In that case, why
don't you use it?

What was wrong with Keith's answer to your original question?
Jan 7 '08 #8
Fred wrote:
>
.... snip ...
>
Thanks for help. Maybe I'm not making myself clear. vfscanf()
seems to be a GNU extension, however, I'm under win32. I've
searched MSDN and find solutions like following
No, vfscanf is standard C. If missing on your compiler, the
compiler has failed. Complain to the compiler manufacturer. The
following is from N869:

7.19.6.9 The vfscanf function

Synopsis

[#1]
#include <stdarg.h>
#include <stdio.h>
int vfscanf(FILE * restrict stream,
const char * restrict format,
va_list arg);
Description

[#2] The vfscanf function is equivalent to fscanf, with the
variable argument list replaced by arg, which shall have
been initialized by the va_start macro (and possibly
subsequent va_arg calls). The vfscanf function does not
invoke the va_end macro.231)

Returns

[#3] The vfscanf function returns the value of the macro EOF
if an input failure occurs before any conversion.
Otherwise, the vfscanf function returns the number of input
items assigned, which can be fewer than provided for, or
even zero, in the event of an early matching failure.

____________________

231As the functions vfprintf, vfscanf, vprintf, vscanf,
vsnprintf, vsprintf, and vsscanf invoke the va_arg macro,
the value of arg after the return is indeterminate.

--
Chuck F (cbfalconer at maineline dot net)
<http://cbfalconer.home.att.net>
Try the download section.

--
Posted via a free Usenet account from http://www.teranews.com

Jan 8 '08 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

6
by: Peter | last post by:
-------------------------------------------------------------------------------- Hi, I was wondering if we can create a va_list by adding objects in the va_list instead of passing in the...
3
by: Douwe | last post by:
I try to build my own version of printf which just passes all arguments to the original printf. As long as I keep it with the single argument version everything is fine. But their is also a version...
11
by: thierrydollar | last post by:
Hi, I have written a very simple program using variable arguments calls and I get strange things that I cannot explain. I have one function (add) that displays two parameters. It works well...
2
by: Rick Anderson | last post by:
I want to store a "va_list" in a structure (which gets passed around from function to function). I cannot use the va_copy() routine to create a copy of the varargs (it looks like it uses stack...
1
by: skillzero | last post by:
Is there a portable way to pass a va_list as a parameter to another function taking a variable argument list? I have a function that takes a printf-like format string and I'd like to use...
6
by: junky_fellow | last post by:
Hi, I want to define a function log_file(), that would print the formatted message to stdout if the FILE pointer passed is NULL else print the formatted output to the file corresponding to...
29
by: Bill Cunningham | last post by:
I wrote this small program to read a 512 block of binary data and write the same to a file. My code compiled well. The only thing is when I ran the compilers binary instead of a data file of 512...
5
by: =?ISO-8859-1?Q?Tom=E1s_=D3_h=C9ilidhe?= | last post by:
On Jun 3, 3:23am, Jesse Ziser <d...@spam.diewrote: The relevant paragraph from the Standard is: ---- Begin Quote ---- The type declared is va_list which is an object type suitable for...
1
by: Chuck Chopp | last post by:
I have some code that is being built on the following: Windows Server 2003, both 32-bit & 64-bit editions Windows Vista, both 32-bit & 64-bit editions Windows Server 2008, both 32-bit & 64-bit...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.