function returning two values

Discussion in 'C++' started by arnuld, Aug 13, 2007.

  1. arnuld

    arnuld Guest

    /* 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)
     
    arnuld, Aug 13, 2007
    #1
    1. Advertising

  2. arnuld

    Ian Collins Guest

    arnuld wrote:

    <snip>
    >
    > 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!

    --
    Ian Collins.
     
    Ian Collins, Aug 13, 2007
    #2
    1. Advertising

  3. arnuld

    arnuld Guest

    > On Aug 13, 1:09 pm, Ian Collins <> wrote:

    > 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;
    }
     
    arnuld, Aug 13, 2007
    #3
  4. arnuld

    Guest

    On Aug 13, 5:05 pm, arnuld <> wrote:
    > 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
     
    , Aug 13, 2007
    #4
  5. arnuld

    arnuld Guest

    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 ?
     
    arnuld, Aug 13, 2007
    #5
  6. arnuld

    Ian Collins Guest

    arnuld wrote:
    > 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!

    --
    Ian Collins.
     
    Ian Collins, Aug 13, 2007
    #6
  7. arnuld

    arnuld Guest

    > On Aug 13, 1:40 pm, arnuld <> wrote:
    > i changed code to this:


    > ........[SNIP].......


    > WHAT IS THIS ?


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

    BTW, when i try to print "write_temp", i always get 0 (zero).. ???
     
    arnuld, Aug 13, 2007
    #7
  8. arnuld

    James Kanze Guest

    On Aug 13, 10:05 am, arnuld <> wrote:

    > /* 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.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Aug 13, 2007
    #8
  9. On 2007-08-13 10:42, arnuld wrote:
    >> On Aug 13, 1:40 pm, arnuld <> wrote:
    >> 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.

    --
    Erik Wikström
     
    =?ISO-8859-1?Q?Erik_Wikstr=F6m?=, Aug 13, 2007
    #9
  10. arnuld

    arnuld Guest

    On Aug 13, 2:42 pm, Erik Wikström <> wrote:
    > On 2007-08-13 10:42, arnuld wrote:
    >
    > >> On Aug 13, 1:40 pm, arnuld <> wrote:
    > >> 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;
    }
     
    arnuld, Aug 13, 2007
    #10
  11. arnuld

    Jerry Coffin Guest

    In article <>,
    says...

    [ ... ]

    > 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'.

    --
    Later,
    Jerry.

    The universe is a figment of its own imagination.
     
    Jerry Coffin, Aug 25, 2007
    #11
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jorgen Gustafsson
    Replies:
    4
    Views:
    584
    Jorgen Gustafsson
    Dec 12, 2003
  2. =?ISO-8859-1?Q?Mattias_Br=E4ndstr=F6m?=

    Two pointers to the same obejct, two differnet values...

    =?ISO-8859-1?Q?Mattias_Br=E4ndstr=F6m?=, Dec 18, 2003, in forum: C++
    Replies:
    3
    Views:
    289
    Jumbo
    Dec 18, 2003
  3. Materialised

    Returning values from a function

    Materialised, Oct 20, 2003, in forum: C Programming
    Replies:
    43
    Views:
    926
    Jerry Coffin
    Oct 23, 2003
  4. GenxLogic
    Replies:
    3
    Views:
    1,289
    andrewmcdonagh
    Dec 6, 2006
  5. Replies:
    6
    Views:
    372
Loading...

Share This Page