0

I'm having trouble adding white space to the 2D array "item". In the end, I essentially want the data in file (quote.txt) to be able to index properly with its line number. I've made the array 9(row) by 20(col) which is largest sentence in my file and where ever there are not 20 column units of data I want to populate it with a white space so I can index my array accordingly.

I've tried using vector of vectors but it gets super confusing.

  #include <iostream>
  #include <sstream> 
  #include <fstream>
  #include <vector>
  #include <array>
  #include <string>

  using namespace std;


  int main() 
  {
  string file_name;
  ifstream fin("quote.txt");
  while(!fin)
  {
      cout << "Error Opening File! Try again!" << endl;
      cout << "Enter file name: ";
      cin >> file_name;
  }
  string item[9][20];

  for (int row = 0; row < 9; row++) 
  {
      for (int col = 0; col < 20; col++)
      {
          fin >> item[row][col]; 
        //cout << item[row][col] << endl;

      }
  }
  for (int k = 0; k < 20; k++)
  {
    cout << item[0][k] << endl;
  }

  }

Explanation: I'm trying to populate my item 2d array with the contents in quote.txt but since the sentence length varies I cannot use for loop and say column is 20 units because it bleeds into the next row and screws up the indexing. My solution is that I want to add a white space (filler) so that I can iterate over with my for loop and every content in each row has 20 columns. That way I can use the index of rows to look at each row in the text file. Basically, I want the text file to be a 2D array in which I can find each element(word) through using [row][col] indices.

Text File: "quote.txt"

    People often say that motivation doesn  t last   Well   neither does bathing that s why we recommend it daily   Ziglar
    Someday is not a day of the week      Denise Brennan  Nelson
    Hire character   Train skill      Peter Schutz
    Your time is limited   so don t waste it living someone else s life      Steve Jobs
    Sales are contingent upon the attitude of the salesman      not the attitude of the prospect      W   Clement Stone
    Everyone lives by selling something      Robert Louis Stevenson
    If you are not taking care of your customer   your competitor will      Bob Hooey
    The golden rule for every businessman is this: Put yourself in your customer s place      Orison Swett Marden
    If you cannot do great things do small things in a great way    Napoleon Hill

What the Program is suppose to do?

The program is suppose to allow me to find a word by user input. say the word is "of" it is suppose to output which line numbers it is on. Similarly if I input "of People" it outputs the line number

  • 2
    Your file-open validation loop has a big flaw that could lead to an infinite loop: Nowhere in the loop do you reopen the file. – Some programmer dude Nov 27 '19 at 08:16
  • 2
    And the link to your text file doesn't work (for me). If the file isn't big then copy-paste it into the question itself, otherwise show us a small excerpt from it. Questions should be, as much as possible, self-contained. – Some programmer dude Nov 27 '19 at 08:17
  • 2
    As for your problem, perhaps what you're really looking for is *dynamic arrays* whose size can be extended when needed? Then use [`std::vector`](https://en.cppreference.com/w/cpp/container/vector). [Read a whole line](https://en.cppreference.com/w/cpp/string/basic_string/getline) into a `std::string`. Put the line into a [`std::istringstream`](https://en.cppreference.com/w/cpp/io/basic_istringstream), and use [`std::istream_iterator`](https://en.cppreference.com/w/cpp/iterator/istream_iterator) to create the vector. – Some programmer dude Nov 27 '19 at 08:21
  • BTW the text file in the link you provide seems very unstructured, it's full of random spaces and most of punctuation is absent – Jabberwocky Nov 27 '19 at 08:25
  • Ok I've added the txt file to the post, please have look – Gorav Soni Nov 27 '19 at 08:25
  • Yes, that's my biggest problem. I am suppose to process the file with those random spaces in the middle. I've thought about using getline but just doesn't work out – Gorav Soni Nov 27 '19 at 08:26
  • Maybe you should explain what the program is supposed to do at the end of the day – Jabberwocky Nov 27 '19 at 08:27
  • The program is suppose to allow me to find a word by user input. say the word is "of" it is suppose to output which line numbers it is on. Similarly if I input "of People" it outputs the line number – Gorav Soni Nov 27 '19 at 08:28
  • @GoravSoni please [edit] your question and put all relevant information _there_. Your approach is all wrong, use `std::vector` as already mentioned. – Jabberwocky Nov 27 '19 at 08:28
  • should I use vector of vectors? I've tried that but I'm not quite sure how I can populate the matrices using the data I have – Gorav Soni Nov 27 '19 at 08:30
  • To expand on my previous comment about using `std::istream_iterator`... If you follow the link and read the reference it should tell you that it uses the normal input operator `>>` to read input from the stream. This will read space-delimited "words" when you use it with `std::string`, so the number of spaces between words doesn't matter. – Some programmer dude Nov 27 '19 at 08:31
  • If the number of lines in the input file could vary as well then a vector of vectors would be a good choice. – Some programmer dude Nov 27 '19 at 08:33
  • hmm.. very interesting I was thinking to add like a filler in the white space. But using a dynamic array with the input operator seems more logically clear. The "quote.txt" is fixed so 9 rows and 20 columns (at most). – Gorav Soni Nov 27 '19 at 08:35
  • Ok, I'm still kind of confused as to where to start. Creating 2D dynamic array looks way too complicated and if I happen to ignore the white spaces how can I iterate over the array properly because each line is different size. Please help @Someprogrammerdude – Gorav Soni Nov 27 '19 at 08:46
  • @Jabberwocky I'm lost – Gorav Soni Nov 27 '19 at 08:51

1 Answers1

3

I would probably do it something like this:

// The dynamic vector of strings from the file
std::vector<std::vector<std::string>> items;

std::string line;

// Loop to read line by line
while (std::getline(fin, line))
{
    // Put the line into an input string stream to extract the "words" from it
    std::istringstream line_stream(line);

    // Add the current line to the items vector
    items.emplace_back(std::istream_iterator<std::string>(line_stream),
                       std::istream_iterator<std::string>());
}

After this the items vector will contain all words on all lines. For example items[1] will be the second line, and items[1][2] would be the third word on the second line ("not" with the file contents you show).


Going by the stated purpose of the program (to find a word or a phrase in the file, and report which line numbers those are found on) you don't need to store the lines at all.

All you need to do is read each line into a string, replace all tabs and multiple spaces with a single space, and see if the word (or phrase) is found on that line. If it is found then store the line number in a vector. Then discard the current line as you read the next one.

After all of the file have been processed, just report the line-numbers from the vector.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • That's great already. We'd yet need to produce a 'square matrix', but with `std::vector`s, this is trivial: 1. Remembering maximum number of words yet while reading the lines 2. `for(auto& i : items) { i.resize(maxWords); }` – Aconcagua Nov 27 '19 at 09:06
  • @Aconcagua For the stated purpose (finding words in lines and reporting the line numbers) a square or rectangular matrix isn't really needed. To be honest for this there's really no need to store the contents of the file in memory at all. – Some programmer dude Nov 27 '19 at 09:13
  • Hm, I see, reading question again, this 'filling with whitespace' stuff just seems to be a (failed) workaround for not being able to detect line ends... – Aconcagua Nov 27 '19 at 09:16