"ispunct()" not working on std::string

A

arnuld

/* C++ Primer 4/e
* section 3.2 - String Standard Library

* exercise 3.10
* STATEMENT
* write a programme to strip the punctation from the string. */

#include <iostream>
#include <string>

int main()
{
std::cout << "Enter a string: ";
std::string a_word, stripped_word;
std::cin >> a_word;

for(std::string::size_type ix = 0; ix != a_word.size(); ++ix)
{
if(ispunct(a_word[ix]) == 0)
stripped_word[ix] = a_word[ix];
}

std::cout << stripped_word << std::endl;

return 0;
}
 
A

arnuld

/* C++ Primer 4/e
* section 3.2 - String Standard Library

* exercise 3.10
* STATEMENT
* write a programme to strip the punctation from the string. */

#include <iostream>
#include <string>

int main()
{
std::cout << "Enter a string: ";
std::string a_word, stripped_word;
std::cin >> a_word;

for(std::string::size_type ix = 0; ix != a_word.size(); ++ix)
{
if(ispunct(a_word[ix]) == 0)
stripped_word[ix] = a_word[ix];
}

std::cout << stripped_word << std::endl;

return 0;
}


SORRY, i forgot to post the output:

[arnuld@arch cpp ]% g++ -ansi -pedantic -Wall -Wextra ex_03-10.cpp
[arnuld@arch cpp ]% ./a.out
Enter a string: comp.lang.c++

[arnuld@arch cpp ]%


you see, it does not prinit anything at all but it compiled successfully.
where is the bug ?
 
O

Obnoxious User

/* C++ Primer 4/e
* section 3.2 - String Standard Library

* exercise 3.10
* STATEMENT
* write a programme to strip the punctation from the string. */

#include <iostream>
#include <string>

int main()
{
std::cout << "Enter a string: ";
std::string a_word, stripped_word;
std::cin >> a_word;

for(std::string::size_type ix = 0; ix != a_word.size(); ++ix)
{
if(ispunct(a_word[ix]) == 0)
stripped_word[ix] = a_word[ix];

A std::string is not an open array, you can't just assign
to random non-existing positions.

stripped_word += a_word[ix];
or
stripped_word.append(a_word[ix]);
 
A

anon

arnuld said:
/* C++ Primer 4/e
* section 3.2 - String Standard Library

* exercise 3.10
* STATEMENT
* write a programme to strip the punctation from the string. */

#include <iostream>
#include <string>

int main()
{
std::cout << "Enter a string: ";
std::string a_word, stripped_word;
std::cin >> a_word;

for(std::string::size_type ix = 0; ix != a_word.size(); ++ix)
{
if(ispunct(a_word[ix]) == 0)
stripped_word[ix] = a_word[ix];
}

std::cout << stripped_word << std::endl;

return 0;
}

Here is the fixed (hack) version:


#include <iostream>
#include <string>

int main()
{
std::cout << "Enter a string: ";
std::string a_word, stripped_word;
std::cin >> a_word;

for(std::string::size_type ix = 0; ix != a_word.size(); ++ix)
{
if(ispunct(a_word.at(ix)) == 0)
stripped_word.append(1,a_word.at(ix));
}

std::cout << stripped_word << std::endl;

return 0;
}
 
I

Ian Collins

arnuld said:
/* C++ Primer 4/e
* section 3.2 - String Standard Library

* exercise 3.10
* STATEMENT
* write a programme to strip the punctation from the string. */

#include <iostream>
#include <string>

int main()
{
std::cout << "Enter a string: ";
std::string a_word, stripped_word;
std::cin >> a_word;

for(std::string::size_type ix = 0; ix != a_word.size(); ++ix)
{
if(ispunct(a_word[ix]) == 0)
stripped_word[ix] = a_word[ix];
}

std::cout << stripped_word << std::endl;

return 0;
}
As well as the other suggestions, you could use:

for( std::string::const_iterator ix = a_word.begin();
ix != a_word.end(); ++ix )
{
if(ispunct(*ix) == 0)
stripped_word += *ix;
}
 
A

arnuld

A std::string is not an open array, you can't just assign to random
non-existing positions.

ok, got it

stripped_word += a_word[ix];

this works. we are just concatenating 2 string objects. right ?

stripped_word.append(a_word[ix]);

[arnuld@arch cpp ]% g++ -ansi -pedantic -Wall -Wextra ex_03-10.cpp
ex_03-10.cpp: In function ‘int main()’: ex_03-10.cpp:21: error: no
matching function for call to ‘std::basic_string<char,
std::char_traits<char>, std::allocator<char> >::append(char&)’
/usr/lib/gcc/i686-pc-linux-gnu/4.2.1/../../../../include/c++/4.2.1/bits/basic_string.tcc:330:
note: candidates are: std::basic_string<_CharT, _Traits, _Alloc>&
std::basic_string<_CharT, _Traits, _Alloc>::append(const
std::basic_string<_CharT, _Traits, _Alloc>&) [with _CharT = char, _Traits
= std::char_traits<char>, _Alloc = std::allocator<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.2.1/../../../../include/c++/4.2.1/bits/basic_string.tcc:347:
note: std::basic_string<_CharT, _Traits, _Alloc>&
std::basic_string<_CharT, _Traits, _Alloc>::append(const
std::basic_string<_CharT, _Traits, _Alloc>&, typename
_Alloc::rebind<_CharT>::eek:ther::size_type, typename
_Alloc::rebind<_CharT>::eek:ther::size_type) [with _CharT = char, _Traits =
std::char_traits<char>, _Alloc = std::allocator<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.2.1/../../../../include/c++/4.2.1/bits/basic_string.tcc:303:
note: std::basic_string<_CharT, _Traits, _Alloc>&
std::basic_string<_CharT, _Traits, _Alloc>::append(const _CharT*, typename
_Alloc::rebind<_CharT>::eek:ther::size_type) [with _CharT = char, _Traits =
std::char_traits<char>, _Alloc = std::allocator<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.2.1/../../../../include/c++/4.2.1/bits/basic_string.h:824:
note: std::basic_string<_CharT, _Traits, _Alloc>&
std::basic_string<_CharT, _Traits, _Alloc>::append(const _CharT*) [with
_CharT = char, _Traits = std::char_traits<char>, _Alloc =
std::allocator<char>] <near match>
/usr/lib/gcc/i686-pc-linux-gnu/4.2.1/../../../../include/c++/4.2.1/bits/basic_string.tcc:286:
note: std::basic_string<_CharT, _Traits, _Alloc>&
std::basic_string<_CharT, _Traits, _Alloc>::append(typename
_Alloc::rebind<_CharT>::eek:ther::size_type, _CharT) [with _CharT = char,
_Traits = std::char_traits<char>, _Alloc = std::allocator<char>]
[arnuld@arch cpp ]%
[arnuld@arch cpp ]% g++ --version
g++ (GCC) 4.2.1 20070704 (prerelease) Copyright (C) 2007 Free Software
Foundation, Inc. This is free software; see the source for copying
conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE.

[arnuld@arch cpp ]%
 
V

Victor Bazarov

arnuld said:
[..]
can you tell me how this works or just point me to someplave which
explains that:

stripped_word.append(1,a_word.at(ix));

i mean, what is "1" doing here ? and why (ix) rather than [ix] ? i am
at halfway of chapter 3 so i have not come across this "append" member
function. just covered "size" and "empty" till yet.

RTFM. 'append' is overloaded and one of them takes a number (N) and
the character and appends a string generated from N characters. There
is a constructor that does similar stuff, BTW.

V
 
A

arnuld

Here is the fixed (hack) version:
:)

#include <iostream>
#include <string>

int main()
{
std::cout << "Enter a string: ";
std::string a_word, stripped_word;
std::cin >> a_word;

for(std::string::size_type ix = 0; ix != a_word.size(); ++ix)
{
if(ispunct(a_word.at(ix)) == 0)
stripped_word.append(1,a_word.at(ix));
}

std::cout << stripped_word << std::endl;

return 0;


can you tell me how this works or just point me to someplave which
explains that:

stripped_word.append(1,a_word.at(ix));

i mean, what is "1" doing here ? and why (ix) rather than [ix] ? i am at
halfway of chapter 3 so i have not come across this "append" member
function. just covered "size" and "empty" till yet.
 
A

anon

Victor said:
arnuld said:
[..]
can you tell me how this works or just point me to someplave which
explains that:

stripped_word.append(1,a_word.at(ix));

i mean, what is "1" doing here ? and why (ix) rather than [ix] ? i am
at halfway of chapter 3 so i have not come across this "append" member
function. just covered "size" and "empty" till yet.

RTFM. 'append' is overloaded and one of them takes a number (N) and
the character and appends a string generated from N characters. There
is a constructor that does similar stuff, BTW.

These guys got very good references:
http://www.cppreference.com/cppstring/index.html
and should answer all questions.


PS If anyone know better references, please let me know.
www.cppreference.com is missing lots of stuff
 
?

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

Victor said:
arnuld said:
[..]
can you tell me how this works or just point me to someplave which
explains that:

stripped_word.append(1,a_word.at(ix));

i mean, what is "1" doing here ? and why (ix) rather than [ix] ? i am
at halfway of chapter 3 so i have not come across this "append" member
function. just covered "size" and "empty" till yet.

RTFM. 'append' is overloaded and one of them takes a number (N) and
the character and appends a string generated from N characters. There
is a constructor that does similar stuff, BTW.

These guys got very good references:
http://www.cppreference.com/cppstring/index.html
and should answer all questions.


PS If anyone know better references, please let me know.
www.cppreference.com is missing lots of stuff

www.cplusplus.com is quite complete I think, but I like the simplicity
of www.cppreference.com better.
 
R

red floyd

arnuld said:
/* C++ Primer 4/e
* section 3.2 - String Standard Library

* exercise 3.10
* STATEMENT
* write a programme to strip the punctation from the string. */

#include <iostream>
#include <string>

int main()
{
std::cout << "Enter a string: ";
std::string a_word, stripped_word;
std::cin >> a_word;

for(std::string::size_type ix = 0; ix != a_word.size(); ++ix)
{
if(ispunct(a_word[ix]) == 0)
stripped_word[ix] = a_word[ix];
}

std::cout << stripped_word << std::endl;

return 0;
}


Don't you also need to #include <cctype> for ispunct()?
 
B

BobR

arnuld said:
/* C++ Primer 4/e * section 3.2 - String Standard Library
* exercise 3.10
* STATEMENT
* write a programme to strip the punctation from the string. */

#include <iostream>
#include <string>
int main(){
std::cout << "Enter a string: ";
std::string a_word, stripped_word;
std::cin >> a_word;
for(std::string::size_type ix = 0; ix != a_word.size(); ++ix){
if(ispunct(a_word[ix]) == 0)
stripped_word[ix] = a_word[ix];
}
std::cout << stripped_word << std::endl;
return 0;
}

Another way than shown already (push_back()):

#include <iostream>
#include <string>
#include <cctype>

int main(){
std::string a_word("I think, therefore, I am! I'm shocked?");
// std::cout << "Enter a string: ";
// std::cin >> a_word;
std::cout<<"a_word="<<a_word<<std::endl;

std::string stripped_word;
for( std::string::size_type ix = 0; ix != a_word.size(); ++ix){
if( not std::ispunct( a_word.at( ix ) ) )
stripped_word.push_back( a_word.at( ix ) );
}

std::cout<<"stripped_word="<<stripped_word<<std::endl;
return 0;
}
// out:a_word=I think, therefore, I am! I'm shocked?
// out:stripped_word=I think therefore I am Im shocked
 
J

James Kanze

arnuld said:
/* C++ Primer 4/e
* section 3.2 - String Standard Library
* exercise 3.10
* STATEMENT
* write a programme to strip the punctation from the string. */
#include <iostream>
#include <string>
int main()
{
std::cout << "Enter a string: ";
std::string a_word, stripped_word;
std::cin >> a_word;
for(std::string::size_type ix = 0; ix != a_word.size(); ++ix)
{
if(ispunct(a_word[ix]) == 0)
stripped_word[ix] = a_word[ix];
}
std::cout << stripped_word << std::endl;
return 0;
}
As well as the other suggestions, you could use:
for( std::string::const_iterator ix = a_word.begin();
ix != a_word.end(); ++ix )
{
if(ispunct(*ix) == 0)
stripped_word += *ix;
}

That's getting close to what I would write. Except that the one
argument form of ispunct requires an include of <ctype.h>, and
it's undefined behavior to use it directly on a char. For a
quick program, without using any of my existing toolset, I'd
write:

if ( ! ispunct( static_cast< unsigned char >( *ix ) ) {
stripped_word += *ix ;
}

in the loop. With my usual tools, I'd more likely write:

word.erase( std::remove( word.begin(), word.end(),
CTypeIs( std::ctype_base::punct )),
word.end() ) ;

and be done with it. But this only works because I've got the
function objects to wrap std::ctype<char> in my standard
toolbox. Otherwise, you have to write a special class to do
this, which is a bit of a drag.
 
J

Jerry Coffin

[ ... ]
As well as the other suggestions, you could use:

for( std::string::const_iterator ix = a_word.begin();
ix != a_word.end(); ++ix )
{
if(ispunct(*ix) == 0)
stripped_word += *ix;
}

Or:

std::remove_copy_if(a_word.begin(), a_word.end(),
std::back_inserter(stripped_word), ispunct);

Of course, to be correct you really can't apply ispunct directly to
chars. Something like this should fix that:

struct punct {
bool operator()(char ch) {
return ispunct((unsigned char)ch);
}
};

then the same algorithm, but using that functor:

std::remove_copy_if(a_word.begin(), a_word.end(),
std::back_inserter(stripped_word), punct());
 

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,744
Messages
2,569,484
Members
44,906
Latest member
SkinfixSkintag

Latest Threads

Top