【问题标题】:Reading words from a file into dynamically allocated array将文件中的单词读入动态分配的数组
【发布时间】:2021-12-16 05:43:42
【问题描述】:

所以我试图将文件中的字符串数据读取到动态分配的数组中,但我似乎无法获得这样做的正确代码。我在下面有一个使用预设大小的数组的代码,但这效率不高,因此我想使用动态内存分配。我知道我必须使用指针,但我对这个概念还很陌生,因此我们将不胜感激。

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

#define SIZE 100

using namespace std;

void loadData();

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

        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(fileName);
        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); });
            }
        }
        dataFile.close();
    }
}

【问题讨论】:

  • std::vector&lt;std::string&gt; 怎么样?
  • 互联网上肯定有数百个例子。有什么你已经尝试过的吗?
  • return 0; main() 的第二行会导致程序结束。不确定为什么要把那里放在那里。我也不确定 loadData() 实际完成了什么,因为它没有任何参数。
  • 我知道我必须使用指针 -- 不,你不必使用指针。 std::vector&lt;std::string&gt; 使您不必使用指针。

标签: c++ file pointers dynamic-arrays


【解决方案1】:

below 程序展示了如何存储从 input.txt 文件中读取的字符串,并将它们以小写形式存储在 std::vector 中。

版本 1:将逐字(小写)存储到向量中


#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <sstream>
int main()
{
    std::ifstream inputFile("input.txt");
    
    //create vector that will contain the words in the file in lowercase 
    std::vector<std::string> wordVec;
    
    std::string line, individualWord;
    
    if(inputFile)
    {
        while(std::getline(inputFile, line, '\n'))
        {
            std::istringstream ss(line);
            while(ss >> individualWord)//word by word
            {
                std::transform(individualWord.begin(), individualWord.end(), individualWord.begin(),
                [](unsigned char c)
                { return std::tolower(c); 
                    
                });
                
                wordVec.push_back(individualWord);
            }
            
        
            
        }
    }
    else 
    {
        std::cout<<"file could not be opened"<<std::endl;
    }
    inputFile.close();
    
    //lets print out the elements of the vector to check if elements are correctly stored in lowercase 
    for(const std::string &elem: wordVec)
    {
        std::cout<<elem<<std::endl;
    }
    return 0;
}

版本1的输出可见here

版本 2:将完整的单行(小写)存储到向量中

#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
int main()
{
    std::ifstream inputFile("input.txt");
    
    //create vector that will contain the words in the file in lowercase 
    std::vector<std::string> wordVec;
    
    std::string line;
    
    if(inputFile)
    {
        while(std::getline(inputFile, line, '\n'))
        {
            std::transform(line.begin(), line.end(), line.begin(),
            [](unsigned char c)
            { return std::tolower(c); 
                
            });
            
            wordVec.push_back(line);
        
            
        }
    }
    else 
    {
        std::cout<<"file could not be opened"<<std::endl;
    }
    inputFile.close();
    
    //lets print out the elements of the vector to check if elements are correctly stored in lowercase 
    for(const std::string &elem: wordVec)
    {
        std::cout<<elem<<std::endl;
    }
    return 0;
}

上面(版本2)程序的输出可以看到here

版本 1 和 2 之间的区别是版本 1 读取完整的一行,然后逐字读取 并将这些单词(以小写形式)存储到 @987654327 @ 而版本 2 读取完整的行(以 '\n' 结尾)并将该行(以小写形式)存储到 std::vector

【讨论】:

  • 很抱歉未能达到您的期望。我会努力提高自己,努力变得更熟练地使用 C++。感谢您提示解决问题的 3 或 4 个语句可能太复杂了。我添加了一个额外的解决方案,只需要 2 个语句。再次感谢您。
【解决方案2】:

有时生活会很轻松。通过使用现代 C++ 元素,最终实现将非常简单。

我不太确定我应该为 3 行代码解释什么。用代码中的cmets基本可见。

请看第一个解决方案:

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cctype>

int main() {

    // Open the input file and check, if it could be opened
    if (std::ifstream inputStream{ "r:\\input.txt" }; inputStream) {

        // Define a vector and read all words from the file
        std::vector words(std::istream_iterator<std::string>(inputStream), {});

        // Show result to the user
        std::copy(words.begin(), words.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
    }
}

然后下一个解决方案将单词转换为小写。所以,我不得不写 4 个陈述。请参阅下面的第二个解决方案。

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <cctype>

int main() {

    // Open the input file and check, if it could be opened
    if (std::ifstream inputStream{ "r:\\input.txt" }; inputStream) {

        std::vector<std::string> words{};

        // Read all words from the file and convert to lower case
        std::transform(std::istream_iterator<std::string>(inputStream), {}, std::back_inserter(words), 
            [](std::string w) { for (char& c : w) c = std::tolower(c); return w; });

        // Show result to the user
        std::copy(words.begin(), words.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
    }
}

如果不需要存储数据,我们可以提出一个 2-statement 版本。

#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
#include <iterator>
#include <cctype>

int main() {

    // Open the input file and check, if it could be opened
    if (std::ifstream inputStream{ "r:\\input.txt" }; inputStream) {

        // Read all words from the file and convert to lower case and output it
        std::transform(std::istream_iterator<std::string>(inputStream), {}, std::ostream_iterator<std::string>(std::cout, "\n"),
            [](std::string w) { for (char& c : w) c = std::tolower(c); return w; });
    }
}

有时老师希望学生使用指针学习动态内存管理。

但强烈建议不要使用拥有内存的指针。十多年前,std::vector 就是出于这个原因发明的。

无论如何,我也会展示一个使用new 的解决方案。它有效,但你不应该使用它。

int main() {

    // Open the input file and check, if it could be opened
    if (std::ifstream inputStream{ "r:\\input.txt" }; inputStream) {

        // Do some initial allocation of memory
        std::string* words = new std::string[1]{};
        unsigned int numberOfAvaliableSlotsInDynamicArray{1};

        // Now we want to read words. We want also to count the words,so that we can allocate appropriate memory
        std::string word{};
        unsigned int wordCounter{};

        // Read all words in a loop
        while (inputStream >> word) {

            // Check, if we still have enough space in our dynamic array
            if (wordCounter >= numberOfAvaliableSlotsInDynamicArray) {

                // Oh, we are running out of space. Get more memory
                numberOfAvaliableSlotsInDynamicArray *= 2;
                std::string* temp = new std::string[numberOfAvaliableSlotsInDynamicArray]{};

                // Copy all existing data into new array
                for (unsigned int i{}; i < wordCounter; ++i)
                    temp[i] = words[i];

                // Delete old memory
                delete[] words;

                // And assign new storage to words
                words = temp;
            }
            // STore the recently read word at the end of the array
            words[wordCounter] = word;

            // Count words. Now we have one word more
            ++wordCounter;
        }
        // Now we have read all words from the file. Show output
        for (unsigned int i{}; i < wordCounter; ++i)
            std::cout << words[i] << '\n';

        // Release memory
        delete[] words;
    }
}

即使是智能指针(如果有的话也应该用作指针)也不好。

也不应该使用以下内容。

#include <iostream>
#include <fstream>
#include <string>
#include <memory>

int main() {

    // Open the input file and check, if it could be opened
    if (std::ifstream inputStream{ "r:\\input.txt" }; inputStream) {

        // Do some initial allocation of memory
        std::unique_ptr<std::string[]> words = std::unique_ptr<std::string[]>(new std::string[1]);
        unsigned int numberOfAvaliableSlotsInDynamicArray{ 1 };

        // Now we want to read words. We want also to count the words,so that we can allocate appropriate memory
        std::string word{};
        unsigned int wordCounter{};

        // Read all words in a loop
        while (inputStream >> word) {

            // Check, if we still have enough space in our dynamic array
            if (wordCounter >= numberOfAvaliableSlotsInDynamicArray) {

                // Oh, we are running out of space. Get more memory
                numberOfAvaliableSlotsInDynamicArray *= 2;

                std::unique_ptr<std::string[]> temp = std::unique_ptr<std::string[]>(new std::string[numberOfAvaliableSlotsInDynamicArray]);

                // Copy all existing data into new array
                for (unsigned int i{}; i < wordCounter; ++i)
                    temp[i] = std::move(words[i]);

                // And assign new storage to words
                words = std::move(temp);
            }
            // STore the recently read word at the end of the array
            words[wordCounter] = word;

            // Count words. Now we have one word more
            ++wordCounter;
        }
        // Now we have read all words from the file. Show output
        for (unsigned int i{}; i < wordCounter; ++i)
            std::cout << words[i] << '\n';
    }
}

结论:使用std::vector

【讨论】:

    猜你喜欢
    • 2021-10-26
    • 2013-10-06
    • 2015-06-14
    • 1970-01-01
    • 2020-01-22
    • 2011-06-15
    • 2015-06-04
    • 2014-06-19
    • 2017-11-04
    相关资源
    最近更新 更多