![第12章 輸入輸出流與文件_第1頁](http://file4.renrendoc.com/view/6ad79e50c7c58d6e914429a7ae91309c/6ad79e50c7c58d6e914429a7ae91309c1.gif)
![第12章 輸入輸出流與文件_第2頁](http://file4.renrendoc.com/view/6ad79e50c7c58d6e914429a7ae91309c/6ad79e50c7c58d6e914429a7ae91309c2.gif)
![第12章 輸入輸出流與文件_第3頁](http://file4.renrendoc.com/view/6ad79e50c7c58d6e914429a7ae91309c/6ad79e50c7c58d6e914429a7ae91309c3.gif)
![第12章 輸入輸出流與文件_第4頁](http://file4.renrendoc.com/view/6ad79e50c7c58d6e914429a7ae91309c/6ad79e50c7c58d6e914429a7ae91309c4.gif)
![第12章 輸入輸出流與文件_第5頁](http://file4.renrendoc.com/view/6ad79e50c7c58d6e914429a7ae91309c/6ad79e50c7c58d6e914429a7ae91309c5.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第十二章
輸入輸出流與文件C++流及流庫輸入輸出流文件操作案例實(shí)戰(zhàn)與實(shí)訓(xùn)C++流及流庫12.1.1C++流流是一種抽象的概念,負(fù)責(zé)在數(shù)據(jù)的生產(chǎn)者和數(shù)據(jù)的使用者之間建立聯(lián)系,并管理數(shù)據(jù)的流動(dòng)。輸入操作是數(shù)據(jù)流從輸入設(shè)備(如鍵盤、磁盤)流向內(nèi)存。輸出操作是數(shù)據(jù)流從內(nèi)存流向輸出設(shè)備(如屏幕、打印機(jī)、磁盤)。C++流12.1.2C++流庫C++流體系是一個(gè)派生體系,ios是抽象基類,所有派生都是公有派生ios繼承關(guān)系圖12.1.2C++流庫I/O類庫中常用流類類名頭文件作用iosiostream抽象基類istreamiostream通用輸入流和其他輸入流的基類ostreamiostream通用輸出流和其他輸出流的基類iostreamiostream通用輸入輸出流和其他輸入輸出流的基類ifstreamfstream輸入文件流類ofstreamfstream輸出文件流類fstreamfstream輸入輸出文件流類istrstreamstrstream輸入字符串流類ostrstreamstrstream輸出字符串流類strtreamstrstream輸入輸出字符串類輸入輸出流12.2.1標(biāo)準(zhǔn)輸出流cout流對(duì)象cout是標(biāo)準(zhǔn)輸出流對(duì)象,用于在計(jì)算機(jī)屏幕上顯示信息,輸出的純文本內(nèi)容。在用cout進(jìn)行標(biāo)準(zhǔn)類型輸出時(shí),用戶不必通知計(jì)算機(jī)按何種類型輸出,系統(tǒng)會(huì)自動(dòng)判別輸出數(shù)據(jù)的類型,使輸出的數(shù)據(jù)按相應(yīng)的類型輸出。cerr流對(duì)象cerr是標(biāo)準(zhǔn)錯(cuò)誤輸出流對(duì)象,用于顯示錯(cuò)誤信息。默認(rèn)情況下被關(guān)聯(lián)到標(biāo)準(zhǔn)輸出流,但它不被緩沖,即錯(cuò)誤消息可以直接發(fā)送到顯示器上。clog流對(duì)象clog也是標(biāo)準(zhǔn)錯(cuò)誤輸出流對(duì)象,作用和cerr是一樣的,但clog中的消息存放緩沖區(qū),知道緩沖區(qū)滿或者遇到endl時(shí)才輸出。
標(biāo)準(zhǔn)輸出流就是數(shù)據(jù)從內(nèi)存流向輸出設(shè)備(比如,顯示器)12.2.2標(biāo)準(zhǔn)輸入流cin是istream類的對(duì)象,主要用于從鍵盤輸入的數(shù)據(jù)中讀取數(shù)據(jù)。cin是通過流提取運(yùn)算符“>>”從流中提取數(shù)據(jù),會(huì)自動(dòng)跳過輸入流中的空格、Tab鍵、換行符等空白字符。
標(biāo)準(zhǔn)輸入流是從標(biāo)準(zhǔn)輸入設(shè)備(比如,鍵盤)流向計(jì)算機(jī)內(nèi)存的數(shù)據(jù)1 cin流對(duì)象12.2.2標(biāo)準(zhǔn)輸入流get成員函數(shù)是從指定的輸入流中提取一個(gè)字符,函數(shù)的返回值就是這個(gè)字符。該函數(shù)在istream類里進(jìn)行了重載,主要表現(xiàn)形式有四種:無參數(shù)的get函數(shù)函數(shù)原型:intcin.get()有一個(gè)參數(shù)的get函數(shù)函數(shù)原型:istream&cin.get(char&ch)有兩個(gè)參數(shù)的get函數(shù)函數(shù)原型:istream&get(char*s,streamsizen)有三個(gè)參數(shù)的get函數(shù)函數(shù)原型:istream&get(char*s,streamsizen,chardelim)2 cin.get成員函數(shù)讀取一個(gè)字符12.2.2標(biāo)準(zhǔn)輸入流函數(shù)原型:istream&getline(char*s,streamsizen,chardelim)3 cin.getline成員函數(shù)讀取一行字符12.2.3輸入輸出控制格式cin輸入數(shù)據(jù)會(huì)自動(dòng)忽略所有的空格、換行和回車等字符,而自動(dòng)匹配相應(yīng)的字符和數(shù)字。輸入格式控制輸出格式控制使用控制字符如果使用控制符,在程序開頭除了要添加iostream頭文件外,還要加上iomanip頭文件。另外,在設(shè)置了一次控制符后,對(duì)后面的輸出內(nèi)容都按照設(shè)置進(jìn)行輸出,除非對(duì)輸出格式進(jìn)行取消或更改。使用流對(duì)象的成員函數(shù)通過調(diào)用流對(duì)象cout中用于控制輸出格式的成員函數(shù)來控制輸出格式。12.2.3輸入輸出控制格式流成員函數(shù)與之作用相同的控制符作用precision(n)setprecision(n)設(shè)置浮點(diǎn)數(shù)的精度為n位width(n)setw(n)設(shè)置字段寬度為n位fill(c)setfil(c)設(shè)置填充字符csetf()setiosflags()設(shè)置輸出格式狀態(tài),括號(hào)中應(yīng)給出格式狀態(tài),內(nèi)容與控制符setiosflags括號(hào)中內(nèi)容相同ubsetf()resetiosflags()終止已設(shè)置的輸出格式狀態(tài)常見控制輸出格式的成員函數(shù)文件操作文件的概念文件流與文件流對(duì)象文件的打開與關(guān)閉文件的操作12.3.1文件的概念文件是數(shù)據(jù)的集合,通常存儲(chǔ)在磁盤上,便于以后使用;幾乎所有的程序都用文件存儲(chǔ)信息,如:數(shù)據(jù)庫管理系統(tǒng)、操作系統(tǒng)、編譯器等;所有文件都有名字。文件12.3.2文件流與文件流對(duì)象在讀寫文件時(shí),必須定義一個(gè)文件流類的對(duì)象,文件流的對(duì)象定義方法如下:ifstreaminfile; //定義一個(gè)文件流對(duì)象infile,用來讀文件ofstreamoutfile; //定義一個(gè)文件流對(duì)象outfile,用來寫文件12.3.3文件的打開與關(guān)閉在對(duì)文件進(jìn)行讀或?qū)懖僮髦氨仨毾却蜷_文件,指定打開的文件名和文件操作方式。使用ifstream定義對(duì)象時(shí),默認(rèn)打開方式為:ios::in示例如下: ifstreaminputFile;// inputFile.open(“d:\\customer.dat”);//成員函數(shù) //默認(rèn)打開方式為“讀” charfileName[20]; cin>>fileName; inputFile.open(fileName); open函數(shù)有兩個(gè)參數(shù)(“文件名”,方式)//第二個(gè)參數(shù)使用默認(rèn)值,ios::in文件打開12.3.3文件的打開與關(guān)閉使用ofstream對(duì)象時(shí),默認(rèn)打開方式是輸出;ios::out使用fstream對(duì)象時(shí),第二個(gè)參數(shù)用于表明文件的打開方式,必須顯示寫出來,既可以ios::in,又可以ios::out示例: ofstreamfout(“a.txt”);等價(jià) ofstreamfout;fout.fopen((“a.txt”,ios::out); fstreamdataFile; dataFile.open("info.dat",ios::out);文件打開12.3.3文件的打開與關(guān)閉ifstream:只能用于從文件中讀取數(shù)據(jù),ofstream:只能用于向文件寫數(shù)據(jù).其他模式見下表。多個(gè)模式組合時(shí),用“|”或運(yùn)算實(shí)現(xiàn)示例: Output.open("values.dat",ios::in|ios::binary);注意12.3.3文件的打開與關(guān)閉文件的打開模式方式作用ios::app以輸出方式打開文件,寫入的數(shù)據(jù)添加在文件末尾ios::ate如果已存在,直接轉(zhuǎn)到文件尾部ios::binary以二進(jìn)制方式打開一個(gè)文件ios::in以輸入方式打開文件ios::out以輸出方式打開文件ios::trunc若文件存在,刪除其內(nèi)容;若文件不存在,則打開新文件ios::nocreate若文件不存在,則打開失敗ios::noreplace若文件不存在,則建立文件,若文件已存在,則操作失敗12.3.3文件的打開與關(guān)閉先定義流對(duì)象,再打開文件 fstreamdataFile; dataFile.open(“info.dat”,ios::in|ios::out); dataFile.open("info.dat",ios::out|ios::app);定義流對(duì)象時(shí)打開文件 fstreamdataFile("names.dat",ios::in|ios::out);測(cè)試open函數(shù)打開文件是否成功使用dataFile.fail()文件打開12.3.3文件的打開與關(guān)閉當(dāng)程序不再使用文件時(shí),應(yīng)關(guān)閉文件文件緩沖區(qū)是一塊小的內(nèi)存空間操作系統(tǒng)限制同時(shí)打開的文件數(shù)量格式:dataFile.close();文件關(guān)閉12.3.4文件的操作使用<<向一個(gè)文件寫入信息fstreamdataFile;dataFile.open("E:\\demofile.txt",ios::out);if(!dataFile){ cout<<"Erroropeningfile.\n"; exit(0); }dataFile<<"Confucius\n";dataFile<<"Mo-tse\n";dataFile.close();dataFile.open(“E:\\demofile.txt",ios::out|ios::app);dataFile<<"Einstein\n";dataFile<<"Shakespeare\n";dataFile.close();1 文本文件的讀寫操作12.3.4文件的操作使用>>從文件讀數(shù)據(jù)fstreamdataFile;charname[81];dataFile.open("demofile.txt",ios::in);if(!dataFile){cout<<"Fileopenerror!"<<endl;exit(0);}for(intcount=0;count<4;count++){ dataFile>>name; cout<<name<<endl;}dataFile.close();1 文本文件的讀寫操作12.3.4文件的操作空白字符是數(shù)據(jù)之間的分界符,采用>>操作符進(jìn)行讀取時(shí),就會(huì)略過空白字符。使用函數(shù)成員讀寫文件:getline成員函數(shù)——dataFile.getline(str,81,'\n');str:從文件中讀取的數(shù)據(jù)將存儲(chǔ)在該空間中。81:從文件中最多能讀取80個(gè)字符?!甛n’界符。如果在讀滿最大字符個(gè)數(shù)之前,遇到了界符,那么將停止讀?。ㄗ⒁猓涸搮?shù)可選)。采用函數(shù)成員讀寫文件1 文本文件的讀寫操作12.3.4文件的操作空白字符是數(shù)據(jù)之間的分界符,采用>>操作符進(jìn)行讀取時(shí),就會(huì)略過空白字符。使用函數(shù)成員讀寫文件:getline成員函數(shù)——dataFile.getline(str,81,'\n');get成員函數(shù):每次從文件讀取一個(gè)字符——inFile.get(ch);put成員函數(shù):每次向文件寫入一個(gè)字符——outFile.put(ch);采用函數(shù)成員讀寫文件1 文本文件的讀寫操作12.3.4文件的操作二進(jìn)制文件中存儲(chǔ)的數(shù)據(jù)是非格式化的,按照在內(nèi)存中存儲(chǔ)的形式存儲(chǔ),不是按照ASCII純文本方式存儲(chǔ)。示例: ofstreamfile("num.dat"); intx=1297; file<<x;
存儲(chǔ)形式是:'1','2','9','7'二進(jìn)制文件2 二進(jìn)制文件的讀寫操作12.3.4文件的操作以二進(jìn)制方式打開文件方式: file.open("stuff.dat",ios::out|ios::binary);注意:缺省情況下文件是以文本方式打開.讀/寫函數(shù): file.write((char*)buffer,sizeof(buffer)); file.read((char*)buffer,sizeof(buffer));二進(jìn)制文件2 二進(jìn)制文件的讀寫操作12.3.4文件的操作文件位置指針成員函數(shù)3 二進(jìn)制文件隨機(jī)訪問成員函數(shù)作用gcount()返回最后一次輸入所輸入的字節(jié)數(shù)tellg()返回輸入文件位置指針的當(dāng)前位置seekg(文件中的位置)將輸入文件中位置指針移動(dòng)到指定的位置seekg(位移量,參照位置)以參照位置為基礎(chǔ)移動(dòng)到指定的位置tellp()返回輸出文件位置指針當(dāng)前的位置12.3.4文件的操作不關(guān)閉和重新打開文件的情況下,同時(shí)執(zhí)行輸入和輸出。 fstream file("data.dat",ios::in|ios::out); file.open("data.dat",ios::in|ios::out); file.open("data.dat",ios::in|ios::out|ios::binary);文件綜合實(shí)例案例實(shí)戰(zhàn)與實(shí)訓(xùn)12.4.1案例實(shí)戰(zhàn)通過讀寫文件實(shí)現(xiàn)簡(jiǎn)單學(xué)生信息管理系統(tǒng)。要求定義一個(gè)日期類和學(xué)生類,日期類定義year、month和day成員變量,成員函數(shù)實(shí)現(xiàn)設(shè)置日期以及分別返回年月日,學(xué)生類定義學(xué)號(hào)、姓名和出生日期成員,并對(duì)文件中保存的學(xué)生信息實(shí)現(xiàn)輸入、瀏覽、查找、修改、刪除和修改等功能。案例實(shí)戰(zhàn)案例分析定義日期類日期信息包括:私有數(shù)據(jù)成員month,day和year。基本操作包括:設(shè)置日期、返回日期的年月日等信息。定義學(xué)生類學(xué)生信息包括:學(xué)號(hào)、姓名和出生日期,基本操作包括:輸入學(xué)生信息、瀏覽學(xué)生信息、查找學(xué)生信息、修改學(xué)生信息、刪除學(xué)生信息和修改學(xué)生信息。創(chuàng)建一個(gè)學(xué)生信息文件創(chuàng)建學(xué)生信息文件用于保存學(xué)生基本信息。定義普通函數(shù)菜單函數(shù)實(shí)現(xiàn)功能選項(xiàng)的顯示,功能選擇函數(shù)創(chuàng)建對(duì)象,選擇相應(yīng)功能選擇,并用函數(shù)遞歸實(shí)現(xiàn)重復(fù)操作。定義主程序調(diào)用菜單函數(shù)和功能選擇函數(shù)。12.4.1案例實(shí)戰(zhàn)【案例實(shí)現(xiàn)】#include<iostream>#include<fstream>#include<string>#include<cstdlib>usingnamespacestd;//定義日期類表示學(xué)生出生日期classDate{public:voidsetDate();intgetYear();intgetMonth();intgetDay();private:intyear;intmonth;intday;};voidDate::setDate(){cout<<"請(qǐng)輸入出生年份:"<<endl;cin>>year;cout<<"請(qǐng)輸入出生月份:"<<endl;cin>>month;cout<<"請(qǐng)輸入出生日:"<<endl;cin>>day;}intDate::getYear(){returnyear;}intDate::getMonth(){returnmonth;}intDate::getDay(){returnday;}//定義學(xué)生類classStudent{public:voidsetStuValues(Date&birthday);voidsetNum();intgetNum();voidsetName();stringgetName();voidsetBirthday(Date&birthday);intgetBirYear(Date&birthday);intgetBirMonth(Date&birthday);intgetBirDay(Date&birthday);voidinPut(Date&birthday);voidoutPut();voidfindByNum();voiddeleteByNum();voidalterNameByNum();private:intnum;stringname;Datebirthday;};voidStudent::setStuValues(Date&birthday){cout<<"請(qǐng)輸入學(xué)生的學(xué)號(hào):"<<endl;cin>>num;cout<<"請(qǐng)輸入學(xué)生的姓名:"<<endl;cin>>name;birthday.setDate();}voidStudent::setNum(){cin>>num;}intStudent::getNum(){returnnum;}voidStudent::setName(){cin>>name;}stringStudent::getName(){returnname;}voidStudent::setBirthday(Date&birthday){birthday.setDate();}intStudent::getBirYear(Date&birthday){returnbirthday.getYear();}intStudent::getBirMonth(Date&birthday){returnbirthday.getMonth();}intStudent::getBirDay(Date&birthday){returnbirthday.getDay();}voidStudent::inPut(Date&birthday){charch;cout<<"請(qǐng)輸入學(xué)生信息"<<endl;ofstreamoutfile("student.txt",ios::app);if(!outfile){cout<<"文件打開失?。?<<endl;exit(0);}setStuValues(birthday);outfile<<getNum()<<""<<getName()<<""<<birthday.getYear()<<""<<birthday.getMonth()<<""<<birthday.getDay()<<endl;cout<<"是否繼續(xù)輸入學(xué)生信息,輸入y(繼續(xù))或者n(停止)";cin>>ch;if(ch='y'){inPut(birthday);}outfile.close();system("pause");}voidStudent::outPut(){intyear,month,day;ifstreaminfile("student.txt",ios::in);if(!infile){cout<<"文件打開失??!"<<endl;exit(0);}while(!infile.eof()){infile>>num>>name>>year>>month>>day;cout<<num<<""<<name<<""<<year<<""<<month<<""<<day<<endl;infile.get();if(infile.peek()=='\n')break;}infile.close();system("pause");}voidStudent::findByNum(){intyear,month,day;intfindnum;boolflag=false;cout<<"請(qǐng)輸入要查找學(xué)生的學(xué)號(hào):";cin>>findnum;ifstreaminfile("student.txt",ios::in);if(!infile){cout<<"文件打開失敗!"<<endl;exit(0);}while(!infile.eof()){infile>>num>>name>>year>>month>>day;if(num==findnum){cout<<num<<""<<name<<""<<year<<""<<month<<" "<<day<<endl;flag=true;}infile.get();if(infile.peek()=='\n')break;}if(!flag){cout<<"查無此人!"<<endl;}infile.close();system("pause");}voidStudent::deleteByNum(){intyear,month,day;intfindnum;boolflag=false;cout<<"請(qǐng)輸入要?jiǎng)h除學(xué)生的學(xué)號(hào):";cin>>findnum;ifstreaminfile("student.txt",ios::in);if(!infile){cout<<"文件打開失?。?<<endl;exit(0);}ofstreamoutfile("studentcpy.txt",ios::app);if(!outfile){cout<<"文件打開失敗!"<<endl;exit(0);}while(!infile.eof()){infile>>num>>name>>year>>month>>day;if(num!=findnum){outfile<<num<<""<<name<<""<<year<<""<<month<<"" <<day<<endl;}else{cout<<num<<""<<name<<""<<year<<""<<month<<""<< day<<endl;flag=true;cout<<"已刪除該學(xué)生信息!"<<endl;}infile.get();if(infile.peek()=='\n')break;}if(!flag){cout<<"查無此人!"<<endl;}infile.close();outfile.close();remove("student.txt");rename("studentcpy.txt","student.txt");}voidStudent::alterNameByNum(){intyear,month,day;intfindnum;stringaltername;boolflag=false;cout<<"請(qǐng)輸入要修改學(xué)生的學(xué)號(hào):";cin>>findnum;cout<<"請(qǐng)輸入要修改學(xué)生的姓名:";ifstreaminfile("student.txt",ios::in);if(!infile){cout<<"文件打開失?。?<<endl;exit(0);}ofstreamoutfile("studentcpy.txt",ios::app);if(!outfile){cout<<"文件打開失??!"<<endl;exit(0);}while(!infile.eof()){infile>>num>>name>>year>>month>>day;if(num!=findnum){outfile<<num<<""<<name<<""<<year<<""<<month<<""<<day<<endl;}else{outfile<<num<<""<<name<<""<<year<<""<<month<<""<<day<<endl;flag=true;cout<<"已修改該學(xué)生信息!"<<endl;}infile.get();if(infile.peek()=='\n')break;}if(!flag){cout<<"查無此人!"<<endl;}infile.close();outfile.close();remove("student.txt");rename("studentcpy.txt","student.txt");}voidmenu(){cout<<"\t\t****學(xué)生信息管理系統(tǒng)****"<<endl;cout<<"\t\t****1.輸入學(xué)生信息****"<<endl;cout<<"\t\t****2.瀏覽全部學(xué)生信息****"<<endl;cout<<"\t\t****3.按學(xué)號(hào)查找學(xué)生信息****"<<endl;cout<<"\t\t***
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025屆高考英語讀后續(xù)寫說課稿 追車人
- 2025SRV汽化煙道熱噴涂合金防護(hù)層施工合同
- 2025民間融資合同范本
- 14《母雞》(說課稿)-2023-2024學(xué)年語文四年級(jí)下冊(cè)統(tǒng)編版
- 2025年駕校培訓(xùn)合同范本
- 2025商品購銷合同(超市類)
- 2024年五年級(jí)數(shù)學(xué)下冊(cè) 一 圖形的運(yùn)動(dòng)(二)1.2畫對(duì)稱圖形說課稿 冀教版
- 2024-2025學(xué)年高中歷史 第一單元 第一次世界大戰(zhàn) 第2課 慘烈的四年戰(zhàn)事教學(xué)說課稿 岳麓版選修3
- 陶土板幕墻施工方案
- 游樂場(chǎng)植物墻施工方案
- 消防器材與消防設(shè)施的維護(hù)與檢查
- 2024年度碳陶剎車盤分析報(bào)告
- 四川省綿陽市2025屆高三上學(xué)期第二次診斷性考試語文試題(含答案)
- 2025年1月 浙江首考英語試卷
- 2025年1月廣西2025屆高三調(diào)研考試英語試卷(含答案詳解)
- 質(zhì)檢工作計(jì)劃書2025質(zhì)檢部工作計(jì)劃范文
- 《復(fù)旦大學(xué)》課件
- 《纏論的實(shí)戰(zhàn)技法》課件
- 承包魚塘維修施工合同范例
- 耶魯綜合抽動(dòng)嚴(yán)重程度量表正式版
- 2024年浙江省公務(wù)員錄用考試《行測(cè)》題(A類)
評(píng)論
0/150
提交評(píng)論