embed loops in scanf function? Is it possible?

Started by
4 comments, last by siliconsurfer 18 years, 6 months ago
Hi, in short I would like to pass a dynamic number of parameters to scanf, why? Because sometimes in some programs I want to read files with four fields, and other times I want read files with three fields, sometimes they are strings, sometimes they are ints. Now forgetting the problems assocaited with storing data in strings, or int's. Is it possible to embed a loop in scanf, so it cycles through pointers to store the data i.e say I have a file with the following data on each line:- --------- #firstName secondName address age dave jones belfast 22 --------- So i would create a formatString to pass to scanf. char formatString[] = "\%s \%s \%s \%d"; now after reading a line into a buffer how can I pass say four arguments to scanf, without implicitly coding four arguments in? could I write something like:- char fName[32]; char sName[32]; char address[32]; char *array[3]; array[0]=&fName array[1]=&sName array[2]=&address scanf(buffer, formatString, for(int i=0;i<3;i++){array}, &age); Any thoughts, suggestions on how to achive this or something simliar?
Advertisement
Second thoughts, is it possible to just declare an array of char pointers, and pass that in, will scanf create the data on the heap, and assign the address to each pointer in the array?
C or C++? The equivalent is easy to write in C++ (using streams). I don't think it's actually possible in pure C without either a) preprocessor metaprogramming to create a large number of similar functions with similar names (if this is even possible), b) restricting the problem to a small number of example cases or c) writing your own scanf function from scratch with a non-standard array conversion character.

Enigma
C++

I used scanf, because I was famliar with the function, but if you could point me to an example using streams, or a better way then please do.

I'm assuming you mean sscanf not scanf, since you're passing a buffer argument.

literal version of your request:
#include <iostream>#include <sstream>#include <string>#include <vector>template < typename CharT, typename CharTraitsT, typename TYPE >std::basic_istream< CharT, CharTraitsT > & operator>>(std::basic_istream< CharT, CharTraitsT > & stream, std::vector< TYPE * > & vector){	for (std::vector< TYPE * >::iterator element = vector.begin(), end = vector.end(); element != end; ++element)	{		stream >> **element;	}	return stream;}struct Person{	std::string givenName;	std::string surname;	std::string address;	unsigned int age;};int main(){	std::string buffer = "dave jones belfast 22";	Person person;	std::vector< std::string * > array;	array.push_back(&person.givenName);	array.push_back(&person.surname);	array.push_back(&person.address);	std::istringstream stream(buffer);	stream >> array >> person.age;	std::cout << person.givenName << '\n' << person.surname << '\n' << person.address << '\n' << person.age << '\n';}

better version:
#include <iostream>#include <sstream>#include <string>struct Person{	std::string givenName;	std::string surname;	std::string address;	unsigned int age;};template < typename CharT, typename CharTraitsT >std::basic_istream< CharT, CharTraitsT > & operator>>(std::basic_istream< CharT, CharTraitsT > & stream, Person & person){	stream >> person.givenName >> person.surname >> person.address >> person.age;	return stream;}int main(){	std::string buffer = "dave jones belfast 22";	Person person;	std::istringstream stream(buffer);	stream >> person;	std::cout << person.givenName << '\n' << person.surname << '\n' << person.address << '\n' << person.age << '\n';}

Of course there's no need to read via a buffer. You can just read from the source input stream directly into the target object (you could do this in C too by using fscanf/scanf).

Enigma
Cheers, that's great... Pretty much exactly what I wanted.

This topic is closed to new replies.

Advertisement