// 32_32-9.cpp : コンソール アプリケーションのエントリ ポイントを定義します。
//

#include "stdafx.h"
#include <iostream>
#include <windows.h>

using namespace std;

class my_break {};	// break的用法のためのデータ型
class my_longjmp {};	// longjmp的用法のためのデータ型
class my_return {	// 関数return的用法のためのデータ型
public:
	int pos;
	my_return(int n) { pos = n; }
};

void find_ch(char *ss, char ch);
void breaktst();
void jmptst1();
void jmptst2();
void jmptst3();

// --------------------
// main関数
// --------------------
int _tmain(int argc, _TCHAR* argv[])
{
	cout << "-----代替break/goto機能を見る\n";
	breaktst();

	cout << "-----代替return機能を見る\n";
	try {
		find_ch("ABCDEFG", 'D');
	}
	catch (my_return e) {
		cout << "pos=" << e.pos << '\n';
	}
	cout << "-----代替longjmp機能を見る\n";
	try {
		jmptst1();
	}
	catch (my_longjmp) {
		cout << "-----jmptst end.\n";
	}
	
	MessageBox(NULL, _T("Check Console Window"), L"MessageBox", MB_OK);
	
	return 0;
}

// ------------------------------------------------------------
// throwをbreakもしくはgoto的に使う例
// ループの深層部から一気に脱出できることに注目
// ------------------------------------------------------------
void breaktst()
{
	int a, b, c, ans;

	try {
		for (a = 1; a <= 100; a++) {
			for (b = 1; b <= 100; b++) {
				for (c = 1; c <= 100; c++) {
					ans = a * b * c;
					if (a == 10 && b == 20 && c == 30) {
						throw my_break();
					}
				}
			}
		}
	}
	catch (my_break) {
		cout << "a=" << a << " b=" << b << " c=" << c << " ans=" << ans << '\n';
	}
}

// ------------------------------------------------------------
// throwをreturn的に使う例
// 文字列ssの中の文字chの位置を返す
// void型関数なのに値を戻せることに注目
// ------------------------------------------------------------
void find_ch(char *ss, char ch)
{
	int i;
	for (i = 0; ss[i]; ++i) {
		if (ss[i] == ch) {
			throw my_return(i);
		}
	}
	throw my_return(-1);
}

// ------------------------------------------------------------
// throwをsetjmp/longjmp的に使う例
// jmptst3から、jmptst2とjmptst1を経ずに直接呼び出し側に
// 戻っていることに注目
// ------------------------------------------------------------
void jmptst1()
{
	cout << "-----jmptst 1a\n";
	jmptst2();
	cout << "-----jmptst 1b\n";
}

void jmptst2()
{
	cout << "-----jmptst 2a\n";
	jmptst3();
	cout << "-----jmptst 2b\n";
}

void jmptst3()
{
	cout << "-----jmptst 3a\n";
	throw my_longjmp();
	cout << "-----jmptst 3b\n";
}