0

I am trying to create a program where I could read string data from a file and store it into an array, but I want to skip any integers or non-letters and not read them into the array. Any ideas on how to do that?

This is my code:

#include <iostream>
#include <stream>
#include <iomanip>
#include <cstdlib>
#include <algorithm>
#include <cctype>
#include <string>

using namespace std;

void loadData();

int main()
{
    loadData();
    return 0;
}

void loadData()
{
    const int SIZE = 100;
    string fileName;
    std::string wordArray[SIZE];
    cout << "Please enter the name of the text file you want to process followed by '.txt': " << endl;
    cin >> fileName;

    ifstream dataFile; 
    dataFile.open(fileName, ios::in);
    if (dataFile.fail())
    {
        cerr << fileName << " could not be opened." << endl; //error message if file opening fails
        exit(-1);
    }
    while (!dataFile.eof())
    {
        for (int i = 0; i < SIZE; i++)
        {
            dataFile >> wordArray[i];

            for (std::string& s : wordArray) //this for loop transforms all the words in the text file into lowercase
                std::transform(s.begin(), s.end(), s.begin(),
                    [](unsigned char c) { return std::tolower(c); });

            cout << wordArray[i] << endl;
        }
    }
}
AbuDavid
  • 35
  • 2
  • 1
    This doesn't address the question, but get in the habit of initializing objects with meaningful values rather than default-initializing them and immediately overwriting the default values. In this case, that means changing `ifstream dataFile; dataFile.open(fileName, ios::in);` to `ifstream dataFile(fileName, ios::in);` Also, you don't need that second argument; `ifstream` is an input stream, so you don't need to tell it that that's what it is. `ifstream dataFile(fileName);` is sufficient. – Pete Becker Oct 29 '21 at 18:31
  • I don't like using `cin >> field`. I prefer to make use of getline and then parse the data myself. That's a little more work but gives you far better ability to perform error handling and do whatever else you want to do. – Joseph Larson Oct 29 '21 at 18:40
  • To help solve a future bug read [Why is iostream::eof inside a loop condition (i.e. `while (!stream.eof())`) considered wrong?](https://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-i-e-while-stream-eof-cons) – user4581301 Oct 29 '21 at 18:51

2 Answers2

0

Use copy_if:

for (std::string& s : wordArray) 
                std::copy_if(s.begin(), s.end(), s.begin(),
                    [](char& c) { c = std::tolower(c); return std::isalpha(c); });

Note that this may not be the most efficient code.

Captain Hatteras
  • 490
  • 3
  • 11
0

This is a scenario where regexes can come in handy.

They do require forward iterators though, so you need to read in the whole file at once before extracting words.

#include <iostream>
#include <iterator>
#include <fstream>
#include <regex>
 
std::string read_whole_file(const std::string& file_name) {
    std::ifstream file(file_name);

    return {std::istreambuf_iterator<char>(file),
            std::istreambuf_iterator<char>()};
}

int main()
{
    // ...
    auto file_data = read_whole_file(filename);

    std::regex word_regex("(\\w+)");

    auto words_begin =
        std::sregex_iterator(file_data.begin(), file_data.end(), word_regex);

    auto words_end = std::sregex_iterator();
 
    for (auto i = words_begin; i != words_end; ++i) {
        std::cout << "found word" << i->str() << '\n';
    }
}