-1

我正在尝试计算来自用户的文本文件中的单词数,将它们写入向量,然后输出一个文本文件,其中第一行的单词数和后续行由向量中的单词组成,显示按排序顺序。有什么想法有什么问题吗?

#include <iostream>
#include  <iomanip>
#include <vector>
#include <string>
#include <fstream>
#include <algorithm>
#include <stdio.h>
#include <ctype.h>

using namespace std;

//gets user input for file names to open/write to
string getUserInput (string inputORoutput) {
  cout << "Enter desired " << inputORoutput << " filename (include file extension). ";
  string userInput;
  getline(cin,userInput);
  return userInput;
}
//ensures that string word is an alphabetical word
string isAlpha (string& word) {
  string newWord;
  for (int i = 0; i < word.length(); i++) {
    if (isalpha(word[i])) {
      newWord += word[i];
    }
    else if (isspace(word[i])) {
      word[i] = word[i+1];
    }
    else {
      newWord = "";
    }
  }
  return newWord;
}
//removes empty elements of uniqueWords
void removeEmptyLines (vector<string>& uniqueWords) {
  for (int i = 0; i < uniqueWords.size(); i++) {
    if (uniqueWords [i] == "") {
      uniqueWords.erase(uniqueWords.begin() + i);
    }
  }
}
//calls isAlpha, calls removeEmptyLines, & sorts uniqueWords in alphabetical order
void sortUniqueWords (vector<string>& uniqueWords) {
  sort (uniqueWords.begin(), uniqueWords.end());
  for (int i = 0; i <= uniqueWords.size(); i++) { //remove this loop if digits are allowed
    uniqueWords[i] = isAlpha(uniqueWords[i]);
  }
  removeEmptyLines(uniqueWords); //remove this loop if digits are allowed
  if (uniqueWords.size() == 2) { //alpha.txt wont work without this
    uniqueWords [1] = "";
  }
}
//adds a new unique word to uniqueWords vector
void addUniqueWord (vector<string>& uniqueWords, string lineToAdd) {
  bool doesContain = false;
  int i = 0;
  while (i <= uniqueWords.size() && !doesContain) {
    if (lineToAdd == uniqueWords [i]) {
      doesContain = true;
    }
    else {
      i++;
    }
  }
  if (!doesContain) {
    uniqueWords.push_back(lineToAdd);
  }
}

int main(int argc, const char * argv[]) {
  vector<string> uniqueWords(1); //for some reason the program produces error EXC_BAD_ACCESS (code=1, address=0x0)
  string fileName;
  ifstream inFile;
  inFile.open(getUserInput("input"));
  string currentLine = "";
  while (getline(inFile, currentLine)) { //reads input and tests for failure
    addUniqueWord (uniqueWords, currentLine);
  }
  uniqueWords.erase(uniqueWords.begin() + 1);
  uniqueWords.erase(uniqueWords.begin());
  sortUniqueWords (uniqueWords);
  inFile.close();
  ofstream outFile;
  outFile.open(getUserInput("output"));
  for (int i = 0; i <= uniqueWords.size(); i++) {
    outFile << uniqueWords[i] << endl;
  }
  return 0;
}
4

2 回答 2

2

在我看来,与其尝试修复此代码,不如从头开始,创建更简单、更高效的东西会容易得多。

完全清楚(至少对我来说)你的目标是什么,但我假设它是读取输入文件,找到唯一单词,并显示唯一单词的数量,然后是它们的排序列表。您显然只想将连续的字母字符字符串视为单词。假设是这样,我会以不同的方式完成这项工作。首先,我将创建一个 ctype facet,将字母分类为字母,其他所有内容为“空格”:

struct alpha_only: std::ctype<char> {
    alpha_only(): std::ctype<char>(get_table()) {}

    static std::ctype_base::mask const* get_table() {
        // As far as we care, everything is white-space:
        static std::vector<std::ctype_base::mask> 
            rc(std::ctype<char>::table_size,std::ctype_base::space);

        // except letters:
        std::fill(&rc['a'], &rc['z'], std::ctype_base::alpha);
        std::fill(&rc['A'], &rc['Z'], std::ctype_base::alpha);
        return &rc[0];
    }
};

然后,我不会尝试过滤,以便在读取向量时仅将唯一单词插入到向量中,而是将所有单词插入向量中,然后对其进行排序并使其唯一:

int main() { 
    // For simplicity, we'll just read from standard input.   
    std::cin.imbue(std::locale(std::locale(), new alpha_only));

    // Initialize vector from file:
    std::vector<std::string> words((std::istream_iterator<std::string>(infile)),
                                    std::istream_iterator<std::string>());

    // erase the non-unique words
    words.erase(std::unique(words.begin(), words.end()), words.end);

    // Show the number of unique words:
    std::cout << "Number of unique words: " << words.size();

    // show the words:
    for (auto const & s : words)
        std::cout << s << "\n";
    return 0;
}

如果你真的想确保只存储唯一的单词,那可以更简单地完成(尽管它可能会更慢)。如果您正在处理大文件(尤其是有很多重复文件),您可能更喜欢std::unordered_set,然后复制到向量并排序。

int main() { 
    // For simplicity, we'll just read from standard input.   
    std::cin.imbue(std::locale(std::locale(), new alpha_only));

    // Initialize vector from file:
    std::set<std::string> words((std::istream_iterator<std::string>(infile)),
                                 std::istream_iterator<std::string>());

    // Show the number of unique words:
    std::cout << "Number of unique words: " << words.size();

    // show the words:
    for (auto const & s : words)
        std::cout << s << "\n";
    return 0;
}
于 2013-06-09T06:05:12.787 回答
0

该程序的问题在于您将所有内容放在一起,而没有花时间了解任何单个步骤的后果/副作用,因此,您并不完全清楚该程序的所有功能。结果,我们这些阅读它以尝试帮助您的人在大多数步骤中都不知道您实际上打算做什么。例如 main 的第一行

vector<string> uniqueWords(1); //for some reason the program produces error EXC_BAD_ACCESS (code=1, address=0x0)

该错误意味着您有一个空指针,它与这一行无关。看起来您甚至不确定如何使用调试器。

这一行所做的只是创建一个包含一个空字符串的向量。为什么你希望你的向量以一个空字符串开始?当你开始这样做时,它似乎只会在稍后回来咬你

uniqueWords.erase(uniqueWords.begin() + 1);
uniqueWords.erase(uniqueWords.begin());

那里——那是纯的、坚实的、错误代码的黄金。如果您为某人工作,那么该代码将有理由被解雇。

实际上,我在您的部分代码中看到了一些有希望的做法,假设这些做法不是从其他地方复制的,我的建议是:停止。删除所有代码,然后重新开始。迭代工作:花时间了解每个步骤是如何工作的,以便您可以正确地整合它。使用调试器遍历您的代码,不仅观察代码流,而且观察数据流。查找std::vector并了解它的实际工作原理,当您在那里时,请查看其他选项,例如 std::hash。

于 2013-06-09T07:28:41.123 回答