質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

1010閲覧

キューによる配列の操作

program777

総合スコア7

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/06/20 07:10

以下の main 関数が動作するように、string 型のデータを格納する Queue クラスのプログラムを作成する問題です。但し、環状配列を動的に拡張する実装を想定しているため、Queueクラスに関して、以下のデータメンバとメンバ関数を持つことを 条件としています。
class Queue{
string *data; //データが格納されているメモリへのポインタ
int num; //有効なデータの数。配列要素の数。
int head; //リングバッファの配列上の開始位置。キューの先頭データの位置を表す。     int memorysize; //dataの指す配列の大きさ。
public :
Queue(int); //引数で指定された大きさの配列を動的に確保し、必要な初期値を設定する。     ~Queue(); //デストラクタ。dataが指しているメモリをすべて開放する。
bool empty(); //有効なデータ数が 0のときtrueを返し、それ以外で false を返す     void push_back(string); //引数のデータをキューの末尾に追加。有効なデータ数と配列の大きさが等しい状態で、データを追加する際には、配列の大きさを倍にする。
string front(); //キューの先頭データの値を返す
void pop_front(); //キューの先頭データを削除する
int size(); //配列の大きさではなく、有効なデータ数を返す。
void print(); //有効なデータ数、先頭データの位置、0から
memorysize-1 番目の配列dataの値を出力
//その他、必要なメンバ関数・フレンド関数の宣言など
};

int main(){
Queue queue(5);
string tmp;

  queue.push_back("1"); //①

    queue.print();
queue.push_back("2"); //②
queue.print();
queue.push_back("3"); //③
queue.print();

 queue.pop_front(); //④

   queue.print();
tmp=queue.front();
cout << "The first element of the queue is " << tmp << ".¥n";
queue.pop_front(); //⑤
queue.print();
queue.pop_front(); //⑥
queue.print();

 queue.push_back("1"); //⑦ queue.print(); queue.push_back("2"); //⑧ queue.print(); queue.push_back("3"); //⑨ queue.print(); queue.push_back("4"); //⑩ queue.print(); queue.push_back("5"); //⑪ queue.print(); queue.push_back("6"); //⑫ queue.print(); return 0;

}


実行結果は以下の通りです。
num:1, head:0, data:1 0 0 0 0
num:2, head:0, data:1 2 0 0 0
num:3, head:0, data:1 2 3 0 0
num:2, head:1, data:1 2 3 0 0
The first element of the queue is 2.
num:1, head:2, data:1 2 3 0 0
num:0, head:3, data:1 2 3 0 0
num:1, head:3, data:1 2 3 1 0
num:2, head:3, data:1 2 3 1 2
num:3, head:3, data:3 2 3 1 2
num:4, head:3, data:3 4 3 1 2
num:5, head:3, data:3 4 5 1 2
num:6, head:0, data:1 2 3 4 5 6 0 0 0 0
All the elements (10) are released.


** 以下自分で作成したコードです。**
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
class Queue{
string *data; //データが格納されているメモリへのポインタ
int num; //有効なデータの数。配列要素の数。
int head; //リングバッファの配列上の開始位置。キューの先頭データの位置を表す。
int memorysize; //dataの指す配列の大きさ。
public :
Queue(int);//引数で指定された大きさの配列を動的に確保し、必要な初期値を設定する。
~Queue(){ //デストラクタ。dataが指しているメモリをすべて開放する。
delete[] data;
};
bool empty(); //有効なデータ数が 0のときtrueを返し、それ以外で false を返す
void push_back(string); //引数のデータをキューの末尾に追加。有効なデータ数と配列の大きさが等しい状態
//で、データを追加する際には、配列の大きさを倍にする。
string front(); //キューの先頭データの値を返す
void pop_front(); //キューの先頭データを削除する
int size(); //配列の大きさではなく、有効なデータ数を返す。
void print(); //有効なデータ数、先頭データの位置、0から memorysize-1 番目の配列dataの値を出力
//その他、必要なメンバ関数・フレンド関数の宣言など
};

Queue::Queue(int n){
head=0;
num=0;
memorysize=n;
data= new string[memorysize];
}
bool Queue::empty(){
if(num==0)
return true;
else
return false;
}

void Queue::push_back(string st){
string *Head = new string[memorysize];
//if(num==memorysize){
//string tmp = new string[memorysize2];

//else{ Head[(head+num)%memorysize] = st; string HeadOfResult = Head[head]; //}

}

string Queue::front(){
string *Head = new string[memorysize];
Head = data;
string HeadOfResult = Head[head];
delete[] Head;
return HeadOfResult;
}

void Queue::pop_front(){
if (empty()) {
return;
}
int tmp = head;
head = head + 1;
string Head = new string[memorysize];
Head[tmp] = data;
string
HeadOfResult = Head[tmp];
delete HeadOfResult;
}

int Queue::size(){
return num;
}

void Queue::print(){
int tmp = head;
string *Head = new string[memorysize];
Head[tmp] = data;
while(Head[tmp]!=NULL){
cout << *Head[tmp];
tmp = tmp+1;
}
cout << endl;
}

int main(){
Queue queue(5);
string tmp;

queue.push_back("1"); //① queue.print(); queue.push_back("2"); //② queue.print(); queue.push_back("3"); //③ queue.print(); queue.pop_front(); //④ queue.print(); tmp=queue.front(); cout << "The first element of the queue is " << tmp << ".¥n"; queue.pop_front(); //⑤ queue.print(); queue.pop_front(); //⑥ queue.print(); queue.push_back("1"); //⑦ queue.print(); queue.push_back("2"); //⑧ queue.print(); queue.push_back("3"); //⑨ queue.print(); queue.push_back("4"); //⑩ queue.print(); queue.push_back("5"); //⑪ queue.print(); queue.push_back("6"); //⑫ queue.print(); return 0;

}

今のところコンパイルは通りますが、実行すると何も起きず終了してしまいます。
配列の動的確保の仕方と環状配列によるhead、num(有効数字)の動かし方を全くつかいこなせて
いない気がします、、、
また、配列の中に含まれているデータの長さを用いて、enqueue,dequeueを行いたいですが、
データの長さを求めるメンバ関数をどのようにに定義して、どのように使っていけばいいのかもわかりません。
アドバイスあればお願いします。


【参考】
・環状配列手順
1.データの先頭を指す変数を導入する
2. 最後尾(head+データ長)の位置にデータを追加する
2'.(head+データ長)%momerysizeの位置にデータを追加する

また、データ長がmemorysize以上になった時の対処法としては、
1.例えば、momerysizeの2倍の領域Headを別に確保する
2.headの位置から順番にデータをHeadに複製する
3.dataが指し示している配列領域をまとめて解放した後に、Headに格納されているアドレスをdataに複製する
4.head,memorysizeを更新する
5.(head+データ長)%momerysizeの位置に新しい数値を追加する

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

yumetodo

2020/06/20 11:18

Markdownにはソースコードをハイライトする記法がありますからそれで書いてください。
guest

回答1

0

ベストアンサー

そもそもなんですけど、環状配列になってないですよね。なんでこんなあちこちnewしてるんですか?環状配列というなら、メモリー確保はただ一回しかいらないはずですよね?
だから

1.データの先頭を指す変数を導入する
2. 最後尾(head+データ長)の位置にデータを追加する

の時点ですでにおかしいです。範囲外参照ですから未定義動作です。

また、データ長がmemorysize以上になった時の対処法としては、

そんな状況は単に例外を投げるべきです。


もっというと、C++でnew/deleteは書くべきではありません。std::unique_ptrを使ってください。

投稿2020/06/20 11:25

編集2020/06/20 11:27
yumetodo

総合スコア5850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

episteme

2020/06/20 11:32

さらに言えば 「自作するな、std::queue 使え」なんよなー
yumetodo

2020/06/20 14:17

いやまあそこはqueueの勉強のために再発明してるのかもしれないし・・・
episteme

2020/06/20 14:24 編集

だったらせめてstd::listを基にですね... 可変長配列からqueue作るのが良手には思えんのよ。
yumetodo

2020/06/20 14:24

リングバッファベースにやりたいって言ってるんだからそれは違うような。boost::circular_buffer使えって言うならまだしも
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問