Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > C++ Primer exercise 3.13

Reply
Thread Tools

C++ Primer exercise 3.13

 
 
arnuld
Guest
Posts: n/a
 
      07-19-2007
i have solved the problem but it is quite length. as usual, i wanted some
coding-standards or good-design opinions:


/* C++ Primer 4/e
* chapter 3 - Library Types

* exercise 3.13
* STAMEMENT
* read a set of integers into the vector. calculate and print the
sum of each * pair of adjacent elements of the vector. If there is an odd
number then tell the * user about it and print the value of the last
element without summing it. *
*/


#include <iostream>
#include <vector>

int main()
{
std::vector<int> ivec; /* empty vector */

int ivec_limit = 11;
for(int i = 5; i != ivec_limit; ++i) /* inserts itegers */
ivec.push_back(i);

/* now we will print the elements of vector */ std::cout << "These are
the elements of vector:\t"; for(std::vector<int>::const_iterator
iter=ivec.begin(); iter != ivec.end(); ++iter)
{
std::cout << *iter << " ";
}

std::cout << std::endl;
/* actual programme */
for(std::vector<int>::iterator iter = ivec.begin(); iter != ivec.end();
++iter)
{
if((*iter % 2) != 0)
{
std::cout << "\n"
<< *iter
<< " is an odd number"
<< " not adding it to the total."
<< std::endl;
if(iter == ivec.begin())
{
std::cout << *iter
<< " is the 1st element of vector"
<< std::endl;
}
else
{
std::cout << "--> last element was: "
<< *(iter - 1)
<< std::endl;
}
}
else
{
if((iter + 1) == ivec.end())
{
std::cout << "\nLast element of vector is: "
<< *iter
<< std::endl;
}
else
{
std::cout << "\nAdjacent elements are: "
<< *iter
<< " & "
<< *(iter + 1)
<< "\n--> and their sum is: "
<< *iter + *(iter + 1)
<< std::endl;
}
}
}


return 0;
}


===== OUTPUT =============
[arnuld@arch cpp ]% g++ -ansi -pedantic -Wall -Wextra ex_03-13.cpp
[arnuld@arch cpp ]% ./a.out
These are the elements of vector: 5 6 7 8 9 10

5 is an odd number not adding it to the total. 5 is the 1st element of
vector

Adjacent elements are: 6 & 7
--> and their sum is: 13

7 is an odd number not adding it to the total. --> last element was: 6

Adjacent elements are: 8 & 9
--> and their sum is: 17

9 is an odd number not adding it to the total. --> last element was: 8

Last element of vector is: 10
[arnuld@arch cpp ]%



--
-- http://arnuld.blogspot.com

 
Reply With Quote
 
 
 
 
=?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=
Guest
Posts: n/a
 
      07-19-2007
On 2007-07-19 10:35, arnuld wrote:
> i have solved the problem but it is quite length. as usual, i wanted some
> coding-standards or good-design opinions:
>
>
> /* C++ Primer 4/e
> * chapter 3 - Library Types
>
> * exercise 3.13
> * STAMEMENT
> * read a set of integers into the vector. calculate and print the
> sum of each * pair of adjacent elements of the vector. If there is an odd
> number then tell the * user about it and print the value of the last
> element without summing it. *
> */


Sorry, but you have not solved the problem the author intended. First of
you should let the user enter the numbers. Then you should print the sum
of each pair of numbers, but if the user entered an odd number of
numbers you can't sum the last element with another so you you should
just print it:

So an example run could look something like this:
--
Please enter some numbers:
1
2
3
4
5

You entered an odd number of numbers.

The sums of the pairs are:
3
7
5
--
Or like this:
--
Please enter some numbers:
1
2
3
4
5
6

The sums of the pairs are:
3
7
11

--
Erik Wikström
 
Reply With Quote
 
 
 
 
arnuld
Guest
Posts: n/a
 
      07-19-2007
> On Thu, 19 Jul 2007 09:23:21 +0000, Erik Wikström wrote:


> Sorry, but you have not solved the problem the author intended. First of
> you should let the user enter the numbers. Then you should print the sum
> of each pair of numbers, but if the user entered an odd number of
> numbers you can't sum the last element with another so you you should
> just print it:


ok, BTW, i found the statement ambiguous. so i created the programem on
that basis of what it could mean.

> So an example run could look something like this: -- Please enter some
> numbers:
> 1
> 2
> 3
> 4
> 5
>
> You entered an odd number of numbers.
>
> The sums of the pairs are:
> 3
> 7
> 5


sorry, after 1.5 hours of grueling work, my new programme still gives
"segmentatioon fault" on finding an odd list of numbers. for even amount
of numbers this programme works:

#include <iostream>
#include <vector>

int main()
{
std::vector<int> ivec; /* empty vector */ int v_num;

std::cout << "Please enter some numbers: " << std::endl; while(std::cin
>> v_num)

ivec.push_back(v_num);

if((ivec.size() % 2) != 0)
{
std::cout << "oops!, you enetered an odd number of numbers" <<
std::endl;
}

std::cout << "The sum of the pairs are: " << std::endl; /* actual
programme */
for(std::vector<int>::const_iterator iter = ivec.begin(); iter !=
ivec.end(); iter += 2)
{
if((iter + 1) == ivec.end())
{
std::cout << *iter << std::endl;
}
else
{
std::cout << *iter + *(iter + 1) << std::endl;
}
}

return 0;
}


--
-- http://arnuld.blogspot.com

 
Reply With Quote
 
=?UTF-8?B?RXJpayBXaWtzdHLDtm0=?=
Guest
Posts: n/a
 
      07-19-2007
On 2007-07-19 13:41, arnuld wrote:
>> On Thu, 19 Jul 2007 09:23:21 +0000, Erik Wikström wrote:

>
>
>> Sorry, but you have not solved the problem the author intended. First of
>> you should let the user enter the numbers. Then you should print the sum
>> of each pair of numbers, but if the user entered an odd number of
>> numbers you can't sum the last element with another so you you should
>> just print it:

>
> ok, BTW, i found the statement ambiguous. so i created the programem on
> that basis of what it could mean.
>
>> So an example run could look something like this: -- Please enter some
>> numbers:
>> 1
>> 2
>> 3
>> 4
>> 5
>>
>> You entered an odd number of numbers.
>>
>> The sums of the pairs are:
>> 3
>> 7
>> 5

>
> sorry, after 1.5 hours of grueling work, my new programme still gives
> "segmentatioon fault" on finding an odd list of numbers. for even amount
> of numbers this programme works:
>
> #include <iostream>
> #include <vector>
>
> int main()
> {
> std::vector<int> ivec; /* empty vector */ int v_num;
>
> std::cout << "Please enter some numbers: " << std::endl; while(std::cin
> >> v_num)

> ivec.push_back(v_num);
>
> if((ivec.size() % 2) != 0)
> {
> std::cout << "oops!, you enetered an odd number of numbers" <<
> std::endl;
> }
>
> std::cout << "The sum of the pairs are: " << std::endl; /* actual
> programme */
> for(std::vector<int>::const_iterator iter = ivec.begin(); iter !=
> ivec.end(); iter += 2)


Replace the check to a less than (iter < ivec.end()), since you are
increasing the iterator with 2 each step you will step over ivec.end()
if the number of elements is odd..

> {
> if((iter + 1) == ivec.end())
> {
> std::cout << *iter << std::endl;


Or add break; here.

> }
> else
> {
> std::cout << *iter + *(iter + 1) << std::endl;
> }
> }
>
> return 0;
> }


--
Erik Wikström
 
Reply With Quote
 
arnuld
Guest
Posts: n/a
 
      07-19-2007
> On Thu, 19 Jul 2007 12:01:55 +0000, Erik Wikström wrote:

>> On 2007-07-19 13:41, arnuld wrote:
>> for(std::vector<int>::const_iterator iter = ivec.begin(); iter !=
>> ivec.end(); iter += 2)


> Replace the check to a less than (iter < ivec.end()), since you are
> increasing the iterator with 2 each step you will step over ivec.end()
> if the number of elements is odd..


that i never thought of

>> {
>> if((iter + 1) == ivec.end())
>> {
>> std::cout << *iter << std::endl;


> Or add break; here.


this is what i wanted. i supposed and befooled myself into thinking that
since now test is true only this one statement will execute but i forgot
about the for loop



--
-- http://arnuld.blogspot.com

 
Reply With Quote
 
Andre Kostur
Guest
Posts: n/a
 
      07-19-2007
=?UTF-8?B?RXJpayBXaWtzdHLDtm0=?= <Erik-> wrote in
news:ToIni.4399$:

> On 2007-07-19 13:41, arnuld wrote:
>>> On Thu, 19 Jul 2007 09:23:21 +0000, Erik Wikström wrote:

>>
>>
>>> Sorry, but you have not solved the problem the author intended.
>>> First of you should let the user enter the numbers. Then you should
>>> print the sum of each pair of numbers, but if the user entered an
>>> odd number of numbers you can't sum the last element with another so
>>> you you should just print it:

>>
>> ok, BTW, i found the statement ambiguous. so i created the programem
>> on that basis of what it could mean.
>>
>>> So an example run could look something like this: -- Please enter
>>> some numbers:
>>> 1
>>> 2
>>> 3
>>> 4
>>> 5
>>>
>>> You entered an odd number of numbers.
>>>
>>> The sums of the pairs are:
>>> 3
>>> 7
>>> 5

>>
>> sorry, after 1.5 hours of grueling work, my new programme still gives
>> "segmentatioon fault" on finding an odd list of numbers. for even
>> amount of numbers this programme works:
>>
>> #include <iostream>
>> #include <vector>
>>
>> int main()
>> {
>> std::vector<int> ivec; /* empty vector */ int v_num;
>>
>> std::cout << "Please enter some numbers: " << std::endl;
>> while(std::cin
>> >> v_num)

>> ivec.push_back(v_num);
>>
>> if((ivec.size() % 2) != 0)
>> {
>> std::cout << "oops!, you enetered an odd number of numbers" <<
>> std::endl;
>> }
>>
>> std::cout << "The sum of the pairs are: " << std::endl; /* actual
>> programme */
>> for(std::vector<int>::const_iterator iter = ivec.begin(); iter !=
>> ivec.end(); iter += 2)

>
> Replace the check to a less than (iter < ivec.end()), since you are
> increasing the iterator with 2 each step you will step over ivec.end()
> if the number of elements is odd..


Caveat: this is not good general advice. Testing for != end() is better
than testing for < end() as it is how one does the same sort of test for
the other containers. May work for vectors, won't work for the other
containers.

Finally, assuming that the += 2 steps past the end() iterator, isn't it
technically undefined behaviour to make the comparison as you would be
comparing a pointer to an element within an array (one-past-the-end
pointer is still considered to be "within the array") to a pointer that
isn't in the same array (and isn't 0)?

>> {
>> if((iter + 1) == ivec.end())
>> {
>> std::cout << *iter << std::endl;

>
> Or add break; here.


I think this may be a better choice. Then again, I'd probably using
indexing for this instead of iteration (which does pretty much tie me to
vector...). Or perhaps use a while loop instead of a for.

>> }
>> else
>> {
>> std::cout << *iter + *(iter + 1) << std::endl;
>> }
>> }
>>
>> return 0;
>> }

>


 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      07-20-2007
On Jul 19, 2:01 pm, Erik Wikström <Erik-wikst...@telia.com> wrote:
> On 2007-07-19 13:41, arnuld wrote:

[...]
> > #include <iostream>
> > #include <vector>

>
> > int main()
> > {
> > std::vector<int> ivec; /* empty vector */ int v_num;


> > std::cout << "Please enter some numbers: " << std::endl; while(std::cin
> > >> v_num)

> > ivec.push_back(v_num);


> > if((ivec.size() % 2) != 0)
> > {
> > std::cout << "oops!, you enetered an odd number of numbers" <<
> > std::endl;
> > }


> > std::cout << "The sum of the pairs are: " << std::endl; /* actual
> > programme */
> > for(std::vector<int>::const_iterator iter = ivec.begin(); iter !=
> > ivec.end(); iter += 2)


> Replace the check to a less than (iter < ivec.end()), since you are
> increasing the iterator with 2 each step you will step over ivec.end()
> if the number of elements is odd..


That won't work either, since you'll still enter the loop when
there is only one element remaining (and thus add 2, resulting
in undefined behavior). Interpreting the requirements strictly,
I'd use something like:

while ( iter != end && iter + 1 != end ) {
// ...
iter +=2 ;
}
if ( iter != end ) {
// odd number...
}

Interpreting them a bit more loosely, I'd probably use a vector
of std:air< int, int >, and handle the case of an odd number
of elements at input. (In a real world application, I'd
probably require two integers per line, and use getline to
read.)

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

 
Reply With Quote
 
James Kanze
Guest
Posts: n/a
 
      07-20-2007
On Jul 19, 4:14 pm, Andre Kostur <nntps...@kostur.net> wrote:
> =?UTF-8?B?RXJpayBXaWtzdHLDtm0=?= <Erik-wikst...@telia.com> wrote innews:ToIni.4399$:
> > On 2007-07-19 13:41, arnuld wrote:
> >>> On Thu, 19 Jul 2007 09:23:21 +0000, Erik Wikström wrote:


> > Replace the check to a less than (iter < ivec.end()), since
> > you are increasing the iterator with 2 each step you will
> > step over ivec.end() if the number of elements is odd..


> Caveat: this is not good general advice. Testing for != end()
> is better than testing for < end() as it is how one does the
> same sort of test for the other containers. May work for
> vectors, won't work for the other containers.


Agreed, sort of. It's what one expects, and code should provide
the least surprises to the reader. But he needs random access
iterators for the + 1 as well, so the code won't work for other
containers anyway.

> Finally, assuming that the += 2 steps past the end() iterator,
> isn't it technically undefined behaviour to make the
> comparison as you would be comparing a pointer to an element
> within an array (one-past-the-end pointer is still considered
> to be "within the array") to a pointer that isn't in the same
> array (and isn't 0)?


It's not only undefined behavior; it crashes with both g++ and
VC++ when you turn on debugging options. (You should be using
the debugging options whenever possible, especially when
learning. Regretfully, code compiled with the debugging options
is not compatible with code compiled without. The debugging
options have significant runtime overhead, and a bottleneck
anywhere in the application means that you can't use them
anywhere.)

> >> {
> >> if((iter + 1) == ivec.end())
> >> {
> >> std::cout << *iter << std::endl;


> > Or add break; here.


> I think this may be a better choice.


Using a break to leave a loop is NEVER a good choice.

> Then again, I'd probably using indexing for this instead of
> iteration (which does pretty much tie me to vector...). Or
> perhaps use a while loop instead of a for.


There's a very nice solution with a while loop:

while ( iter != ivec.end() ) {
{
int first = *iter ++ ;
if ( iter != ivec.end() ) {
int second = *iter ++ ;
std::cout << first + second << std::endl ;
} else {
std::cout << "odd number of elements, last was: "
<< first << std::endl ;
}
}

I'm not overly enthusiastic about spreading the increments out
all over the loop, but it seems preferable here to the
alternatives. It also avoids the requirement for a random
access iterator, so you can replace vector with just about any
container. (I still rather prefer the idea of using a container
of std:air, however, and handling the odd case at the end of
input.)

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

 
Reply With Quote
 
arnuld
Guest
Posts: n/a
 
      07-20-2007
> On Fri, 20 Jul 2007 08:22:32 +0000, James Kanze wrote:
> Agreed, sort of. It's what one expects, and code should provide the
> least surprises to the reader. But he needs random access iterators for
> the + 1 as well, so the code won't work for other containers anyway.





> It's not only undefined behavior; it crashes with both g++ and VC++ when
> you turn on debugging options. (You should be using the debugging
> options whenever possible, especially when learning. Regretfully, code
> compiled with the debugging options is not compatible with code compiled
> without. The debugging options have significant runtime overhead, and a
> bottleneck anywhere in the application means that you can't use them
> anywhere.)


ok, i have added "-ggdb" to my arsenal


> Using a break to leave a loop is NEVER a good choice.


and i am the one who always believed that "break" was especially created
for the purpose of "breaking out of loop".


> There's a very nice solution with a while loop:
>
> while ( iter != ivec.end() ) {
> {
> int first = *iter ++ ;
> if ( iter != ivec.end() ) {
> int second = *iter ++ ;
> std::cout << first + second << std::endl ;
> } else {
> std::cout << "odd number of elements, last was: "
> << first << std::endl ;
> }
> }
> }
> I'm not overly enthusiastic about spreading the increments out all over
> the loop, but it seems preferable here to the alternatives. It also
> avoids the requirement for a random access iterator, so you can replace
> vector with just about any container. (I still rather prefer the idea
> of using a container of std:air, however, and handling the odd case at
> the end of input.)


James, that is really nice solution, i just loved it . i always thought
that "for" loop is the official loop of C++ (like 'C' is the official
language of GNU, at least to speak) but i see, in this situation "while"
fits much better.


--
-- http://arnuld.blogspot.com

 
Reply With Quote
 
Andre Kostur
Guest
Posts: n/a
 
      07-20-2007
arnuld <> wrote in newsan.2007.07.20.09.46.53.778891
@gmail.com:

>> On Fri, 20 Jul 2007 08:22:32 +0000, James Kanze wrote:


[snip]

>> Using a break to leave a loop is NEVER a good choice.

>
> and i am the one who always believed that "break" was especially created
> for the purpose of "breaking out of loop".


For that, and switch statements. However it is a tool that is easily
misused. By using break you are stepping outside of the expected code
flow. Much like scattering goto's all over your code too. I'm not sure
that "never" is a good word, but it should probably be avoided where
possible.

[snip while solution]

> James, that is really nice solution, i just loved it . i always thought
> that "for" loop is the official loop of C++ (like 'C' is the official
> language of GNU, at least to speak) but i see, in this situation "while"
> fits much better.


There are three looping constructs in C++ language itself... "for",
"while", and "do..while". Learn them all as each one has certain
behaviours and makes them better for various situations. Keep in mind that
each one could be implemented in terms of one of the other ones, but the
syntax would get awkward and you'd only be obscuring your intent. In
addition there are other constructs in the Standard Library that do loop-
like things, such as std::for_each, std::transform, and others.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Answer to C++ Primer 4th edition Exercise 1.20 (in section 1.4.4) mmdspam@googlemail.com C++ 0 05-26-2008 05:41 PM
C++ Primer (5th ed) - Exercise 14.5 Kveldulv C++ 2 10-20-2007 05:14 AM
C++ Primer 4/e exercise 1.19 arnuld C++ 14 07-13-2007 01:52 PM
exercise 3.9, C++ Primer 4/e arnuld C++ 2 10-09-2006 05:03 PM
PC TV Tuner Primer Silverstrand Front Page News 0 10-19-2005 01:47 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57