【问题标题】:Concatenate two string arrays without using STL or vectors in C++在 C++ 中不使用 STL 或向量连接两个字符串数组
【发布时间】:2015-07-21 00:43:41
【问题描述】:

我正在自学 C++,因此这是一个糟糕的命名和超级简单的问题。我正在尝试在 C++ 中连接两个数组。数组是字符串类型。它们的构造函数允许它们的默认容量为 12。 所以基本上我正在尝试组合数组,以便我有一个能够容纳 24 个元素的数组。我不想使用向量,也不想使用 STL。阵列有一些项目,但它们并没有完全填满它们的容量。您将在下面找到代码。

这是我的 ArrayBag.h 类定义:

#ifndef _ARRAY_BAG
#define _ARRAY_BAG
#include "BagInterface.h"
#include <vector>


template<class ItemType>
class ArrayBag : public BagInterface<ItemType>
{
private:
    static const int DEFAULT_CAPACITY = 24; // the bag size a bit bigger to allow
                                            // adding bags.
    ItemType items[DEFAULT_CAPACITY];      // Array of bag items
    int itemCount;                         // Current count of bag items
    int maxItems;                          // Max capacity of the bag

    // Returns either the index of the element in the array items that
    // contains the given target or -1, if the array does not contain
    // the target.
    int getIndexOf(const ItemType& target) const;

public:
    ArrayBag();
    int getCurrentSize() const;
    bool isEmpty() const;
    bool add(const ItemType& newEntry);
    void clear();
    bool remove(const ItemType& anEntry);
    bool contains(const ItemType& target) const;
    int getFrequencyOf(const ItemType& anEntry) const;
    std::vector<ItemType> toVector() const;
}; // end ArrayBag

#endif

这是我实际的类实现。

#include "ArrayBag.h"
#include <cstddef>

template<class ItemType>
ArrayBag<ItemType>::ArrayBag(): itemCount(0), maxItems(DEFAULT_CAPACITY)
{
}  // end default constructor

template<class ItemType>
int ArrayBag<ItemType>::getCurrentSize() const
{
    return itemCount;
}  // end getCurrentSize

template<class ItemType>
bool ArrayBag<ItemType>::isEmpty() const
{
    return itemCount == 0;
}  // end isEmpty

template<class ItemType>
bool ArrayBag<ItemType>::add(const ItemType& newEntry)
{
    bool hasRoomToAdd = (itemCount < maxItems);
    if (hasRoomToAdd)
    {
        items[itemCount] = newEntry;
        itemCount++;
    }  // end if

    return hasRoomToAdd;
}  // end add

template<class ItemType>
void ArrayBag<ItemType>::clear()
{
    itemCount = 0;
}  // end clear

template<class ItemType>
bool ArrayBag<ItemType>::remove(const ItemType& anEntry)
{
    int locatedIndex = getIndexOf(anEntry);
    bool canRemoveItem = !isEmpty() && (locatedIndex > -1);
    if (canRemoveItem)
    {
        itemCount--;
        items[locatedIndex]=items[itemCount];
    }//end if
    return canRemoveItem;
} //end remove

template<class ItemType>
bool ArrayBag<ItemType>::contains(const ItemType& anEntry) const
{
    bool found = false;
    int curIndex = 0; //current array index
    while(!found && (curIndex < itemCount))
    {
        if(anEntry == items[curIndex])
        {
            found = true;
        } //end if

        curIndex++; //increment to the next entry
    } //end while
    return found;
}

template<class ItemType>
int ArrayBag<ItemType>::getFrequencyOf(const ItemType& anEntry) const
{
    int frequency = 0;
    int curIndex = 0; //current index array
    while(curIndex < itemCount)
    {
        if (items[curIndex] == anEntry)
        {
            frequency++;
        } //end if

        curIndex++; //incremenet to next entry
    } //end while
    return frequency;
} //end getFrequencyOf


template<class ItemType>
vector<ItemType> ArrayBag<ItemType>::toVector() const
{
    vector<ItemType> bagContents;
    for (int i = 0; i < itemCount; i++)
        bagContents.push_back(items[i]);

    return bagContents;
}  // end toVector

ArrayBag<string> merge(const ArrayBag<string>& oneBag,
                       const ArrayBag<string>& anotherBag)
{
    int sizeOnebag, sizeAnotherbag, newBagsize;
         sizeOnebag = oneBag.getCurrentSize();
         sizeAnotherbag = anotherBag.getCurrentSize();
         newBagsize = sizeAnotherbag + sizeOnebag;

在上面,我获取了两个包的大小并创建了一个新的 int 来保存两个原始数组的大小。但从那里我不知道该怎么做。我试过下面的。但是每次都会收到编译器警告。

 ArrayBag<string> finalBag;

     int itemCount = finalBag.getCurrentSize();

     if (itemCount > newBagsize){
         newBagsize++;
         itemCount = finalBag.getCurrentSize();
         finalBag[itemCount];
     }

下面是 BagInterface.h

#ifndef _BAG_INTERFACE
#define _BAG_INTERFACE

#include <vector>
using namespace std;

template<class ItemType>
class BagInterface
{
public:
    /** Gets the current number of entries in this bag.
     @return The integer number of entries currently in the bag. */
    virtual int getCurrentSize() const = 0;

    /** Sees whether this bag is empty.
     @return True if the bag is empty, or false if not. */
    virtual bool isEmpty() const = 0;

    /** Adds a new entry to this bag.
     @post  If successful, newEntry is stored in the bag and
     the count of items in the bag has increased by 1.
     @param newEntry  The object to be added as a new entry.
     @return  True if addition was successful, or false if not. */
    virtual bool add(const ItemType& newEntry) = 0;

    /** Removes one occurrence of a given entry from this bag,
     if possible.
     @post  If successful, anEntry has been removed from the bag
     and the count of items in the bag has decreased by 1.
     @param anEntry  The entry to be removed.
     @return  True if removal was successful, or false if not. */
    // virtual bool remove(const ItemType& anEntry) = 0;

    /** Removes all entries from this bag.
     @post  Bag contains no items, and the count of items is 0. */
    virtual void clear() = 0;

    // I commented this out because I did not implement it.
    /** Counts the number of times a given entry appears in bag.
     @param anEntry  The entry to be counted.
     @return  The number of times anEntry appears in the bag. */

    virtual int getFrequencyOf(const ItemType& anEntry) const = 0;

     // I commented this out because I did not implement it.

    /** Tests whether this bag contains a given entry.
     @param anEntry  The entry to locate.
     @return  True if bag contains anEntry, or false otherwise. */


    virtual bool contains(const ItemType& anEntry) const = 0;

    /** Empties and then fills a given vector with all entries that
     are in this bag.
     @return  A vector containing all the entries in the bag. */
    virtual vector<ItemType> toVector() const = 0;

    virtual bool remove(const ItemType& anEntry) = 0;
}; // end BagInterface
#endif

这是我的主文件。

    #include <iostream>
#include <string>
#include "ArrayBag.h"

using namespace std;

void displayBag(ArrayBag<string>& bag)
{
    cout << "The bag contains " << bag.getCurrentSize()
    << " items:" << endl;
    vector<string> bagItems = bag.toVector();
    int numberOfEntries = (int)bagItems.size();
    for (int i = 0; i < numberOfEntries; i++)
    {
        cout << bagItems[i] << " ";
    }  // end for
    cout << endl << endl;
}  // end displayBag

void displayBag(ArrayBag<int>& bag)
{
    cout << "The bag contains " << bag.getCurrentSize()
    << " items:" << endl;
    vector<int> bagItems = bag.toVector();
    int numberOfEntries = (int)bagItems.size();
    for (int i = 0; i < numberOfEntries; i++)
    {
        cout << bagItems[i] << " ";
    }  // end for
    cout << endl << endl;
}  // end displayBag

int sumOfBag(ArrayBag<int>& aBag)
{
    int sum=0;
    vector<int> aBagvector = aBag.toVector();
    int numberOfEntries = (int) aBagvector.size();
    for (int i = 0; i < numberOfEntries; i++)
    {
        sum += aBagvector[i];
    }
    //cout << "The sum of the bag is " << sum << endl;
    return sum;
}

void bagTester(ArrayBag<string>& bag)
{
    cout << "isEmpty: returns " << bag.isEmpty()
    << "; should be 1 (true)" << endl;
    displayBag(bag);

    string items[] = {"one", "two", "three", "four", "five", "one"};
    cout << "Add 6 items to the bag: " << endl;
    for (int i = 0; i < 6; i++)
    {
        bag.add(items[i]);
    }  // end for

    displayBag(bag);

    cout << "isEmpty: returns " << bag.isEmpty()
    << "; should be 0 (false)" << endl;

    cout << "getCurrentSize: returns " << bag.getCurrentSize()
    << "; should be 6" << endl;

    cout << "Try to add another entry: add(\"extra\") returns "
    << bag.add("extra") << endl;
    displayBag(bag);
} // end bagTester


int main()
{
    ArrayBag<string> bag;
    cout << "Testing the Array-Based Bag:" << endl;
    cout << "The initial bag is empty." << endl;
    bagTester(bag);
    ArrayBag<string> bag_of_strings1;
    string items[] = {"tom","dick","harry"};
    for (int i=0; i<3; i++) {bag_of_strings1.add(items[i]);}
    displayBag(bag_of_strings1);
    ArrayBag<string> bag_of_strings2;
    string new_items[] = {"now","is","the","time","for","all"};
    for(int i=0; i<6; i++){
        bag_of_strings2.add(new_items[i]);
    }
    displayBag(bag_of_strings2);
    //ArrayBag<string> newbag=merge(bag_of_strings1,bag_of_strings2);

    //displayBag(newbag);

    ArrayBag<int> bag_of_ints;
    int array_of_ints[]={6,7,85,9,12,15};
    for (int i=0;i<6;i++){
        bag_of_ints.add(array_of_ints[i]);
    }
    displayBag(bag_of_ints);
    cout<<sumOfBag(bag_of_ints)<<endl;

    return 0;
} // end main

【问题讨论】:

  • 好吧,你找到我了。
  • 您收到什么警告,为什么会出现问题?
  • 我得到的警告是我没有为 ArrayBag 提供下标操作但是我不认为重载我的操作符是这里的解决方案。我确信有一个更简单的解决方案。
  • 我认为您需要有关实现 ArrayBag::merge 方法的帮助。对吗?
  • @KacheFlowe 说真的,编写代码来做这些类型的事情,除非你有 C++ 经验,否则并不像你想象的那么简单。它只是不适合初学者。数组不能在运行时调整大小。您需要创建自己的向量类来声明指针、分配内存、正确管理内存、毫无问题地释放内存、确保类是异常安全的等等。这需要大量的工作来了解和了解甚至在尝试这样的事情之前。

标签: c++ arrays concatenation abstract-data-type


【解决方案1】:

您可以将merge 声明为好友:

public:
friend ArrayBag<string> merge(ArrayBag<string> a, ArrayBag<string> b);
ArrayBag();
int getCurrentSize() const;
bool isEmpty() const;
...

然后像这样定义合并:

ArrayBag<string> merge(ArrayList<string> a, ArrayList<string> b) {
    int newsz = a.getCurrentSize() + b.getCurrentSize();
    if (newsz > a.DEFAULT_CAPACITY)
        // do something here
        abort();
    ArrayBag<string> result;
    for (int c=0; c<a.getCurrentSize(); ++c)
        result.add(a.items[c]);
    for (int c=0; c<b.getCurrentSize(); ++c)
        result.add(b.items[c]);
    return result;
}

当然,更简洁的方法是添加下标运算符:

T operator[](size_t x) const { return items[x]; }

那么您就不需要merge 成为朋友,只需将a.items[c]b.items[c] 替换为a[c]b[c]

【讨论】:

  • 我很抱歉,因为我实际上是在要求你把这个喂给我,但是我如何实际实现下标运算符?这就是我现在所拥有的: ArrayBag merge(ArrayBag a, ArrayBag b) { T operator[](size_t x) const { return items[x]; }
  • @KacheFlowe 您需要将声明放在您的类中,而不是 merge 函数中。
  • 我假设声明将是 .h 文件中的公共函数?
  • 是的。我将发布我的 BagInterface.h 和主文件。
【解决方案2】:

您还没有显示ArrayBag 的代码,但是如果您想合并两个 C 样式的数组,您必须创建一个包含 24 个元素的新数组并手动复制(如果使用 C++11,则移动或 C++14) 元素结束,然后删除旧数组。

顺便说一句,假设您使用的是 std::string,那么您已经在使用 STL。

【讨论】:

  • 对不起。我对此有点陌生。我还应该展示什么?
  • 所有相关代码。如果您不向我们展示ArrayBag,这里的任何人都应该知道它是什么?
  • 另外,这是否意味着我必须更改默认构造函数的容量?我想我的意思是使用诸如复制之类的 STL 方法。
  • 澄清一下,这是 C++11
猜你喜欢
  • 2016-02-24
  • 1970-01-01
  • 2015-09-14
  • 2012-10-05
  • 1970-01-01
  • 1970-01-01
  • 2015-03-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多