function returning two values

A

arnuld

/* C++ Primer - 4/e
*
* 1st example from section 7.2.2, page 234
* returning 2 values from a function
*
* STATEMENT:
* to find a specific value in a vector and number of times
* that value occurs in th vector.
*/


#include <iostream>
#include <vector>

/* returns an iterator that refers to the first occurence of
"find_this_value"
the reference paramater "occurs" contains a second return value, the
number of times "find_this_value" occured in the vector
*/
std::vector<int>::const_iterator find_val(
std::vector<int>::const_iterator beg,
std::vector<int>::const_iterator end,
int find_this_value,
std::vector<int>::size_type& occurs)
{
/* res_iter will hold the first occurence, if any */
std::vector<int>::const_iterator res_iter = end;
occurs = 0;

for( ; beg != end; ++beg)
{
if ( *beg == find_this_value )
{
if ( res_iter == end ) /* this will remeber the 1st occurence */
{
res_iter = beg;
}
++occurs;
}
}

return res_iter;
}


int main()
{
std::cout << "enter some numbers to creat a vector : ";
std::vector<int> ivec;
int i;
while(std::cin >> i)
{
ivec.push_back(i);
}

/* clear the input stream */
std::cin.clear();
std::cout << "which numbe you want to find: ";
int find_value;
std::cin >> find_value;

std::vector<int>::const_iterator begin = ivec.begin();
std::vector<int>::const_iterator end = ivec.end();

find_val(begin, end, find_value);

return 0;
}

as expected this function never compiles because function call expects
the 4 arguments whereas 3 are given. but how i am supposed to provide
4th argument when what i want to find out is the 4th argument and the
author says that 4th argument is the 2nd return value. i am confused
on this

(BTW, it seems like circular-dependencies problem of emerge)
 
I

Ian Collins

arnuld wrote:

std::vector<int>::const_iterator begin = ivec.begin();
std::vector<int>::const_iterator end = ivec.end();
std::vector<int>::size_type occurs;

find_val(begin, end, find_value, occurs);
find_val(begin, end, find_value);

return 0;
}

as expected this function never compiles because function call expects
the 4 arguments whereas 3 are given. but how i am supposed to provide
4th argument when what i want to find out is the 4th argument and the
author says that 4th argument is the 2nd return value. i am confused
on this
Just add it!
 
A

arnuld

std::vector<int>::size_type occurs;
.......[SNIP].............

find_val(begin, end, find_value, occurs);
..............[SNIP]................

Just add it!

added, it compiles and runs and i modified last 2 lines of main() to
print the output to terminal but still no luck :(

/* C++ Primer - 4/e
*
* 1st example from section 7.2.2, page 234
* returning 2 values from a function
*
* STATEMENT:
* to find a specific value in a vector and number of times
* that value occurs in th vector.
*/


#include <iostream>
#include <vector>

/* returns an iterator that refers to the first occurence of
"find_this_value"
the reference paramater "occurs" contains a second return value, the
number of times "find_this_value" occured in the vector
*/
std::vector<int>::const_iterator find_val(
std::vector<int>::const_iterator beg,
std::vector<int>::const_iterator end,
int find_this_value,
std::vector<int>::size_type& occurs)
{
/* res_iter will hold the first occurence, if any */
std::vector<int>::const_iterator res_iter = end;
occurs = 0;

for( ; beg != end; ++beg)
{
if ( *beg == find_this_value )
{
if ( res_iter == end ) /* this will remeber the 1st occurence */
{
res_iter = beg;
}
++occurs;
}
}

return res_iter;
}


int main()
{
std::cout << "enter some numbers to creat a vector : ";
std::vector<int> ivec;
int i;
while(std::cin >> i)
{
ivec.push_back(i);
}

/* clear the input stream */
std::cin.clear();
std::cout << "which numbe you want to find: ";
int find_value;
std::cin >> find_value;

std::vector<int>::const_iterator begin = ivec.begin();
std::vector<int>::const_iterator end = ivec.end();

/* a temperaory variable for 4th classic write argument */
std::vector<int>::size_type write_temp = 0;

std::cout << "---------------------------\n";
find_val(begin, end, find_value, write_temp);

std::cout << std::endl;

return 0;
}
 
T

tony_in_da_uk

std::vector<int>::const_iterator find_val(
std::vector<int>::const_iterator beg,
std::vector<int>::const_iterator end,
int find_this_value,
std::vector<int>::size_type& occurs)
{
occurs = 0;
...
[sometimes] ++occurs; < ...
}

how i am supposed to provide
4th argument when what i want to find out is the 4th argument and the
author says that 4th argument is the 2nd return value. i am confused
on this

Unfortunately, C++ doesn't provide any elegant way to "return" ad-hoc
multiple values, especially of different types. You can return
containers, and the containers can hold variants, and there are
templates like std::pair<> that can stitch a couple values together,
but they're all really ugly in different ways. A "return { "string
literal", 3.14 }" notation would be really nice, complemented by
"{ std::string x, int y } = fn();", but it's not available.

Consequently, it's fairly common for function arguments to be non-
const references (or pointers) and the referenced variable to be
modified by the function call. This is pretty ugly when the argument
is not even an input, especially when it's not being done as some kind
of "use my buffer for performance and/or life-time management"
reasons.

Tony
 
A

arnuld

i changed code to this:

/* C++ Primer - 4/e
*
* 1st example from section 7.2.2, page 234
* returning 2 values from a function
*
* STATEMENT:
* to find a specific value in a vector and number of times
* that value occurs in th vector.
*/


#include <iostream>
#include <vector>

/* returns an iterator that refers to the first occurence of
"find_this_value"
the reference paramater "occurs" contains a second return value, the
number of times "find_this_value" occured in the vector
*/
std::vector<int>::const_iterator find_val(
std::vector<int>::const_iterator beg,
std::vector<int>::const_iterator end,
int find_this_value,
std::vector<int>::size_type& occurs)
{
/* res_iter will hold the first occurence, if any */
std::vector<int>::const_iterator res_iter = end;
occurs = 0;

for( ; beg != end; ++beg)
{
if ( *beg == find_this_value )
{
if ( res_iter == end ) /* this will remeber the 1st occurence */
{
res_iter = beg;
}
++occurs;
}
}

return res_iter;
}


int main()
{
std::cout << "enter some numbers to creat a vector : ";
std::vector<int> ivec;
int i;
while(std::cin >> i)
{
ivec.push_back(i);
}

/* clear the input stream */
std::cin.clear();
std::cout << "which numbe you want to find: ";
int find_value;
std::cin >> find_value;

std::vector<int>::const_iterator begin = ivec.begin();
std::vector<int>::const_iterator end = ivec.end();

/* a temperaory variable for 4th classic write argument */
std::vector<int>::size_type write_temp = 0;

std::cout << "---------------------------\n"
<< *find_val( begin, end, find_value, write_temp )
<< std::endl;

return 0;
}


========== OUTPUT ===========
~/programming/cpp $ g++ -ansi -pedantic -Wall -Wextra 7.2.2_return-two-
values.cpp
~/programming/cpp $ ./a.out
enter some numbers to creat a vector : 1 2 3 4 5 5 0 2 3 2 5 9
which numbe you want to find: 2
---------------------------
2
~/programming/cpp $ ./a.out
enter some numbers to creat a vector : 1 2 20 9 8 0 6 20 20 98
which numbe you want to find: 20
---------------------------
20
~/programming/cpp $



WHAT IS THIS ?
 
I

Ian Collins

arnuld said:
std::vector<int>::size_type write_temp = 0;

std::cout << "---------------------------\n";
find_val(begin, end, find_value, write_temp);

std::cout << std::endl;

std::cout << write_temp << std::endl;

It helps if you output the value!
 
J

James Kanze

/* returns an iterator that refers to the first occurence of
"find_this_value"
the reference paramater "occurs" contains a second return value, the
number of times "find_this_value" occured in the vector
*/
std::vector<int>::const_iterator find_val(
std::vector<int>::const_iterator beg,
std::vector<int>::const_iterator end,
int find_this_value,
std::vector<int>::size_type& occurs)
{
/* res_iter will hold the first occurence, if any */
std::vector<int>::const_iterator res_iter = end;
occurs = 0;

for( ; beg != end; ++beg)
{
if ( *beg == find_this_value )
{
if ( res_iter == end ) /* this will remeber the 1st occurence */
{
res_iter = beg;
}
++occurs;
}
}
return res_iter;
}

You seem to have gotten most of it, but I'd certainly consider
defining a structure and returning it:

struct Results
{
std::vector< int >::const_iterator
firstPos ;
size_t count ;
} ;

Results
find_val( // ...

Which solution is more appropriate depends on the actual
application. If you always need both return values, the
structure (or even a full fledged class) is often the most
appropriate. But there are cases where the principal role of
the function is to find one of the values, and the second is
just an added feature. In such cases, it is traditional to use
a pointer for the added feature return value; if the user passes
a null pointer (which can be the default value), you don't
return this additional value.
 
?

=?ISO-8859-1?Q?Erik_Wikstr=F6m?=

i changed code to this:
........[SNIP].......

WHAT IS THIS ?

i mean why i dis not get 2 values as output ?

C++ only allows one return value, however by using references or
pointers you can let the function modify variables in the scope of the
caller, thus simulating more return values.
BTW, when i try to print "write_temp", i always get 0 (zero).. ???

Probably because you are trying to print it like this:

std::cout << "---------------------------\n"
<< *find_val( begin, end, find_value, write_temp )
<< " " << write_temp << std::endl;

The problem with this statement is that the order of evaluation is
unspecified, so write_temp can be evaluated before the call to
find_val(), in which case it will be 0. Make sure to call the function
and print the value of write_temp in two different statements.
 
A

arnuld

i changed code to this:
........[SNIP].......
WHAT IS THIS ?
i mean why i dis not get 2 values as output ?

C++ only allows one return value, however by using references or
pointers you can let the function modify variables in the scope of the
caller, thus simulating more return values.
BTW, when i try to print "write_temp", i always get 0 (zero).. ???

Probably because you are trying to print it like this:

std::cout << "---------------------------\n"
<< *find_val( begin, end, find_value, write_temp )
<< " " << write_temp << std::endl;

The problem with this statement is that the order of evaluation is
unspecified, so write_temp can be evaluated before the call to
find_val(), in which case it will be 0. Make sure to call the function
and print the value of write_temp in two different statements.

you are right, it works. BTW, i changed the last part of code to
this.


/* a temperaory variable for 4th classic write argument */
std::vector<int>::size_type write_temp = 0;

int value_called = *find_val( begin, end, find_value, write_temp );
/* value stored because we will use it more than once */

std::cout << "------------- you are looking for -----------\n"
<< value_called
<< "\n\n";

std::cout << "number of times "
<< value_called
<< " was found: "
<< write_temp
<< std::endl;


return 0;
}
 
J

Jerry Coffin

[ ... ]
You seem to have gotten most of it, but I'd certainly consider
defining a structure and returning it:

struct Results
{
std::vector< int >::const_iterator
firstPos ;
size_t count ;
} ;

When you're dealing with exactly two values, another way to define the
struct would be something like this:

std::pair<std::vector<int>::const_iterator, size_t>

Which is more appropriate will depend on how you're using the returned
value. For one example, std::pair is handy in quite a bit of template
code, because the names of the two members are pre-defined, making it
easier for some code to deal with pairs of essentially any two types.
OTOH, 'x.count' will usually be more informative than 'x.second'.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,733
Messages
2,569,440
Members
44,829
Latest member
PIXThurman

Latest Threads

Top