1

At the end of the program I output the contents of a vector, the strings were inputted from a text file. The entire vector is outputted, but how do I just output one word? I am asking this because I will later need to modify each string.

#include<iostream>
#include<fstream>
#include<vector>
#include<algorithm>
using namespace std;



int main(){ 

  ifstream in;
  string line, file_name;
  vector <string> phrase;
  int total_words, total_letters, total_chars;

  cout << "PIG LATIN PROGRAM" << endl; 

  cout << "Which file are you accessing? : ";
  cin >> file_name;

  in.open(file_name);

  if (in.fail()) cout << "\nFile not found!" << endl;


  while(getline(in, line)) phrase.push_back(line);



    for(int i = 0; i < phrase.size(); i++){

    int limit = phrase.size() - 1;
    while(i < limit &&  phrase[i] == phrase[i]){
        i++;

    }
       cout << phrase[i];


}   
Deduplicator
  • 44,692
  • 7
  • 66
  • 118
nb12345
  • 21
  • 4
  • `how do I just output one string?` I am not entirely sure what you mean but aren't you already output one string here: `cout << phrase[i];`? – DimChtz Apr 29 '18 at 00:25
  • There are multiple words in the text file. When I output phrase[i], it outputs every words. How do I output an individual word? – nb12345 Apr 29 '18 at 00:27
  • Okay, now I see what you mean. Your question should say: `how do I just output one WORD?` – DimChtz Apr 29 '18 at 00:29
  • Okay thank you, I fixed it. – nb12345 Apr 29 '18 at 00:31

2 Answers2

1

You could start by splitting the line in phrase[i] at points there's whitespace:

std::istringstream iss{phrase[i]};
std::vector<std::string> words;
std::string word;
while (iss >> word)
    words.push_back(std::move(word));

std::istringstream creates an input stream - a bit like cin - that contains the full line of text read from your file and stored in phrase[i]. If you then use >> word it will extract one whitespace-delimited word of text at a time.

Say your line/phrase[i] input contained "the blue socks were her favourites", it'll be split nicely into words. If there is also punctuation in the line, some of the strings in words will embed that punctuation, e.g. "world.". If you care about that, you can learn to use std::string member functions to search in and edit the strings.

In the case of punctuation you could use std::erase(std::remove_if(word.begin(), word.end(), std::ispunct), word.end()) to remove it (further details/explanation).

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • Why do you need move? –  Apr 29 '18 at 01:22
  • @GRC: it's a small optimisation. `std::string`s *sometimes* store their text in dynamically allocated memory, which is relatively slow to allocate with `new` and deallocate with `delete`, and if you *copy* such dynamically allocated text the destination `std::string` (being `push_back`-ed to `words`) needs to take the time to dynamically allocate its own buffer and copy all the characters across. By telling the compiler it can move `word`, you let the destination string steal any dynamically allocated buffer `word` already has the text in (word is typically left empty). – Tony Delroy Apr 29 '18 at 01:37
  • @GRC: that said, most C++ libraries use a "Short String Optimisation" - e.g. GCC will store up to 15 chars (excluding the implementation-added NUL) inside a `std::string` object, i.e. without dynamically allocating memory. Such "short" strings do not benefit from being allowed to be moved. Further, if we move from `word`, and a long string happens to be parsed from `iss` again, a moved-from `word` will need to do another dynamic allocation to store it, whereas if we'd copied `word` then it would still have a dynamically allocated buffer that *might* already be big enough to use as is. – Tony Delroy Apr 29 '18 at 01:42
  • Thank you, I changed this in my program, now how do I output a specific word from the file? If the file contained "This is an example sentence.", how would I output the word "example", or the word "is"? – nb12345 Apr 30 '18 at 13:40
  • @nb12345: that depends. Why would you output "example", or "is"? Because they're the 4th and 2nd words? Will your program always print the fourth and second words, or will it read which ones to print from somewhere like the command line, i.e. you typing `my_program 4 2`. Or will you search for "example" in the file and printing it if you find it anywhere, then the same for "is"? Until you answer such questions, we can't tell you how to do it. We've already told you how to read the lines from the file and extract each word from them, but how are we supposed to know which words to print? – Tony Delroy Apr 30 '18 at 13:50
0

phrase[i] == phrase[i]
Well, that's just redundant. This will always return true for a vector holding strings.

for(int i = 0; (...); i++){
   while( (...) ){
       i++;
   }
}

You are modifying variable i twice in this a single for loop. Once in the third parameter of for, and once in an inner while loop. It's almost never a good idea.

What's happening here is that you set i=0, then immediately set it to point to the last element of a vector (as the second condition in while is always true).

Then you print this element to console, which is the last line of your text file.

What you want to do, is:
1. Load text file line by line into a vector.
2. Each element of vector will hold a single line.
3. Split each line into a vector of WORDS (space separated).
4. Work with the resulting vector.

Or pheraps:
1. Load file word by word at the beginning.

vector<string> words; 
copy( istream_iterator<string>{YourFileStream}, istream_iterator<string>{}, back_inserter{words} ); // this will copy the content of file directly into vector, white-space-separated (no need for while loop to do it)
for ( auto i = phrase.begin(); i != phrase.end(); ++i ) // it's the proper c++ way of iterating over a vector. very similar, but variable i will point to every element of vector in order ( not just to the index of an element )
{
      // do some work on *i. at least: 
      std::cout << *i; // dereference operator (*) is needed here, since i doesn't hold index of an element, it's a "pointer" to an element
}

If you need the first approach ( to differentiate between words in different lines ), here you can find some excellent ways to separate a string by any delimeter (space, for example): The most elegant way to iterate the words of a string

MkjG
  • 144
  • 2
  • 15