こんにちは.はじめて書き込みするtoroimoです.
私は,理工学系の大学院の修士課程に在学しています.
来春から社会人です.
プログラミング暦は,研究に取り組んでから2年半たちます.
使用言語はCです.
最近,自分のプログラミングのセンスというか技術について
考えてしまいます.
ある権威者の人は,プログラムは慣れであり,プログラミングは芸術といいます.
芸術であるがいえに万人が優れた美しいコードはかけないと…
それを聞いてはじめは落胆しました.
けれど,その後は少しでも優れたコードを書けるようにと
書籍・サイトを探り読んでいます.
私は,Cに関する初級本
改訂 新C言語入門 シニア編
など4冊,アルゴリズムに関しては,1冊.
また,日経ソフトウエアやC_MAGAZINEなどをよんで知識の習得に
勤める努力はしています(実力として初級はクリアしてると思うのですが.).
しかし,実際研究でコードを書くとなると
アルゴリズムに悩む時間ばかり費やし手が止まってしまう状態です.

こんな私に社会で働いている人(SEやプログラマ)や
学生の方から御叱咤・御忠告を賜りたいです.
どうかよろしくおねがいいたします.

このQ&Aに関連する最新のQ&A

A 回答 (7件)

一口に「プログラム」といっても、いろんなプログラムがあります。



出来云々を別にしても、そのプログラム自体が、「製品」である場合と、
そうじゃない場合、とか、消費されていく(寿命が短い)ものとして作られる
場合とか、そうじゃないとか。

> 万人が優れた美しいコードはかけないと…

というのはある程度納得できますが、ふつう綺麗だ、汚いだなんて言う対象の
プログラムのレベルだったら、センスの前に、まず技術、でしょう。

ただ、その「技術」を、万人が(ある程度)同じレベルにするための統一的な
方法がなく、センスの問題と片づけてしまっているということだと思います。


後、「技術」の前に「姿勢」という問題があると思ってます。

技術の修得に対するモチベーションの問題なのかもしれませんが、「動けば
良いや」っていうレベルに甘んじていると、いつまで経っても技術は向上しません。

そういう意味では、「技術を修得する為の姿勢が正しい」ということが「センス」
だったり「才能」だったりするのかも。

# なにも、プログラムに限った話ではないと思います


私が、自分でものびたなあと思った時期は「他人の汚いコードを保守・改造している」
ときでした。他人の綺麗なコードもあわせて読むのが更に良い。

でも、「研究でコードを書いている」という環境だと、ちょっと難しいかも。


> アルゴリズムに悩む時間ばかり費やし手が止まってしまう状態です

これは、単に「引き出しに入っているものの数が少ない」だけですね。

早い・遅いの差はありますが、経験だけでもそれなりにカバーできるし、それようの
勉強をすれば、アルゴリズムに悩む時間はどんどん少なくなっていきます。

絶対「ゼロ」にはなりませんけどね。

この回答への補足

a-kumaさん,なんかしみじみ読んでしまいました.

>技術の修得に対するモチベーションの問題なのかもしれませんが、「動けば
>良いや」っていうレベルに甘んじていると、いつまで経っても技術は
>向上しません。

ごもっともです.

>> アルゴリズムに悩む時間ばかり費やし手が止まってしまう状態です

>これは、単に「引き出しに入っているものの数が少ない」だけですね。
>早い・遅いの差はありますが、経験だけでもそれなりにカバーできるし、それようの 勉強をすれば、アルゴリズムに悩む時間はどんどん少なくなっていきます。

すみません,引き出しの中身を増やすには,どのような経験を積んでいったら
よいか御教示御願い致します.

補足日時:2001/08/15 19:25
    • good
    • 0

「動けばいいや」なレベルに甘んじている一研究者です(汗



どんなプログラムがいいプログラムかよくわかりませんが、
センスを磨くには#1の方がおっしゃるように、
とにかくたくさんコードを書いて動かしてみることですね。
その中でも、とりわけデバグ作業がいい訓練になるんじゃないかと思うんです。
このように書くと、「習うより慣れろ」という言葉を想像されるかもしれませんが、
より的確には、プログラミングに限らず「習って慣れろ」だと思うんですね。
だって、プログラミングの技術の中には、
知らなきゃどうしようもないことがいくらでもあるんですから。
で、じゃあ何から習うか、ですが、世の中には教科書はいくらでもあります。
「教科書」はなにも本屋で売っているような書籍に限定されません。
本が買えなきゃ、OSやコンパイラのソースをのぞいてみるのもいいかもしれません。

あと、余談ですが、「動けばいいや」っていうレベルに甘んじては・・・についてですが、
最近はプログラミングの環境が豊かになりすぎているので、
動きさえすれば実用上ほとんど問題が生じないのが実情です。
最新型パソコンですら64Kのメモリと8つの8ビットレジスタを駆使して・・・とかいう、
ある意味ハードウェアの限界まで使い切らなくてはならない時代には、
かなりセンスを磨くチャンスがあったんですけど。
もちろん当時の制御用マイコンはそれよりも条件が厳しかったのですが、
現代と当時の大きな違いは、限界を感じたことがあるか否か、だと思うんですね。
そういう意味で、限界を感じたことがあるから、
さらに限界が低いマシンでも限界の克服の仕方が身についていたからなんとかなったんじゃないか、と。
って、かなり言い訳っぽく聞こえますか・・・
    • good
    • 0
この回答へのお礼

k-841様,ご意見ありがとうございます.
まさか,研究者の方からアドバイスを頂けるとは,
このサイトのありがたさ及び,なんともいえぬ
喜びがあります.
さて,ご意見の方ですが,
>とにかくたくさんコードを書いて動かしてみることですね。
>その中でも、とりわけデバグ作業がいい訓練になるんじゃないかと思うんです。
うんうん,納得です.
私は参考書等のサンプルコードばかりを打ち込みその仕組みを理解する
といった方法で勉強してきました.
自分で考えたコードを実装し,デバックを通して成長するのですね.
うーーん,感動です.

>あと、余談ですが、「動けばいいや」っていうレベルに甘んじては・・・についてですが、
最近はプログラミングの環境が豊かになりすぎているので、
動きさえすれば実用上ほとんど問題が生じないのが実情です。


今日,CPUのスペックやDRAM,およびHDDの容量をみても
べらぼうに性能が向上していますね.

k-841さん,これからも勉強していく過程で
分からないことがあったらご意見を賜りたいので,
今後とも宜しく御願い致します.
ありがとうございました.

お礼日時:2001/08/17 14:35

センスや技術は身に付けられます。



芸術とか頂点とかそのあたりになると、私にも別世界ですが、そのレベルでなければ身につきます。

やり方としては,やはり人のソースを読むこと、
いろんな知識を身につけること,自分で考えてプログラムを
つくることでしょうか。

読むプログラムは良質な物の方がいいでしょう。
フリーウェアで昔からソースが公開されてきて定評のあるものがいいように思います。

知識としてはアルゴリズムの本とか、あとはコンピュータ自身のハードウェアとか、
OS内部の知識もあった方がいいでしょう。
直接直ぐに役立つことはないでしょうけど。


あと、余力があれば、C以外の言語、それもまったく違う
タイプの言語をやってみるといいように思います。
lispなんてやると、頭が固くならずいいかも。
    • good
    • 0
この回答へのお礼

terra5様,お返事ありがとう御座います。
>読むプログラムは良質な物の方がいいでしょう。
>フリーウェアで昔からソースが公開されてきて定評のあるものがいいように思います。

linuxなどのソースコードのことでしょうか?
ちょっと調べてみます.

私は特に,
>センスや技術は身に付けられます。
というterra5さんの言葉に感動しました.

自分の能力に限界さえ感じはじめていましたので,
この言葉に救われた気がいたします.
もっと視野を広げ勉強していきたいと思います.
貴重なご意見ありがとうございました.

なにかありましたら今後ともよろしく御願い致します.

最後にterra5さんのみならず,私の質問に対して
アドバイスをして頂いた方々にお礼をいいたいです.
ありがとうございました.

それでは.

お礼日時:2001/08/17 14:28

> すみません,引き出しの中身を増やすには,どのような経験を積んでいったら


> よいか御教示御願い致します.

「御教示」って程ではないのですが、私の経験談を。

純粋に「アルゴリズム」という引き出しの中身を一気に増やせたのは、本でした。
その当時は Turbo Pascal 使いだったのですが、奥村晴彦著の『コンピュータ・アルゴリズム事典』
という本にであって、いろいろ勉強になりました。

最近は C++ の STL のソース(とっても汚いですが)も勉強になりました。

他にも、コード集のサイトや本なんか、それこそ掃いて捨てるほどありますので、
引き出しの中身を増やすのに、それほどお金はかかりません。

とりあえずは、あまり有用かどうかを悩まずに乱読してみるのはどうでしょうか。
良い本やコード集に出会えると良いですね。

参考URL:http://www.matsusaka-u.ac.jp/~okumura/algo/
    • good
    • 0
この回答へのお礼

a-kuma様,お返事ありがとうございます.

>他にも、コード集のサイトや本なんか、それこそ掃いて捨てるほどありますの
>で、 引き出しの中身を増やすのに、それほどお金はかかりません。

>とりあえずは、あまり有用かどうかを悩まずに乱読してみるのはどうでしょうか。
>良い本やコード集に出会えると良いですね。

うーーん,納得です.そうですね,今ある環境をフルにいかすして
知識と増やし,またスキルをみがくための努力を継続していきたいと
思います.

お礼日時:2001/08/17 14:24

こういう回答はそれぞれの個人によって全然異なりますので、


自信ナシでいきます。

万人が優れた美しいコードは書けない…
これは、その通りだと思います。
才能のある人は最初から組んでくるコードが違いますね。
私が思うに
コンピュータに慣れ親しんだ人=コンピュータになりきれる人
のような気がします。
そのような人は、こう組んだらこう動くと言う事を分かりきって書いてきますので、
美しく無駄のないプログラムを組んできます。

で、誰でも最初は初心者な訳で、どうやってレベルアップしていくか
というと
人のソースをガンガン見る
といいと思います。
単純にテクニックをもらったり、それから発想の違いに驚くこともあります。
いい刺激になると思います。
そうしていくうちに、自分の書くコードがだんだん変わっていくのだと思います。

要するに
(1) コンピュータに関する知識をつける(慣れ親しむ)
(2) 人のコードを見た刺激により自分のコードを作り上げる
でしょうか。
    • good
    • 0
この回答へのお礼

mkiiさん,早速のアドバイスありがとうございます.
>(1) コンピュータに関する知識をつける(慣れ親しむ)
>(2) 人のコードを見た刺激により自分のコードを作り上げる
承知致しました.少し勉強の方法,プログラムを組む姿勢を
考え直します.

mkiiさん今後とも宜しく御願いします.

お礼日時:2001/08/15 16:57

こんにちは、honiyonです。



 決して参考書を読むな、とは言ってないという事を補足させて下さい(^^;
 参考書だけでは育たないよ、という事を言っています。
 参考書はあくまで「参考」なので、良き参考として上達のための糧として下さい。

 連続投稿ですいませんです(..
    • good
    • 0
この回答へのお礼

honiyonさん,人生の先輩として貴重なご意見を提示して頂きありがとうございます.
honiyonさんがおっしゃる通り,プログラムを組むことが「好き」な
人には,やはりかないませんね.吸収力というか,その取り組む姿勢というか.

私の周りの友人もSEやプログラマーになっています.
文系からでもべらぼうにプログラムを組める方がいらっしゃると
聞いています.

頭で考える(発想力)が私には足りないのでしょうね…
その発想力をつけるためには,どのような訓練をすればよいのか?
と日々考えるところでもあります.

しかし,honiyonさんがおっしゃっていたことは,
私にも通ずるところなので,なんとか頑張ってみたいと思います.
あらためてありがとうございました.

お礼日時:2001/08/15 16:02

こんにちは、honiyonです。


 
 現役プログラマーです。
 でも自分の実力に自信がないので経験者としていつも回答させて頂いてます(笑
 私の書くコードか美しいかどうかは分からないので回答して良いのか悩む所ですが、アドバイスとして回答してみます(^^;

 その「ある権威者」が言う事には納得出来ます。 確かに優れたコードは万人に組めるものではないでしょう。 同じ動作をするプログラムでも、センスのある人、ない人では、センスのある人の方がメモリ消費量も少なく、かつ動作も速い。 更にコードも読みやすいものであると思います。

 ではその「センス」を身につけるにはどうすれば良いか?
 答えはただ1つ。 ひたすら自分の力でプログラムを組むことです。

 発想力は、本だけでは育ちません。 自分で考える事で育ちます。
 本から知識を得るなんて誰だって出来ます。 でもその読んで得た知識を使って、実際にコードを書くのは誰にだって出来るというものではありません。
 プログラマーという職が成り立っているのにはそういう理由があるのです。 

 まずプログラミングを好きになって、「あんなものを作ってみたい」「こんなものを作ってみたい」と、いろんなプログラムを組んでいく事で成長します。

 ここから先は余談なのですが、専門校や大学を卒業して入社希望で来る方が結構います。 しかし、実際に即戦力になる人はほんの一握り。 その差は何か? はっきりいって、プログラムが趣味か否かだと思っています。 
 学校で言われた通りにプログラムを組み、知識だけ身につけてきた人と、プログラムを趣味とし、学校外でいろんなプログラムを組んで「技術」を身につけて来た人の違いではないでしょうか。

 プログラムは知識ではなく技術(発想力)です。

 車は教科書を読むだけで運転出来るようになるか。
 野球も参考書を読むだけで上達出来るのか。
 答えは Noですね。 それと一緒です。

 参考になれば幸いです(..
    • good
    • 0

このQ&Aに関連する人気のQ&A

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Qc++ , template , ファイル分割 , 助けてください...

//-----------------coord.h-------------
template <class type>
class coord
{
type v[3];
public:
coord(void);
void Show(void);
};
//-----------------main.cpp------------
#include<iostream>
#include"coord.h"
using namespace std;

int main(void)
{
coord<double> ob;

ob.Show();

return 0;
}
//----------------------coord.cpp-----------
#include<iostream>
#include"coord.h"
using namespace std;

template <class type>
coord<type>::coord(void)
{
v[0]=v[1]=v[2]=0;
}

template <class type>
void coord<type>::Show(void)
{
cout << "hello" << endl;
}

同一フォルダ内に上記のファイルが 3 つあります.
つまり上の 3 つのファイルを分割してコンパイルさせたいです.
この状態で...MS-DOSプロンプトからコンパイルします.

C:\test>bcc32 -c coord.cpp
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
coord.cpp:

C:\test>bcc32 -c main.cpp
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
main.cpp:

C:\test>bcc32 -emain main.obj coord.obj
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
Error: 外部シンボル 'coord<double>::coord<double>()' が未解決(C:\USERS\TAITO\PR
OG\CPP\TEST\MAIN.OBJ が参照)
Error: 外部シンボル 'coord<double>::Show()' が未解決(C:\USERS\TAITO\PROG\CPP\TE
ST\MAIN.OBJ が参照)


すると, このようなエラー文が出てしまい
実行可能ファイルができません.

コンパイラはbccです.

原因が全く分かりません.

助けてください...





ちなみに,
分割せずにコンパイルすると通ります.

自分は c 言語での分割コンパイル経験はあるので
それをそのまま c++ 言語でも用いているのですが,
何か変えなければならないのでしょうか?

//-----------------coord.h-------------
template <class type>
class coord
{
type v[3];
public:
coord(void);
void Show(void);
};
//-----------------main.cpp------------
#include<iostream>
#include"coord.h"
using namespace std;

int main(void)
{
coord<double> ob;

ob.Show();

return 0;
}
//----------------------coord.cpp-----------
#include<iostream>
#include"coord.h"
using namespace std;

template <class type>
coord<type>::coord(void)
{
v[0]=v[...続きを読む

Aベストアンサー

> クラスの宣言はヘッダファイル上で全て行なわないといけないのですか?

違います。テンプレートだからです。
本来であれば、exportを使って移出を行えば、ほぼ最初のようにソース分割できるのですが、Borland C++ Compilerでは(Visual C++でもGCCでも)exportをサポートしていないので使えません。

Q【C++ TR1】tr1::tupleのコンストラクタについて

 こんばんは。今回初めて此方のカテゴリに質問させて頂きます。
 今暇つぶしにtr1::tuple<T1, T2, ..., TN>の中を書いています。

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf

--------------------------------------------------------------
pdfの[6.1.3]より(少し省略しています)
--------------------------------------------------------------
template<T1, T2, ..., TN>
class tuple
{
public:

↓このコンストラクタのP1~PNが、どの様な型に成るのかが不明瞭です。
explicit tuple(P1, P2, ..., PN);

--------------------------------------------------------------

pdfの[6.1.3.1]辺りにP1~PNの事について、書いてはあるのですが・・・今一掴めません。

例えば、

tr1::tuple<char, int, const char(&)[3]>

と書いた場合、コンストラクタのP1, P2, P3はどう言う型になるのでしょうか。
テンプレートメタプログラムが解る方、ご教示お願いします。

 こんばんは。今回初めて此方のカテゴリに質問させて頂きます。
 今暇つぶしにtr1::tuple<T1, T2, ..., TN>の中を書いています。

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1836.pdf

--------------------------------------------------------------
pdfの[6.1.3]より(少し省略しています)
--------------------------------------------------------------
template<T1, T2, ..., TN>
class tuple
{
public:

↓このコンストラクタのP1~PNが、どの様な型に成るのかが不明瞭...続きを読む

Aベストアンサー

> where Pi is Ti if Ti is a reference type, or const Ti& otherwise.

なので、

tr1::tuple<char, int, const char(&)[3]>

の仮引数の型は、

const char&, const int&, const char(&)[3]

ではないでしょうか?

QMFC,C++/CLI,C#の共存

CCDカメラからの画像を画像処理ボード(MV-10というボードです)で受け取り、そのデータを使ったWindowsプログラムを開発したいと考えています。
開発はVisual C# 2005か Visual C++ 2005(C++/CLI)で行いたい(理想としては、フォームなど外観はC#、内部処理はC++)のですが、画像処理ボードのライブラリがMFCとなっていました。
色々と調べて、MFCとC++/CLIを共存させることが出来るらしく、またC#とC++/CLIを共存させることも出来るらしいと言うことが分かったのですが、具体多的な方法が分かりません。

具体的な方法が記述されている書籍や、ウェブサイトなどがありましたら、教えていただきたいです。

Aベストアンサー

下記URLにヒントがありそうです。

参考URL:http://www.wankuma.com/seminar/200708TechEd/Default.aspx

QC言語でCLAMP(a,b,c)

と書けばこの値はどのような値になるでしょうか?

Aベストアンサー

CLAMPはgmacros.hで定義されているマクロです。
詳細はgmacros.hを見ればわかると思います。

QC#,C++/CLI,MFCにおけるデータ型の対応と、メソッドへの渡し方

現在、Visual Studio 2005の、Visual C#、C++/CLI、MFCを使ったシステムを構築しています。
具体的には、MFCで書かれたライブラリ(DLL)をC++/CLIでラップし、C#から呼び出して使うというものです。
現在は、http://www.atmarkit.co.jp/fdotnet/special/vcppinvista02/vcppinvista02_04.html
http://msdn2.microsoft.com/ja-jp/library/ac7ay120(VS.80).aspx
これらのサイトを参考にしながら、一部のMFCで書かれたメソッドを、C#から呼び出すことに成功しました。しかし、int型やHANDLE型などの、上記サイトに記述されているデータ型を用いたメソッドのラッピングや呼び出しはできたのですが、HDCやLPRECTなどの特殊な型の場合のやり方がよく分かりません。

具体的に現在分からないのは、次の通りです。
HDC(デバイスコンテキスト)、HWND(ウィンドウのハンドル)、CIRCLE,RECT等の構造体、LPRECTなどの構造体のアドレス、POINT*などの構造体のポインタ
これらが、C#やCLIでどのような型になるのか、メソッドに渡す時にどのように記述するのかが分かりません。

以上、どなたか分かる方いらっしゃいましたら、ご回答をお願いします。

現在、Visual Studio 2005の、Visual C#、C++/CLI、MFCを使ったシステムを構築しています。
具体的には、MFCで書かれたライブラリ(DLL)をC++/CLIでラップし、C#から呼び出して使うというものです。
現在は、http://www.atmarkit.co.jp/fdotnet/special/vcppinvista02/vcppinvista02_04.html
http://msdn2.microsoft.com/ja-jp/library/ac7ay120(VS.80).aspx
これらのサイトを参考にしながら、一部のMFCで書かれたメソッドを、C#から呼び出すことに成功しました。しかし、int型やHANDLE型などの、上記サイトに...続きを読む

Aベストアンサー

> DLLのリンクはIJW機構というものを使用して

そのようですね、勉強不足で申し訳ありません。

>>    RECT lprcDC, lprcDib;
>
>>    return dllfunction(hDC, lprcDC, hDib, lprcDib);
> --------------------------------------------------------------
> この記述ですと、lprcDCとlprcDibがポインタに変換されていないと思う
> のですが、これは記述ミスでしょうか?

DllImport でマネージドとアンマネージドに変換されるので構造体を含め
C++/CLI のマネージドコードで記述してます。

# 他のと同じように lp- というプリフィクスにしたのが誤解を招いたかも
# 知れないです。

念のために拙いコードなのですが、 C# の GUI でコードを書いて動作
確認をしてみました。

TestDll.dll 側の関数実装には TextDraw と Bitblt を記述して任意の
文字列を bmp1(C#) の HDC に描画して bmp2(C#) の HDC には Bitblt で
bmp1(C#) の HDC を反転したものを転送するようにしました。
TextDraw と BitBlt のどちらかで失敗した場合はその時点で FALSE を
返すようになっています。

HANDLE は void* の typdef なので HDC にキャストしました。
TestDll.dll にポインタが確実に渡っているか調べるのだけならそれで
問題ないのではないかと思いましたので。

------------- 呼出用プログラム(C#) --------------
// PictureBox サイズの Bitmap を作成
Bitmap bmp1 = new Bitmap(pictureBox1.ClientSize.Width,
             pictureBox1.ClientSize.Height);
Bitmap bmp2 = new Bitmap(pictureBox2.ClientSize.Width,
             pictureBox2.ClientSize.Height);

// Bitmap から Graphics を得る
Graphics g1 = Graphics.FromImage(bmp1);
Graphics g2 = Graphics.FromImage(bmp2);

// Graphics から HDC を得る
IntPtr hDC = g1.GetHdc();
IntPtr hDBI = g2.GetHdc();

// DLL 呼び出し
if (!wrapper.function(hDC, pictureBox1.ClientRectangle,
            hDBI, pictureBox2.ClientRectangle)
  )
    MessageBox.Show("失敗");

// PictureBox へ描画
pictureBox1.Image = bmp1;
pictureBox2.Image = bmp2;
g1.ReleaseHdc();
g2.ReleaseHdc();

その他の部分は ANo.2 に記述したものと同じです。
----------------------------------------------------

それと、一点お尋ねしたいのですが

>  BOOL result = Mvc10_PaintDIB( (HDC)hDC.ToPointer(), LPrcDC , (HANDLE)hDib.ToInt32(), LPrcDib );

HANDLE は typedef void* かと思うのですが hDib.ToInt32() として
hDib.ToPointer() としてないのは何か理由があってのことでしょうか?

# こちらで試したところ ToPointer() でも ToInt32() でも動作する
# ようですし、立ち入ったことであれば申し訳ないですので、流して
# ください。

> 実際に使用してみての結果は後日報告させていただきたいと思います。

無事に動作されることをお祈りいたします。
自己解決されておられるようで、お役に立てなくて申し訳ありませんでした。

> DLLのリンクはIJW機構というものを使用して

そのようですね、勉強不足で申し訳ありません。

>>    RECT lprcDC, lprcDib;
>
>>    return dllfunction(hDC, lprcDC, hDib, lprcDib);
> --------------------------------------------------------------
> この記述ですと、lprcDCとlprcDibがポインタに変換されていないと思う
> のですが、これは記述ミスでしょうか?

DllImport でマネージドとアンマネージドに変換されるので構造体を含め
C++/CLI のマネージドコードで記述してます。...続きを読む


人気Q&Aランキング

おすすめ情報