How do I remove punctuaution from a string - c++

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

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.

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

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

Related

How to get the strings to print in order after they have been reversed

The goal of this program is to get user input and then print the words backwards, but still in the order the user typed them in. For example, the user input- "cats and mice are cool", then the program should output "stac dna ecim era looc", but what I am getting is "looc era ecim dna stac". I think that rearranging the words would happen in the main function, but I'm not sure how to get it to print in order. Any help greatly appreciated!
#include <iostream>
#include <cstring>
using namespace std;
void reverse(string input) {
int size = (int)input.size();
if(size==1){
cout << input[size-1];
}
else {
cout << input[size-1];
reverse(input.substr(0, size-1));
}
}
int main() {
string input;
char choice;
cout << "Please enter a string with spaces." << endl;
getline(cin, input);
reverse(input);
cout << endl;
}
You're reversing the entire string... split string on spaces, then cycle on splits and call reverse() on every split before printing it.
Furthermore, you can use C++ STL classes for reversing and even result useful in splitting:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
std::vector<std::string> split(std::string text, char delimiter)
{
std::vector<std::string> res;
std::istringstream f(text);
std::string s;
while (std::getline(f, s, delimiter)) {
res.push_back(s);
}
return(res);
}
int main() {
std::string input;
std::cout << "Please enter a string with spaces." << std::endl;
std::getline(std::cin, input);
for(auto s : split(input, ' '))
{
std::reverse(s.begin(), s.end());
std::cout << s << " ";
}
std::cout << std::endl;
}

Counting word occurence in textfile

Here's the code that I based here http://www.thecrazyprogrammer.com/2015/02/c-program-count-occurrence-word-text-file.html. (new in c++)
#include <iostream>
#include <fstream>
#include<cstring>
using namespace std;
int main()
{
// std::cout << "Hello World!" << std::endl;
// return 0;
ifstream fin("my_data.txt"); //opening text file
int count=0;
char ch[20],c[20];
cout<<"Enter a word to count:";
gets(c);
while(fin)
{
fin>>ch;
if(strcmp(ch,c)==0)
count++;
}
cout<<"Occurrence="<<count<<"n";
fin.close(); //closing file
return 0;
}
Error in Patter Counting
my_data.txt has only 3 "world" in it, but as I run the program, it results to
here's the textfile's content
What could go wrong?
A solution using std::string
int count = 0;
std::string word_to_find, word_inside_file;
std::ifstream fin("my_data.txt");
std::cout << "Enter a word to count:";
std::cin >> word_to_find;
while (fin >> word_inside_file) {
if (word_to_find == word_inside_file )
count++;
}
std::cout << "Occurrence=" << count << "";
If you want to find all occurrences inside other strings as well, as mentioned in the comments, you can do something like this:
...
while (fin >> word_inside_file) {
count += findAllOccurrences(word_to_find, word_inside_file);
}
...
Inside findAllOccurrences(std::string, std::string) you will implement a "find all string occurrences inside another string" algorithm.
If you are new to c++ you shouldn't really use gets. Read about "buffer overflow vulnerability". gets() is more like c-style. You should consider using std::cin.

C++ Replacing a word in an array of characters

I'm working on a problem where I need to have user input a message then replace the work "see" with "c". I wanted to read in the array message[200] and then break it down into individule words. I tried a for loop but when I concatinate it just adds the privous words. I am only to use array of characters, no strings.
const int MAX_SIZE = 200;
int main(){
char message[MAX_SIZE]; //message array the user will enter
int length; // count of message lenght
int counter, i, j; //counters for loops
char updateMessage[MAX_SIZE]; //message after txt update
//prompt user to
cout << "Please type a sentence" << endl;
cin.get(message, MAX_SIZE, '\n');
cin.ignore(100, '\n');
length = strlen(message);
//Lower all characters
for( i = 0; i < length; ++i)
{
message[i] = tolower(message[i]);
//echo back sentence
cout << "You typed: " << message << endl;
cout << "Your message length is " << length << endl;
for( counter = 0; counter <= length; ++counter)
{
updateMessage[counter] = message[counter];
if(isspace(message[counter]) || message[counter] == '\0')
{
cout << "Space Found" << endl;
cout << updateMessage << endl;
cout << updateMessage << " ** " << endl;
}
}
return 0;
}
After each space is found I would like to output one work each only.
You should really try to learn some modern C++ and standard library features, so you don't end up writing C code in C++. As an example, this is how a C++14 program makes use of standard algorithms from the library to do the job in 10-15 lines of code:
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
int main()
{
using namespace std::string_literals;
std::istringstream input("Hello I see you, now you see me");
std::string str;
// get the input from the stream (use std::cin if you read from console)
std::getline(input, str);
// tokenize
std::vector<std::string> words;
std::istringstream ss(str);
for(std::string word ; ss >> word; words.push_back(word));
// replace
std::replace(words.begin(), words.end(), "see"s, "c"s);
// flatten back to a string from the tokens
str.clear();
for(auto& elem: words)
{
str += elem + ' ';
}
// display the final string
std::cout << str;
}
Live on Coliru
This is not the most efficient way of doing it, as you can perform replacement in place, but the code is clear and if you don't need to save every bit of CPU cycles it performs decently.
Below is a solution that avoids the std::vector and performs the replacement in place:
#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
int main()
{
std::istringstream input("Hello I see you, now you see me");
std::string str;
// get the input from the stream (use std::cin if you read from console)
std::getline(input, str);
// tokenize and replace in place
std::istringstream ss(str);
std::string word;
str.clear();
while (ss >> word)
{
if (word == "see")
str += std::string("c") + ' ';
else
str += word + ' ';
}
// display the final string
std::cout << str;
}
Live on Coliru

C++ User defined string needs to contain spaces (but not allowed by program..?)

I'm working on homework for my c++ class, and it's been quite awhile since I've used it. I was wondering if there was a way to allow spaces in a string (instead of it nulling out and ending the string)
my current code is this:
int chapter10() {
string strinput;
char charstr[1000];
int numwords=1;
cout << "Enter a phrase ";
cin >> strinput;
cout << strinput;
const int size = strinput.size() + 1;
strcpy_s(charstr, strinput.c_str());
cout << strinput << endl;
for (int i = 0; i != size; i++) {
if (*(charstr + i) == ' ')
numwords++;
}
cout << "There are " << numwords << " words in that string." << endl;
return 0;
}
The problem I'm having, is for instance, if I type "Hello World" and press enter, it pops the next line (right after the cin) and says "Hello", and the space made it cut the rest of the phrase off.
How does one fix this issue? I don't want to use the str:: things as I barely know what they are, and have really never had to use them, and that would look a bit suspicious to the teacher :P
Update: If you've suggested using getline(cin, strinput); It doesn't work too well. I can from what I see, only type in the 10 to reach my function, but after I press enter, it thinks that I've presses something else, which makes it completely skip the cin to get the string value. But, there is something weird with this, if I type "10 hello world" it does everything correctly. Well, with the exception that it needs to be in the same line as the number to reach the function.
Solved: The use of getline(cin, strinput) works perfectly fine, if you're not using user input before hand. If you are, you're going to need a cin.ignore before the getline(). As stated in the comment by my best answer.
#include <iostream>
#include <iomanip>
#include <string>
#include <limits>
using namespace std;
//~~~Initialize all functions
int chapter10();
//~~~Initializing complete
int main() {
srand(time(0)); //makes rng thingy work instead of choose same numbers cause it doesn't do it on its own. lol
cout << "Enter the chapter number you need to look at: ";
int chapterNumber;
cin >> chapterNumber;
switch (chapterNumber) {
case 1: testingStuff(); break;
case 9: chapter9(); break;
case 10: chapter10(); break;
default: cout << "You chose an invalid chapter number, reload the program."; break;
}
system("pause");//So console doesn't close instantly cause that's not annoying at all...
}
int chapter10() {
string strinput;
char charstr[10000];
int numwords=1;
cout << "Enter a phrase." << endl;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
getline(cin, strinput);
const int size = strinput.size() + 1;
strcpy_s(charstr, strinput.c_str());
for (int i = 0; i != size; i++) {
if (*(charstr + i) == ' ' & *(charstr + (i+1)) != ' ' )//the & is fail safe so multiple space no ++numwords
numwords++;
}
cout << "There are " << numwords << " words in that string." << endl;
return 0;
}
The way I have my code written was I used a switch/case to reach my function. This required user input, which in turn caused my program to 'think' I was still typing for the second input required in the chapter10 function.
Adding in the line of code: cin.ignore(numeric_limits<streamsize>::max(), '\n'); allowed me to cancel the input, and start a new one.
If you want to get all characters an end-user enters on a single line, use getline: instead of cin >> strinput write this:
getline(cin, strinput);
The fact that it is actually std::getline(std::cin, strinput) makes no difference, because your code uses std namespace anyway. In case you were wondering what std:: prefix is, it's a namespace of the Standard C++ library.
You can use getline() function
It copies into a string till a newline is reached or delimiter is found - so it will accept all the spaces till newline is reached
http://www.cplusplus.com/reference/string/string/getline/
or you can also use cin.getline() as shown here -
std::cin input with spaces?
use:
cin >> noskipws >> strinput;
Use std::getline() function. Example:
#include <iostream>
#include <vector>
#include <sstream>
void WordCounter(
const std::vector<std::string> & lines) {
for (int i = 0; i < lines.size(); ++i) {
std::istringstream iss(lines[i]);
std::string word;
int count = 0;
while (iss >> word) {
++count;
}
std::cout << "Line #" << i << " contains " << count << " words." <<
std::endl;
}
}
int main() {
std::string line;
std::vector<std::string> lines;
while (std::getline(std::cin, line)) {
lines.push_back(line);
}
WordCounter(lines);
return 0;
}

Reading in a simple text file & writing it to another text file with leading blanks and blank lines removed

I want to keep this code but now I am just wondering if there is a way when i read in the file in my while loop if i can remove the blanks within that loop
I am having a ton of problems with removing blanks
I do not have a large understanding on reading in files
to my program so this has been very
difficult for me, can anybody tell me where
I am making my mistakes?
#include <iostream>
#include <cassert>
#include <string>
#include <fstream>
#include <cstdio>
using namespace std;
int main (void)
{
int i=0;
int current=0;
int len;
int ch;
string s1;
string s2;
ifstream fileIn;
cout << "Enter name of file: ";
cin >> s1;
fileIn.open(s1.data() );
assert(fileIn.is_open() );
while (!(fileIn.eof() ) )
{ ch=fileIn.get();
s1.insert(i,1,ch);
s1.end();
i++;}
cout << s1;
len=s1.length();
cout << len;
while (current < len-1)
{
if (!(s1[current] == ' ' && s1[current + 1] == ' ') &&
!(s1[current] == '\n' && s1[current + 1] == '\n')
)
{
s2.append(s1[current]);
}
current++;
}
return 0;
}
There are a number of things that I would do differently. Without going into details, here is what I propose; it requires C++11 (pass the -std=c++11 also to the compiler if you are using gcc or clang):
#include <algorithm>
#include <cctype>
#include <fstream>
#include <functional>
#include <iostream>
#include <locale>
using namespace std;
// trim from left
static string ltrim(string s) {
s.erase(s.begin(), find_if(s.begin(), s.end(), [](char c) { return !isblank(c); } ));
return s;
}
int main() {
string file_name;
cout << "Please enter the file name: " << flush;
cin >> file_name;
ifstream in(file_name);
if (!in.good()) {
cout << "Failed to open file \"" << file_name << "\"" << endl;
return 1;
}
string buffer;
while (getline(in, buffer)) {
buffer = ltrim(buffer);
if (!buffer.empty()) {
cout << buffer << '\n'; // <-- or write into a file as you need
}
}
return 0;
}
Now the title says you want to remove only the leading spaces but to my question you answered that you want to remove the trailing spaces as well from the end of the lines. If it is like that, use trim() instead of ltrim(). The necessary functions are:
// trim from left
static string ltrim(string s) {
s.erase(s.begin(), find_if(s.begin(), s.end(), [](char c) { return !isblank(c); } ));
return s;
}
// trim from right
static string rtrim(string s) {
s.erase(find_if(s.rbegin(), s.rend(), [](char c) { return !isblank(c); }).base(), s.end());
return s;
}
// trim from both left and right
static string trim(string s) {
return ltrim(rtrim(s));
}
There are other, most likely faster trim implementations. See, for example: What's the best way to trim std::string?
The standard library already has most of the functionality you want, so I'd do my best to rely on that to do most of the job.
Copying some data with a specified subset removed is what std::remove_copy_if is supposed to do, so I'd use it for the main loop:
std::remove_copy_if(std::istream_iterator<line>(std::cin),
std::istream_iterator<line>(),
std::ostream_iterator<std::string>(std::cout, "\n"),
[](std::string const &s){return s.empty(); });
So, given an appropriate definition of a line, that will copy lines with any empty ones removed.
Our next step is to define a line class that removes leading white-space when we extract one from a stream, and can be converted to a string. For that, I'd "cheat" a little. When we extract a character from a stream like mystream >> mychar;, it automatically skips any leading white-space. I'd use that by reading a char, then putting it back into the stream1, so I had the stream starting from the first non-whitespace character. Then I'd use getline to read the rest of the line.
1. Reading a character, then immediately putting it back into the stream is probably unusual enough to merit either a comment, or being put into a function with a descriptive name like skip_leading_blanks:
void skip_leading_blanks(std::istream &is){
char ch;
is >> ch;
is.putback(ch);
}