// Ex8_15.cpp
// Extracting words from text
#include <iostream>
#include <iomanip>
#include <string>
using std::cin;
using std::cout;
using std::endl;
using std::ios;
using std::setiosflags;
using std::resetiosflags;
using std::setw;
using std::string;
// Sort an array of string objects
string* sort(string* strings, size_t count)
{
bool swapped(false);
while(true)
{
for(size_t i = 0 ; i < count-1 ; i++)
{
if(strings[i] > strings[i+1])
{
swapped = true;
strings[i].swap(strings[i+1]);
}
}
if(!swapped)
break;
swapped = false;
}
return strings;
}
int main()
{
const size_t maxwords(100);
string words[maxwords];
string text;
string separators(" \".,:;!?()\n");
size_t nwords(0);
size_t maxwidth(0);
cout << "Enter some text on as many lines as you wish."
<< endl << "Terminate the input with an asterisk:" << endl;
getline(cin, text, '*');
size_t start(0), end(0), offset(0); // Record start & end of word & offset
while(true)
{
// Find first character of a word
start = text.find_first_not_of(separators, offset); // Find non-separator
if(string::npos == start) // If we did not find it, we are done
break;
offset = start + 1; // Move past character found
// Find first separator past end of current word
end = text.find_first_of(separators,offset); // Find separator
if(string::npos == end) // If it's the end of the string
{ // current word is last in string
offset = end; // We use offset to end loop later
end = text.length(); // Set end as 1 past last character
}
else
offset = end + 1; // Move past character found
words[nwords] = text.substr(start, end-start); // Extract the word
// Keep track of longest word
if(maxwidth < words[nwords].length())
maxwidth = words[nwords].length();
if(++nwords == maxwords) // Check for array full
{
cout << endl << "Maximum number of words reached."
<< endl << "Processing what we have." << endl;
break;
}
if(string::npos == offset) // If we reached the end of the string
break; // We are done
}
sort(words, nwords);
cout << endl
<< "In ascending sequence, the words in the text are:"
<< endl;
size_t count(0); // Count of duplicate words
// Output words and number of occurrences
for(size_t i = 0 ; i<nwords ; i++)
{
if(0 == count)
count = 1;
if(i < nwords-1 && words[i] == words[i+1])
{
++count;
continue;
}
cout << setiosflags(ios::left) // Output word left-justified
<< setw(maxwidth+2) << words[i];
cout << resetiosflags(ios::right) // and word count right-justified
<< setw(5) << count << endl;
count = 0;
}
cout << endl;
return 0;
}
The code on line 106 doesn't really do anything does it? Cause even when I remove it I see no difference in the output, but when I change it to
setiosflags(ios::right)
I get slightly different output. Whats going on?
I would post the outputs for each except I cant really copy them from my console and if I tried to just type them, it would be in accurate because of the different spacing.
So does line 106 really matter, and what exactly happens when I change it to setiosflags(ios::right) and why?
Short answer, forget about setiosflags/resetiosflags and use cout << left and cout << right.
Longer answer:
There are three adjustment flags in every stream: the left flag, the right flag, and the internal flag.
If left is the only flag set, left-adjustment (pad-after mode) is used by output operations
If right is the only flag set, right-adjustment (pad-before mode) is used by output operations
if internal is the only flag set, internal fill is used (pad after the sign or after the 0x)
OTHERWISE, right-adjustment (pad-before mode) is used
At startup, all three flags are clear
After setiosflags(left), left flag is set and right/internal are clear
If you do resetiosflags(right) after that, nothing changes (right flag is cleared, left and internal are unchanged)
If you do setiosflags(right) after that, BOTH left and right flags are set, but under the "OTHERWISE" condition, right-adjustment is used by output.
If you don't want to have to decypher potentially confusing situations where multiple adjustment flags are set at the same time, use cout << left and cout << right.
I would post the outputs for each except I cant really copy them from my console and if I tried to just type them, it would be in accurate because of the different spacing.
For future reference, you can right click on the title bar of the console window and choose Edit -> Select all, then again Edit -> Copy.