0

I am seeking help on a code that reads a string of characters with punctuation included and outputs what was read with the punctuation omitted. I paid a visit to this link C++ Remove punctuation from String I believe my code is solid. When I compile the code it prompts for the string. However upon entering the string and pressing enter, nothing happens there is no output afterwards I've tweaked the code extensively, but to no avail.

int main(){
    string line;
    cout <<"Please Enter a line"<< endl;
    while(getline(cin, line)){
        for(decltype(line.size()) index = 0; index != line.size() && !isspace(line[index]); ++index){        
            if (ispunct(line[index])){
                line.erase(index--,1);
                line[index] = line.size();
            }
        }
    }
    cout<< line << endl;
    return 0;
}
Community
  • 1
  • 1
dirty_sanchez
  • 69
  • 1
  • 1
  • 12

3 Answers3

1

You are making this way more complicated (decltype? for this?) than it needs to be. Try:

int main()
{
    std::string line;
    std::cout <<"Please Enter a line"<< std::endl;
    while(std::getline(std::cin, line)){
        const char* s = line.c_str();
        while(*s){
            if (!ispunct(*s)){
                std::cout << *s;  // not as slow as you would think: buffered output
            }
            ++s;
        }
        std::cout << std::endl; // flush stdout, that buffering thing
    }
}

Simpler is usually better. As a side bonus, this should also be quite a bit faster.

frasnian
  • 1,973
  • 1
  • 14
  • 24
  • this works and its indeed faster. I'm quite confused on the line.c_str(). what does that imply. thanks Also the code in the if statement can you provide a brief explanation as to it effects with respect to the output. thanks in advance – dirty_sanchez Feb 16 '15 at 03:48
  • `std::string::c_str()` returns a `const char*` to the raw bytes of the string. You can treat its return value as you would any other `const` "C-style" `char*`- dereferencing, incrementing, etc. It's about as "close to the metal" as you can get. Your statements are that much closer to the machine representation of actual opcodes the CPU will execute. Also, the posted method is more efficient anyway because `std::string::erase()` the way you are calling it has to shuffle the entire remainder of the string downwards in memory for every punctuation character, rather than just skip over them. – frasnian Feb 16 '15 at 03:57
  • Regarding the question about the `if` statement and output - clearly, we're just checking each character to see if it is punctuation, and if so we skip it. The character-by-character output is not the performance hit you might think because output by `iostream` is buffered - you're just writing to a memory location until the buffer is flushed, either by writing an explicit `std::endl` (note: NOT a `'\n'` character - `std::endl` writes a `'\n'` to the stream *and* flushes the buffer), or some other event occurs (buffer full, close stream, etc.). – frasnian Feb 16 '15 at 04:10
  • hello you aided me in the above script earlier. But I have another script that incorporate aspects of this script but converts characters up to uppercase. at this site http://stackoverflow.com/questions/28800055/how-to-change-each-word-in-a-string-vector-to-upper-case/28800559#28800559 – dirty_sanchez Mar 02 '15 at 01:28
  • do you have any idea how to do this code if we ate presented with a string vector using the while loops you demonstrated here? thanks – dirty_sanchez Mar 02 '15 at 15:36
  • in re: `how to do this code if ... presented with a string vector using the while loops you demonstrated here?`: I'm not sure what you mean by this - you might want to ask as a separate question (preferably with either pseudo-code or code that might not work but illustrates more clearly what you are trying to accomplish). This is probably also not the best place for your follow-on question, as it a distinctly separate problem so any answer here would muddy the waters of all answers to the original question. – frasnian Mar 04 '15 at 05:56
0

This can be done without any loops. Usage of the algorithm functions is all you need.

In general, if you have a container, and you want to remove items from the container that satisfy a certain condition, you're using a long (and maybe, wrong) approach if you're writing hand-coded loops as you are doing.

Here is an example of usage of the algorithm functions, namely std::remove_if.

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

using namespace std;

int main()
{
   std::string s = "This is, a, string: with ! punctuation.;";
   s.erase(std::remove_if(s.begin(), s.end(), ::ispunct), s.end());
   cout << s;
}

Live Example: http://ideone.com/Q6A0vJ

PaulMcKenzie
  • 34,698
  • 4
  • 24
  • 45
-1

The reason why your code doesn't output anything is because it is stuck in that getline loop.

assuming c++11:

int main(){
  string line;
  cout <<"Please Enter a line"<< endl;
  getline(cin, line);
  line.erase(std::remove_if(line.begin(),  line.end(),  
               [](char ch) { return ispunct(ch) ? true : false; }), line.end());
  cout << line << endl;
  return 0;
}

or

int main(){
  string line;
  cout <<"Please Enter a line"<< endl;
  transform(line.begin(), line.end(), line.begin(), 
              [](char ch) {  return ispunct(ch) ? '\0' : ch; });
  cout << line << endl;
  return 0;
}
thang
  • 3,466
  • 1
  • 19
  • 31