Unique Lines and Words? How to implement it? - c++

I'm having trouble with this program. The program is supposed to tell the user the number of lines, words, characters, unique lines, and unique words there are in a given input. So far, words and characters are okay. However, if the user wants to input more than one line, how do I do that? The functions will only output the results of one line at a time, rather than adding the results of both lines together. Also, I can't get the Unique Lines and Unique Words to work properly. I just got into C++ so I don't really have much experience. Can someone please help me?
Problems:
Program reads one line at a time, so when the user inputs multiple times, the program produces the results separately rather than adding it together as one entity.
Unique Lines and Unique Words are not working. Any ideas how to implement it using the library used in the program.
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
#include <string>
using std::string;
#include <set>
using std::set;
// write this function to help you out with the computation.
unsigned long countLines()
{
return 1;
}
unsigned long countWords(const string& s)
{
int nw =1;
for (size_t i = 0; i < s.size(); i++)
{
if (s[i] == ' ') //everytime the function encounters a whitespace, count increases by 1)//
{
nw++;
}
}
return nw;
}
unsigned long countChars(const string& s)
{
int nc = 0;
for (size_t i = 0; i < s.size(); i++)
{
if ( s[i] != ' ') //everytime the function encounters a character other than a whitespace, count increases//
{
nc++;
}
}
return nc;
}
unsigned long countUnLines(const string& s, set<string>& wl)
{
wl.insert(s);
return wl.size();
}
unsigned long countUnWords(const string& s, set<string>& wl)
{
int m1 = 0;
int m2 = 0;
string substring;
for(m2 = 0; m2 <= s.size(); m2++){
if (m2 != ' ' )
substring = s.substr(m1,m2);
wl.insert(substring);
m1 = m2 + 2;}
}
return wl.size();
int unw = 0;
wl.insert(s);
unw++;
return unw;
}
int main()
{
//stores string
string s;
//stores stats
unsigned long Lines = 0;
unsigned long Words = 0;
unsigned long Chars = 0;
unsigned long ULines = 0;
unsigned long UWords = 0;
//delcare sets
set<string> wl;
while(getline(cin,s))
{
Lines += countLines();
Words += countWords(s);
Chars += countChars(s);
ULines += countUnLines(s,wl);
UWords += countUnWords(s);
cout << Lines << endl;
cout << Words<< endl;
cout << Chars << endl;
cout << ULines << endl;
cout << UWords << endl;
Words = 0;
Chars = 0;
ULines = 0;
UWords = 0;
}
return 0;
}

You are resetting your count variables to zero at the end of your getline while loop. This is why you are only getting results for one line. The user can input multiple lines in your program as it is right now you are just resetting the count.

I think you're headed in the right direction. In order to count unique lines and words you're gonna have to store every line and word in a data structure of some kind, I'd suggest an unordered_map. Each element in the map you'll have a counter for # of occurences of each line/word.

I don't want to give the answer away wholesale, but here are some ideas to get you started.
The function getline() can read in an entire line of input. Do this until there's no more input.
You can use a container like std::set (or better, std::unordered_set) to store the lines read in. Not the most efficient, but it keeps track of all your lines, and only stores the unique ones.
Each line can then be broken down into words. Consider using something like std::stringstream for this.
Store the words in a different std::unordered_set.
The number of unique lines (words) is simply the number of lines (words) stored in the containers. Use the .size() method to obtain this.
Doing the total number of lines, words, and characters can be computed as you read the data in, so I won't go into much detail there.
Each item is googleable, and you may choose to implement different parts differently (if you don't want to use a stringstream, you can always iterate over the line read, for example.) This should get you on the right track.

It's pretty easy to get fairly accurate counts, but can be surprisingly difficult to get correct counts for all of this.
The big problem is the character count. If you open the file (as you usually would) in text mode, the number of characters you count may not match what the OS thinks is there. For the obvious examples, under Windows a CR/LF pair will be translated to a single new-line character, so you'll typically count each line as one character shorter than it really is.
Technically, there's no way to deal with that entirely correctly either -- the translation from external to internal representation when a file is opened in text mode is theoretically arbitrary. At least in theory, opening in binary mode doesn't help a lot either; in binary mode, you can have an arbitrary number of NUL characters after the end of the data that was written to the file.
The latter, however, is pretty much theoretical these days (it was allowed primarily because of CP/M, which most people have long forgotten).
To read lines, but retain the line-end delimiters intact, you can use std::cin.get() instead of std::getline(), then read the delimiters separately from the line itself.
That gives us something like this:
#include <iostream>
#include <set>
#include <string>
#include <iterator>
#include <sstream>
#include <fstream>
int main(int argc, char **argv) {
static char line[4096];
unsigned long chars = 0;
unsigned long words = 0;
unsigned long lines = 0;
std::set<std::string> unique_words;
std::ifstream in(argv[1], std::ios::binary);
while (in.get(line, sizeof(line), '\n')) {
++lines;
chars += strlen(line);
std::istringstream buffer(line);
std::string word;
while (buffer >> word) {
++words;
unique_words.insert(word);
}
while (in.peek() == '\n' || in.peek() == '\r') {
++chars;
in.ignore(1);
}
}
std::cout << "words: " << words << "\n"
<< "lines: " << lines << "\n"
<< "chars: " << chars << "\n"
<< "unique words: " << unique_words.size() << "\n";
}
Note that although this does answer that the OP actually asked at least for most typical OSes (Linux, *BSD, MacOS, Windows), it's probably not what he really wants. My guess is that his teacher isn't really asking for this level of care to try to get an accurate character count.
Also note that if you should encounter a line longer than the buffer, this can still give an inaccurate count of lines -- it'll count each buffer-full of data as a separate line, even if it didn't find a line-delimiter. That can be fixed as well, but it adds still more complexity to a program that's almost certainly already more complex than intended.

Related

Why are my char functions not doing their job?

So I am still new to C++, and I'm trying to make a program that has the user input a string, and then my functions return the string in reverse case, all lower case, and then all uppercase. Instead I just keep receiving the first letter of the string back, always uppercase. Not sure what I am doing wrong. Any suggestions?
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
char answer[255] = "";
int max = strlen(answer);
void reverse() {
for (int i = 0; i < max; i++) {
if (islower(answer[i])) {
isupper(answer[i]);
}
else if (isupper(answer[i])) {
islower(answer[i]);
}
else if (isspace(answer[i])) {
isspace(answer[i]);
}
}
cout << answer[max];
}
void lower() {
for (int i = 0; i < max; i++) {
if (isupper(answer[i])) {
islower(answer[i]);
}
else {
answer[i] = answer[i];
}
}
cout << answer[max];
}
void upper() {
for (int i = 0; i < max; i++) {
if (islower(answer[i])) {
isupper(answer[i]);
}
else {
answer[i] = answer[i];
}
}
cout << answer[max];
}
int main() {
cout << "Please enter a word, or a series of words: " << endl;
cin >> answer[max];
reverse();
lower();
upper();
system("pause");
return 0;
}
islower(char) is just a built in function to check if the char is in lowercase or not. Same goes with isupper. It does not change the case of the character.
In order to convert to lowercase/uppercase, use tolower/toupper. This would return the character in the converted case. But, it is important that you need to assign the returned value to the character itself.
Refer to this answer for some more clarity related to islower, isupper, tolower and toupper.
And now coming to the point why it's printing just the 1st character: As #user4581301 has mentioned in his comment,
"cin >> answer[max]; will read exactly one character because answer[max] is exactly one character, the first character. In C++ you have to do things in order. For example, int max = strlen(answer); will provide an answer based on what is in that string at that time. Since the string was initialized one line earlier and contains an empty string, max will be 0."
Hence your cin should be cin >> answer. BUT, this will accept the 1st word of your sentence. In order to accept all the words including the spaces, use getline() instead. And for using this, answer should be declared as string answer instead of a char array.
This is how you accept a full sentence: getline(cin,answer);
And your variable max will give an error in a few compilers as being ambiguous. This is because of the using namespace std;. to avoid this, rename max to something else, like maxlen.
And finding the length of answer: It would be better if you call answer.length() after accepting the string from user rather than doing it globally.
Your working code should look something like this:
#include <iostream>
#include <string>
#include <cstring>
using namespace std;
string answer;
int maxlen;
void reverse() {
for (int i = 0; i < maxlen; i++) {
if (islower(answer[i])) {
answer[i] = toupper(answer[i]);
}
else if (isupper(answer[i])) {
answer[i] = tolower(answer[i]);
}
else if (isspace(answer[i])) {
answer[i]=' ';
}
}
cout << "Reversed string: " + answer << endl;
}
void lower() {
for (int i = 0; i < maxlen; i++) {
if (isupper(answer[i])) {
answer[i] = tolower(answer[i]);
}
else {
answer[i] = answer[i];
}
}
cout << "Lower case string: " + answer << endl;
}
void upper() {
for (int i = 0; i < maxlen; i++) {
if (islower(answer[i])) {
answer[i] = toupper(answer[i]);
}
else {
answer[i] = answer[i];
}
}
cout << "Upper case string: " + answer << endl;
}
int main() {
cout << "Please enter a word, or a series of words: " << endl;
getline(cin,answer);
cout << "Original string: " + answer << endl;
maxlen = answer.length();
reverse();
lower();
upper();
return 0;
}
With the output:
Please enter a word, or a series of words:
ReVeRsAl UPPER aNd lower
Original string: ReVeRsAl UPPER aNd lower
Reversed string: rEvErSaL upper AnD LOWER
Lower case string: reversal upper and lower
Upper case string: REVERSAL UPPER AND LOWER
cin >> answer[max];
will read exactly one character because answer[max] is exactly one character, the character in the array at position max.
max is 0 because you have to do things in order. For example,
int max = strlen(answer);
will provide the length of answer at that time this line is reached. Since the string was initialized one line earlier
char answer[255] = "";
and contains an empty string, max will be 0. This means answer[max] is answer[0] Nothing in the code ever changes max, so it will remain 0.
OK, say we change things a little and rather than reading into a single character, we read into answer as a string. You will need to
cin.getline(answer, sizeof(answer));
because
cin >> answer;
will read one whitespace-delimited token. One word. Your stated goal is to read more than one word. istream::getline will read everything it finds into the first parameter up to the end of the line or it finds the number of characters specified in the second parameter minus 1 (in order to reserve space for the string's null terminator). sizeof(answer) is literally the size of the answer array in bytes. We're operating in byte-sized characters so the count of characters and number of bytes are the same. Extra care must be taken if multibyte characters are being used.
This seems like a good place to recommend using std::string and std::getline instead. They make a large number of problems, such as the maximum number of characters that can be read, vanish for the vast majority of cases.
I'm not going to use them here, though because the assignment likely has a "No strings" policy.
So now that we have cin.getline(answer, sizeof(answer)); reading the user's input we can work on getting the size for max. We could strlen, but we could also use istream::gcount to get the number of characters read by getline.
main now looks something like
int main() {
cout << "Please enter a word, or a series of words: " << endl;
cin.getline(answer, sizeof(answer));
max = cin.gcount();
reverse();
lower();
upper();
system("pause");
return 0;
}
Whole bunch of stuff can go wrong at this point.
using namespace std; can wreak havoc on the max because of possible collisions with std::max. In general, avoid using namespace std; The few letters it saves you from typing often are recovered by the time wasted debugging the weird errors it can introduce.
isupper(answer[i]); doesn't do anything useful as others have noted in the comments. You want
answer[i] = toupper(static_cast<unsigned char>(answer[i]));
See Do I need to cast to unsigned char before calling toupper(), tolower(), et al.? for why that insane-and-pointless-looking cast may be necessary. Thank you HolyBlackCat for bringing that to my attention.
Self assignments like
answer[i] = answer[i];
are pointless for reasons that should be obvious once you stop and think about it.
Likewise
else if (isspace(answer[i])) {
isspace(answer[i]);
}
May not be particularly useful. If answer[i] is a space, set it to a space? It's already a space. What it would do is replace other forms of whitespace, tabs and carriage returns, with a space. Newline has already been picked off by getline. Also probably needs a cast similar to the one used in the toupper example above. I'm still reading up on that.
As hinted at above,
cout << answer[max];
is not effective. It prints out one character, and if max has been fixed, answer[max] will be the terminating null. Instead print out the whole array.
cout << answer;
General suggestions:
Don't write much code at a time. Write a few lines, a function at the most, before compiling and testing. If you had tested
int main() {
cout << "Please enter a word, or a series of words: " << endl;
cin >> answer[max];
cout << answer;
}
You would have immediately seen data was not being read correctly. and fixed it before proceeding. By allowing errors to build up, you make it harder to find any one bug. You may correctly fix a bug only to find the fix undone or concealed by another bug.
Avoid using global variables. Try to place variables in the smallest possible scope. In this case, move answer and max into main and pass them to the other functions as parameters. This makes it a lot easier to keep track of who set what variable and when. It also helps prevent accidental Variable Shadowing.

Justifying user input string into lines of equal length

So, full disclosure, I have just started learning C++ and this IS part of an assignment. I'm not looking for an answer, just a some guidance.
I'm looking to justify some text in the form of a string into lines of equal length. Both the text and line length are user-input.
What I've got so far is the code below. It works just fine to do the task at hand. I've thrown a bunch of text at it and it's always output the correct formatting for it. However, I am feeling as though I'm going at it the wrong way - the code feels clunky, as if I was forcing it to do something it wasn't designed to do (if you know what I mean).
Should I be looking (or is there) a more elegant way to do what I'm trying to do. I've considered setting up a 2D array of size [width][#lines] so that I can output it line by line. Would that be a preferable way to do things? Is there some sort of "Best Practice" when it comes to this stuff?
#include <iostream>
#include <string>
using namespace std;
int main()
{
string randtext;
string output;
int width;
// User input text string.
cout << "Enter a Random String of Text: " << endl;
getline(cin, randtext);
// User input line width.
cout << "Enter justification Width" << endl;
cin >> width;
int length = randtext.length();
int i = 0;
// This bit parses through the string.
while (i <= length)
{
// This bit creates lines of length = width.
for (int j = 0; j < width; ++j)
{
if (i + j > length) { break; }
char letter = randtext[i+j];
output += letter;
}
// This bit outputs the lines and then clears everything.
cout << output << endl;
output.clear();
i += width;
}
cin.get();
cin.get();
return 0;
}
Your current code has a bug: array indices are 0-based, meaning that 0 to length - 1 are valid, but length is not a valid index. If your goal is to split a string into fixed-sized chunks without any other conditions or constraints, you might consider using string::substr(). This would reduce the amount of code, and make things clearer.
But I'm wondering whether fixed-sized chunks is actually your goal? When I hear "justified" text, I think about text that has been word wrapped (i.e., split on word boundaries) and then spaces inserted so that the left and right edges of each line are aligned. Example:
The quick red fox jumped over the two lazy dogs.
Justified using 14-character line width:
The quick red
fox jumped
over the two
lazy dogs.
Firstly as far as I know there are no best practices. However I would suggest keeping it as simple as possible. I've used a similar approach to what you have done however I have instead inserted a new line character every width interval to the randtext string and then printed that. This dramatically reduces the code size and improves readability. I have tested this against your code and the output is exactly the same. The code is shown below.
#include <iostream>
#include <string>
#include <conio.h>
int main()
{
using namespace std;
string randtext;
int width;
// User input text string.
cout << "Enter a Random String of Text: " << endl;
getline(cin, randtext);
// User input line width.
cout << "Enter justification Width" << endl;
cin >> width;
// Insert a newline character every nth character given that n = width
for (size_t i = 0; i < randtext.length(); i+=width+1)
{
randtext.insert(i,"\n");
}
cout << randtext << endl;
cin.get();
cin.get();
return 0;
}
In case someone stumbles onto this in the future looking for an answer to a similar question, I ended up scrapping my previous code and used SUBSTR (as suggested by #cbranch)to chop up the text and fed it into a VECTOR as follows:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string input = "The quick brown fox, jumps over the. Lazy dog. There is, no cow. LEVEL";
int width = 20;
int length = input.size();
int j = 0;
vector<string> input_vector (0);
// For loop that chops up the input using input.substr() and feeds it into a vector that re-sizes as needed.
for (int i = 0; i < length; i+=width)
{
// Dynamic vector resizing as needed.
input_vector.resize(j + 1);
string input_sub = input.substr(i, width);
input_vector[j] = input_sub;
j++;
}
int size_vector = input_vector.size();
// For loop that outputs the chopped out lines as elements of the vector.
for (int k = 0; k < size_vector; ++k)
{
cout << input_vector[k] << endl;
}
return 0;
}

C++ in Xcode pausing

this is my first SO post.
I am very new to programming, and with C++ I thought I might try and make a program that allows the user to submits a block of text (max 500 characters), allows them to enter a 4 letter word and the program return with the amount of times it picks that word up in the text.
I am using X-code and it keeps making a green breakpoint and pausing the program at the 'for' loop function. my code is shown below:
#include <iostream>
#include <string>
#include <math.h>
#define SPACE ' '(char)
using namespace std;
//Submit text (maximum 500 characters) and store in variable
string text;
string textQuery(string msgText) {
do {
cout << msgText << endl;
getline(cin, text); } while (text.size() > 500);
return text;
}
//Query word to search for and store as variable
string word;
string wordQuery(string msgWord) {
cout << msgWord << endl;
cin >> word;
return word;
}
//Using loop, run through the text to identify the word
int counter = 0;
bool debugCheck = false;
int searchWord() {
for (int i = 0; i < text.size(); i++) {
char ch_1 = text.at(i);
char ch_2 = text.at(i + 1);
char ch_3 = text.at(i + 2);
char ch_4 = text.at(i + 3);
cout << i;
if(ch_1 == word.at(0) &&
ch_2 == word.at(1) &&
ch_3 == word.at(2) &&
ch_4 == word.at(3) )
{
counter++;
debugCheck = true;
}
}
return counter;
}
//cout the result
int main() {
string textUserSubmit = textQuery("Please submit text (max 500 characters): ");
string wordUserSubmit = wordQuery("Please select a word to search for: ");
int counterResponse = searchWord();
cout << debugCheck << endl;
cout << "The number of times is: " << counterResponse << endl;
return 0;
}
I get the error at the for loop. Any other advice about how i can make my program work for different words, multiple lengths of words and also how i can highlight the words in text would be helpful.
I really would appreciate if someone could aid me with my problem. Thanks!
I get the error at the for loop.
You should describe the error you get. I happen to have access to Xcode so I can run your code and see what happens, but you should try to spare that of people from whom you want help.
In this case you should describe how the debugger stops the program at the line:
char ch_4 = text.at(i + 3);
includes the message: "Thread 1: signal SIGABRT" and the console output shows
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: basic_string
Your problem is this: the for loop checks to make sure that i is in the correct range for the string text before using it as an index, but then you also use i+1, i+2, and i+3 as indices without checking that those values are also valid.
Fix that check and the program appears to run fine (given correct input).
Some miscellaneous comments.
Use more consistent indentation. It makes the program easier to read and follow. Here's how I would indent it (using the tool clang-format).
#define SPACE ' '(char) looks like a bad idea, even if you're not using it.
using namespace std; is usually frowned on, though as long as you don't put it in headers it usually won't cause too much trouble. I still could though, and because you probably won't understand the resulting error message you may want to avoid it anyway. If you really don't like writing std:: everywhere then use more limited applications such as using std::string; and using std::cout;.
global variables should be avoided, and you can do so here by simply passing textUserSubmit and wordUserSubmit to searchWord().
there's really no need to make sure text is less than or equal to 500 characters in length. You're using std::string, so it can hold much longer input.
You never check how long word is even though your code requires it to be at least 4 characters long. Fortunately you're using at() to index into it so you don't get undefined behavior, but you should still check. I'd remove the check in textQuery and add one to wordQuery.

How to use single letters to form words

Hey I currently have this code. It gets the user to input strings into an array, with a limit of 5. I plan to use the array to then form words from the array. How can I achieve this?
const int row = 5;
char array[row];
char count = 0;
char letter;
while (count < 5)
{
cout << "Enter a letter: ";
cin >> letter;
array[count] = letter;
count++;
}
cout << "Letter inputed" << endl;
for (count = 0; count < 5; count++)
{
cout << array[count] << " " << endl;
}
system("pause");
Here's a hint to get you started on the right track: don't even consider using std::next_permutation unless this is something you'll only ever use once or twice (and probably not even then, because it's actually more complicated than doing the job right).
Using std::next_permutation, your function will be approximately N! times slower than necessary1 -- in the case of 5 letters, that'll be 120 times slower, and if you ever use longer words, it'll get worse very quickly (e.g., for 10 letters it's over 3.5 million).
Instead, start by pre-processing your dictionary. Instead of a std::set<std::string> of words, create an std::map<std::string, std::vector<string>> (or std::unordered_map, though English has few enough words that this probably won't make a huge difference). As you read in a word from the dictionary, create a sorted version of that string. Use that as the key, and push the original version of the word onto the vector for that key.
Then when you get a word from the user, sort it, look that up in the map, and the associated vector will contain every word (from your dictionary) that can be created from those letters.
1. If you use std::map instead of std::unordered_map, that should be something like N!/(log N), but N! grows so fast and log N grows so slowly that it the difference is negligible (if you get N large enough that log N = 3, N! will be so large that N!/log N computation steps...well, you start to get into questions of cosmology, like whether the universe will have died of heat death before then (to which the answer seems to be "yes, probably").
Here's a hint to get you started. There's a function in the standard library called std::next_permutation. Assuming you have a dictionary of words to check against, a possible solution could look like this:
std::sort(array, array + row);
do {
// Check if array is a word.
} while (std::next_permutation(array, array + row));
This will cycle through every permutation of letters. It's now up to you to verify that it is a valid word.
This solution uses an associative array to map from sorted letters of the word to the words having such sorted letters. It's thus possible to get an answer with one lookup in the map, which takes asymptotically O(log N) time, where N is a size of your dictionary.
Create a file named dic.txt. In case you're using Visual Studio it should be in the same directory as your *.cpp files. Put several words inside in a "word in a row" format. Try the following code:
#include <iostream>
#include <string>
#include <map>
#include <vector>
#include <fstream>
#include <algorithm>
using namespace std;
int main() {
// Dictionary file is in a "word in a row" format
map< string, vector<string> > dictionary;
ifstream dictionary_file("dic.txt");
if (!dictionary_file.good()) {
cout << "File doesn't exist" << endl;
return 0;
}
string word;
while (dictionary_file >> word) {
string key = word;
sort(key.begin(), key.end());
dictionary[key].push_back(word);
}
// Read the letters
string letters;
cin >> letters;
if (letters.size() > 5) {
cout << "Too much letters" << endl;
return 0;
}
// Sort the letters
sort(letters.begin(), letters.end());
// Output the answers
vector<string> & ret = dictionary[letters];
for (size_t i = 0, ilen = ret.size(); i < ilen; ++i) {
cout << ret[i] << endl;
}
}
Mention that such a solution cares for a case your letters are in. In case you don't need it, you can add calls to strtolower function (got that name from PHP) before you add a word to your dictionary and before you sort your letters.
string strtolowers(string const & word) {
string ret = word;
transform(ret.begin(), ret.end(), ret.begin(), tolower);
return ret;
}
You'll need to add <cctype> header for this function to work.

a programm which removes excess spaces from a string [duplicate]

This question already has answers here:
Replace multiple spaces with one space in a string
(5 answers)
Closed 9 years ago.
I wrote a program which is supposed to remove excess spaces from a string. But it only shows characters before spaces. It finds a space and checks the character after that whether it is a space. Depending on excess spaces it shifts other characters over excess spaces. But output is very confusing.
input: "qwe(2 spaces)rt(one space)y"
output: "qwe(one space)rt(one space)y"
#include <iostream>
#include <stdlib.h>
#include <string>
using namespace std;
int main(){
string a;
cin >> a;
int len = a.length();
int new_len=len;
int z,s=0;
for(int i=0; i<new_len; i++){
if(a[i]==' '){
z=i+1;
s=0;
//Assigning the number of excess spaces to s.
while(a[z]==' '){
s++;
z++;
}
//doing the shifting here.
if(s>0){
for(int l=i+1; l<new_len-s; l++){
a[l]=a[s+l];
}
}
new_len-=s;
}
}
cout << a << endl;
cout << a.length();
system("pause");
return 0;
}
Most of your code is semi-pointless -- when you use the normal string extractor (stream >> string) it automatically skips across all consecutive leading white-space, and stops reading at the first whitespace character. As such, it's already doing almost everything the rest of your code is intended to accomplish. That leaves a much simpler approach to accomplishing the same task:
std::copy(std::istream_iterator<std::string>(std::cin),
std::istream_iterator<std::string>(),
std::ostream_iterator<std::string>(std::cout, " "));
This does have one problem: it'll leave one extra space at the end of the output. If you don't want that, you can use the infix_ostream_iterator I've posted previously. With that, you'd change the above to something like this:
std::copy(std::istream_iterator<std::string>(std::cin),
std::istream_iterator<std::string>(),
infix_ostream_iterator<std::string>(std::cout, " "));
If you're using C++11 doing this your way is overkill - you can just use a regex. Something like the following should do it (untested):
#include <regex>
#include <iostream>
#include <string>
using namespace::std;
int main(){
string a;
cin >> a;
regex r(" +");
a = regex_replace(a,r," ");
cout << a << endl;
cout << a.length();
system("pause");
return 0;
}
Your code is highly ineffective. Imagine a following string with 1,000,000 characters:
a a a a a a a...
Each time your algorithm encounters a second space, it goes through the whole string to shift it one char left. I would attempt another approach:
Create two iterators, like realPos and charPos. Set them to 0 at the beginning.
Create a variable, which stores a number of spaces encountered so far, like spacesSeen. Set it to 0.
Now, while realPos is lower than length of the whole string:
If string[realPos] != ' ' and charPos != realPos, make an assignment: string[charPos] = string[realPos]. Then increase both realPos and charPos by one. Set spacesSeen to 0.
If string[realPos] == ' ' and spacesSeen == 0, increase spacesSeen by one, copy characters and advance both iterators.
If string[realPos] == ' ' and spacesSeen > 0, then increase spacesSeen and then increase only realPos.
Now charPos marks the place where your final string ends, adjust strings size, such that it ends there.
In simpler words: copy the characters one by one and skip multiple spaces on the way.