高度情報システム科 ブログ
高度情報システム科のブログ一覧 (全205件中 160件目~162件目を表示)
2018.12.26
Javaプログラミングコンテスト最優秀賞者のプログラムを見てみよう、第3弾です。
残っている処理は、与えられたIPアドレスのブロードキャストアドレスを求めることです。
int型の変数ipには現在、IPアドレスが数値として入っています。またint型の変数zには、サブネットマスクのサフィックス値が入っています。
たとえばIPアドレスが192.168.61.145/26であるとき、ブロードキャストアドレスは上位26ビットはそのまま、残りの6ビットはすべて1にしたものになります。
では、最優秀者のコードを見ていきます。
前回の処理で既に
char[] ipc = Integer.toBinaryString(ip).toCharArray();
を実行しています。char型の配列ipcには、ipを2進数にしたものを1桁ずつ区切って0か1を文字にしたものが格納されています。
ネットワークアドレスのときは、
for (int i = 31; i >= z; i--) ipc[i] = '0';
としましたが、ブロードキャストアドレスのときは
for (int i = 31; i >= z; i--) ipc[i] = '1';
とします。
あとは表示するだけですが、これもネットワークアドレスのときと一緒。
a = b = c = d = 0; for (int i = 0; i < 8; i++) { a += (ipc[i] - '0') << (7 - i); b += (ipc[i + 8] - '0') << (7 - i); c += (ipc[i + 16] - '0') << (7 - i); d += (ipc[i + 24] - '0') << (7 - i); } System.out.println(a + "." + b + "." + c + "." + d);
ちなみに、サブネットマスクとIPアドレスの論理積をとればネットワークアドレスが求まりますが、ブロードキャストアドレスの場合はサブネットマスクの0と1を反転したものとIPアドレスの論理和をとればよいです。
しかし今回のコードでは、あまり難しく考えずにシンプルに処理されていますね。
今回紹介したコードを繋げたものは以下のようになります。
String[] sp = str.split("[\\./]"); int a = Integer.parseInt(sp[0]); int b = Integer.parseInt(sp[1]); int c = Integer.parseInt(sp[2]); int d = Integer.parseInt(sp[3]); int z = Integer.parseInt(sp[4]); int ip = (a << 24) + (b << 16) + (c << 8) + d; char[] ipc = Integer.toBinaryString(ip).toCharArray(); for (int i = 31; i >= z; i--) ipc[i] = '0'; a = b = c = d = 0; for (int i = 0; i < 8; i++) { a += (ipc[i] - '0') << (7 - i); b += (ipc[i + 8] - '0') << (7 - i); c += (ipc[i + 16] - '0') << (7 - i); d += (ipc[i + 24] - '0') << (7 - i); } System.out.println(a + "." + b + "." + c + "." + d); for (int i = 31; i >= z; i--) ipc[i] = '1'; a = b = c = d = 0; for (int i = 0; i < 8; i++) { a += (ipc[i] - '0') << (7 - i); b += (ipc[i + 8] - '0') << (7 - i); c += (ipc[i + 16] - '0') << (7 - i); d += (ipc[i + 24] - '0') << (7 - i); } System.out.println(a + "." + b + "." + c + "." + d);
とにかくコンテストの短い時間でここまで書けたのが驚きだったので、3回に分けて紹介しました!
2018.12.19
これまでの記事
2か月ほど続けてきたプロジェクト開発演習もいよいよ大詰め。
今週はテスト工程を実施しています。
作成しておいたテスト仕様書に沿ってテストを行います。重要な作業です。
今回は2チームに分かれて開発を行ってきました。
チームMASHは、GR-LYCHEE(ライチ)を使用し、定点観測のようなシステムを開発してきました。時間とともに変わるもの(工事現場の進捗状況や植物の生育状況)を撮影し続けるような場面を考えています。
時刻設定してカメラの撮影、うまくできているでしょうか?
どうやら大丈夫そうです。
ある程度作りながら試しているので、大体はうまく動きます。
ただ、しっかりテストをしていくと、やはり不具合に遭遇します。
自分たちで解決できるのが一番ですが、どうしても企業の方に頼ってしまいます・・・。
丁寧に教えてもらっている様子。
一通りテストは終了しましたが、その後お互いのチームのテストも実施してみました。
第三者の目から評価を行うと、たとえば意図していなかった操作に気づいたりします。
どうやって品質を上げていくか、演習を通じて学べたでしょうか。
今回はやり残したこともあるので、今後の課題としてまた取り組んでいきます!
2018.12.15
Javaプログラミングコンテスト最優秀賞者のプログラムを見てみよう、第2弾です。
ネットワーク関連の問題の要点部は「文字列 str にIPv4アドレスがサブネットマスクのサフィックス付きで与えられたときに、ネットワークアドレスとブロードキャストアドレスを表示する」のが目標です。
前回の時点で、IPアドレスの上位から8ビットずつをint型のa、b、c、dに代入し、サブネットマスク(サフィックス値)をzに代入しました。
ここから、ネットワークアドレスを求めていきます。
int ip = (a << 24) + (b << 16) + (c << 8) + d;
ipに、IPアドレスを数値として入れました。
"<<"はシフト演算。
c << 8は、cを左に8ビットシフトした値になります。左に1ビットシフトすると2倍になるので、8ビットシフトすると256倍になります。
このあたり、知っていればどうってことはないのですが、一度は覚えていてもいざ使おうとなるとできるかどうか・・・。
ついつい、c * Math.pow(2, 8) とか b * Math.pow(2, 16)とやってしまいそうな気がします。
ipに32ビットの整数値を格納しましたが、int型は32ビットなので大丈夫です。
ここも、余裕を持ってlong型にしようとか考えそうになりますが、値として持てればいい、つまり正負の符号などを考えなくていいのでint型がぴったりですね。
同様にしてサブネットマスクを求めてint型にし、ipと論理積(&)をとればネットワークアドレスが求まります!
といきたいところですが、最優秀者のコードは違いました。
char[] ipc = Integer.toBinaryString(ip).toCharArray();
ipを一旦、2進数文字列に変換し、char型の配列に格納します。
さらに
for (int i = 31; i >= z; i--) ipc[i] = '0';
としました。
考えてみれば、ipを2進表記したときに下位zビットを0にセットするだけでいいですね。
当たり前のことですが、ネットワークアドレスを求めるときにサブネットマスクと論理積をとる、というふうに覚えているとこうした簡単なことに気づきづらいものです。
ついついまともにやってしまいそう・・・。
こうしてあっさり求めたネットワークアドレスを数値に戻します。
a = b = c = d = 0; for (int i = 0; i < 8; i++) { a += (ipc[i] - '0') << (7 - i); b += (ipc[i + 8] - '0') << (7 - i); c += (ipc[i + 16] - '0') << (7 - i); d += (ipc[i + 24] - '0') << (7 - i); }
プログラムは、それを作った人の思考経路が透けて見えるので面白いです。
たとえばaにはipアドレスの上位8ビットを入れたいのですが、各ビットはchar型の配列に'0'か'1'として入っているので、これを一旦数値に変換します。
このとき、char型は内部的に整数値になっているので、ipc[i] - '0'のように引き算ができます。'0'の次が'1'になっているので、これにより'0'は0に、'1'は1になります。
さらに最上位ビットであれば128倍、つまり左に7ビットシフトします。2番目のビットであれば、左に6ビットシフトし、…となるので、for文で繰り返し処理します。
そしてこれらを足し合わせるためにa += (右辺)としています。これはa = a + (右辺)と同じで、aに(右辺)を加えていくという意味になります。
これで数値に変換されますが、この部分は他にもいろいろなやり方がありそうです。
あとは表示するだけ。
System.out.println(a + "." + b + "." + c + "." + d);
見事でした。
もう一つのブロードキャストアドレスも、同じようにできそうですね。
詳しくは次回!