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

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

新規登録して質問してみよう
ただいま回答率
85.48%
アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

C++

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

Q&A

解決済

1回答

393閲覧

if (j <= list[i].ko.size() - 2) { cout << ",g "; }でjが0でlist[i].ko.size()-2が-1の時にcout << ",g ";が実行される

tada_tadaa

総合スコア111

アルゴリズム

アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

C++

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

0グッド

0クリップ

投稿2018/12/11 13:51

Tree - Rooted Trees
↑のアルゴリズムの問題を解いているのですが書いたプログラムの一部が変な動きをします。
以下に書いたプログラムを載せます。

c++

1#include <stdio.h> 2#include <string.h> 3#include <algorithm> 4#include <iostream> 5#include <string> 6#include <vector> 7#include <functional> 8#include <map> 9#include <iomanip> 10#include <math.h> 11#include <stack> 12#include <queue> 13#include <bitset> 14#include <cstdlib> 15#include <tuple> 16#include <cctype> 17#include <ctype.h> 18#include <set> 19#include <sstream> 20#include <time.h> 21using namespace std; 22//#define int long long 23#define rep(i,s,n) for(int i = s;i<n;i++) 24#define repe(i,s,n) for(int i = s;i<=n;i++) 25#define rrep(i,s,n) for(int i = (n)-1;i>=(s);i--) 26#define all(v) (v).begin(),(v).end() 27#define pb push_back 28#define fi first 29#define se second 30#define chmin(a,b) a=min((a),(b)) 31#define chmax(a,b) a=max((a),(b)) 32typedef long long ll; 33typedef pair<int, int>pint; 34typedef vector<int>vint; 35typedef vector<pint>vpint; 36typedef pair<pint, int> P1; 37typedef pair<int, pint> P2; 38typedef pair<pint, pint> PP; 39static const ll maxLL = (ll)1 << 62; 40const ll MOD = 1000000007; 41const ll INF = 1e18; 42const double PI = 3.14159265; 43int ca[12] = { 31,28,31,30,31,30,31,31,30,31,30,31 }; 44 45struct MyStruct 46{ 47 int parent = -1; 48 int depth; 49 vector<int>ko; 50}; 51 52 53signed main() { 54 int i, j; 55 int n; 56 vector<MyStruct>list(100005); 57 58 59 cin >> n; 60 61 for (i = 0; i < n; i++) { 62 int num, num2; 63 cin >> num >> num2; 64 65 for (j = 0; j < num2; j++) { 66 int num3; 67 cin >> num3; 68 list[num].ko.push_back(num3); 69 list[num3].parent = num; 70 } 71 72 } 73 74 75 for (i = 0; i < n; i++) { 76 int cnt = 0; 77 int num = list[i].parent; 78 79 while ( num != -1 ) 80 { 81 cnt++; 82 num = list[num].parent; 83 } 84 85 list[i].depth = cnt; 86 } 87 88 89 for (i = 0; i < n; i++) { 90 cout << "node " << i << ": parent = " << list[i].parent << ", depth = " << list[i].depth << ", "; 91 if (list[i].parent == -1) { 92 cout << "root, ["; 93 for (j = 0; j < list[i].ko.size(); j++) { 94 cout << list[i].ko[j]; 95 if (j <= list[i].ko.size() - 2) { cout << ",g "; } //←ここがおかしな動きをする 96 } 97 cout << "]" << endl; 98 } 99 else if (list[i].ko.size() >= 1) { 100 cout << "internal node, ["; 101 for (j = 0; j < list[i].ko.size(); j++) { 102 cout << list[i].ko[j]; 103 if (j <= list[i].ko.size() - 2) { cout << ", "; } 104 } 105 cout << "]" << endl; 106 } 107 else if (list[i].ko.size() == 0) { 108 cout << "leaf, []" << endl; 109 } 110 111 } 112 113 114 getchar(); 115 getchar(); 116 return 0; 117}

↑のプログラムに下記のデータを入力します。
2
0 1 1
1 0

すると以下のように出力されます。
node 0: parent = -1, depth = 0, root, [1,g ]
node 1: parent = 0, depth = 1, leaf, []

どうやらif (j <= list[i].ko.size() - 2) { cout << ",g "; }でjが0でlist[i].ko.size() - 2 が-1の時にcout << ",g ";が実行されるようです。条件式の通りに動くならjが0で右辺より大きいので実行されないような気がするのですがどうなっているのでしょうか。

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

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

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

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

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

guest

回答1

0

ベストアンサー

どうやらif (j <= list[i].ko.size() - 2) { cout << ",g "; }でjが0でlist[i].ko.size() - 2 が-1の時にcout << ",g ";が実行されるようです。

vector.sizeの返り値が符号なし整数で、オーバーフローを起こしているのでは。
条件式をj + 2 <= list[i].ko.size()にしてみてはいかがでしょう。

なお、カウンタの型を符号なし整数にした方が無用なトラブルを避けられそうです。

投稿2018/12/11 14:15

編集2018/12/11 14:21
LouiS0616

総合スコア35660

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

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

tada_tadaa

2018/12/11 14:29

回答ありがとうございます。 よく分かりませんが言われた通りにしてみるとうまく動きました。 上手く動いた if (j <= (int)list[i].ko.size() - 2) { cout << ",g "; } if (j + 2 <= list[i].ko.size()) { cout << ",g "; } 上手く動かない if (j <= list[i].ko.size() - 2) { cout << ",g "; } if (j <= (list[i].ko.size()) - 2) { cout << ",g "; } 今まではこのやり方で特に不具合が出ていなかったので思わぬ落とし穴って感じです。 ちなみに >なお、カウンタの型を符号なし整数にした方が無用なトラブルを避けられそうです。 とは変数 j を符号なし整数にした方が良いという事でしょうか?
tada_tadaa

2018/12/11 14:38

https://anond.hatelabo.jp/20090817145359 ↑ここに説明っぽいものが載っていました。 引用 ■C++ STLのvectorコンテナのsize()関数 醜悪なことにこいつの返り値はintではなくunsigned intのようだ。 従って、サイズ0のvectorに対して vec.size()-1 という演算をすると結果は-1ではなく、オーバーフローしてunsigned intの最大値になる。 サイズがゼロだったら-1になるだろjkとか思ってコーディングすると酷い目にあう。 引用終わり vector.size()の返り値がマイナスの値を受け付けないとは知りませんでした。いい勉強になりました。 ありがとうございました。
LouiS0616

2018/12/11 14:40

> よく分かりませんが言われた通りにしてみるとうまく動きました。 次のコードを実行してみると良いです。 unsigned int n = 1; std::cout << n - 2 << "\n"; --- > 変数 j を符号なし整数にした方が良い そのとおりです。 ついでに。カウンタ変数をmain関数のスコープで宣言する意味が無いので、for文の初期化部で宣言した方がすっきりしたコードになると思います。 文字数的には増えますが、幾分か動作を追いやすくなります。
tada_tadaa

2018/12/11 14:59

unsigned int n = 1; int n2 = 1; std::cout << n - 2 << "\n"; std::cout << n2 - 2 << "\n"; 結果 4294967295 -1 となりました。原因がよく分かりました。カウンタ変数に対するアドバイスもありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問