#include <iostream>
#include <string>
const int Asize = 20;
int main()
{
using namespace std;
char line[Asize];
cout << "Type, and I shall repeat.\n";
int idx=0;
char temp{};
do{
cin.get(temp);
line[idx++] = temp;
if(idx==Asize-1){
idx=0;
}
}while(temp!='.');
cout<<string(line);
cout << "\nPlease excuse the slight confusion.\n";
return 0;
}說下自己的理解,供參考。假設(shè)題主了解網(wǎng)絡(luò)編程和計算機(jī)系統(tǒng)的一些基本概念。
簡單概括來說,事件驅(qū)動是實現(xiàn)并發(fā)處理的一種方式。
我們就以HTTP請求的處理過程為例,為簡化說明,僅考慮網(wǎng)絡(luò)IO,不考慮文件IO和數(shù)據(jù)庫等其他過程,也不考慮多核系統(tǒng)。
考慮采用如下最簡模型來處理HTTP請求:
main_loop:
accept()
recv()
parse()
send()
close()
來一個連接,讀取數(shù)據(jù)(請求),解析請求內(nèi)容,返回數(shù)據(jù)(應(yīng)答)。
同一時間只為一個客戶端服務(wù)。在為A客戶端服務(wù)的過程中,B客戶端必須等待。
這種方式非常簡單直接,容易理解,但其無法滿足現(xiàn)實場景的需要——不支持并發(fā)。
現(xiàn)實中,客戶端的請求是并發(fā)的:即當(dāng)一個客戶端的請求還在處理時,另外一個客戶端的請求就會達(dá)到,甚至多個客戶端的請求同時達(dá)到。
而且,recv 和 send等涉及網(wǎng)絡(luò)操作的API由于網(wǎng)絡(luò)數(shù)據(jù)發(fā)送與到達(dá)的不確定性,可能需要等待,CPU會空閑下來——但這種模型下即使CPU空閑了也無法處理其他客戶端的請求,浪費了CPU。
我們采用如下多線程模型,可以解決上述問題:
main_loop:
accept()
start_thread(thread_loop)
thread_loop:
recv()
parse()
send()
close()
exit thread()
即每個客戶端在一個獨立的線程中處理。
當(dāng)一個客戶端的線程執(zhí)行網(wǎng)絡(luò)操作需要等待時,會被操作系統(tǒng)調(diào)度出去,執(zhí)行其他需要干活兒的線程。
似乎完美了解決了我們的問題?
然而并沒有。
因為操作系統(tǒng)創(chuàng)建線程的開銷是比較大的,能夠支持的線程數(shù)量是有限的,通常是幾萬的級別,如果線程太多,就會有很多的CPU浪費在了線程的創(chuàng)建、銷毀、調(diào)度等管理操作上。
所以為了充分發(fā)揮CPU的能力,支持更多的并發(fā)數(shù)量,,在Linux上有另外一種處理并發(fā)的方式:
內(nèi)核提供了監(jiān)聽大量網(wǎng)絡(luò)連接(句柄)可讀、可寫等事件的機(jī)制和接口。
應(yīng)用把需要監(jiān)聽對象以及關(guān)心的事件注冊給內(nèi)核,內(nèi)核在有事件達(dá)到時通知應(yīng)用處理。
基于這種機(jī)制處理并發(fā)就是事件驅(qū)動。
事件驅(qū)動機(jī)制的基本模型是:
create_listen_socket()
register_event_for_listen_socket()
main_loop:
wait_for_event()
check_events:
if listen_socket has event(new client coming) :
accept()
register_event_for_client_socket()
if client_socket has event(new data coming):
recv()
parse()
send()
但這里有一個問題,有可能一個客戶端剛讀取了一部分?jǐn)?shù)據(jù),就沒了,剩下的還在網(wǎng)絡(luò)中沒過來,需要繼續(xù)等待。
這就需要把當(dāng)前的讀取內(nèi)容和請求處理狀態(tài)(也即上下文)保存起來,繼續(xù)處理其他客戶端的事件。
然后下次這個客戶端再有事件到來時再找回上下文繼續(xù)處理。
這其實需要應(yīng)用自己做一些任務(wù)調(diào)度相關(guān)的上下文保存和切換工作。
當(dāng)使用多線程處理并發(fā)時,操作系統(tǒng)幫我們做了這些工作,我們無需關(guān)心任務(wù)切換。
因為一個線程就只處理一個客戶端,反復(fù)調(diào)用recv把一個請求的數(shù)據(jù)讀完然后解析處理就可以了,也不用擔(dān)心沒數(shù)據(jù)到來時,recv阻塞了其他客戶端的處理。
所以多線程編寫并發(fā)代碼非常簡單直接。
如上,事件驅(qū)動機(jī)制是Linux上解決并發(fā)問題的一種高效編程模型。
應(yīng)用反復(fù)探測事件,對接收到的事件進(jìn)行逐個處理的過程就是事件循環(huán)。
那么同步和異步概念體現(xiàn)在哪里呢?
所謂同步就是我們執(zhí)行一個任務(wù),一直等待任務(wù)執(zhí)行結(jié)束。
所謂異步就是我們執(zhí)行一個任務(wù),不等待任務(wù)執(zhí)行結(jié)束,繼續(xù)去干其他活兒,任務(wù)結(jié)果后有個通知,或者干脆不關(guān)心任務(wù)的執(zhí)行結(jié)果。
在多線程模型中,每接收到一個新的客戶端就創(chuàng)建一個線程處理,這就是一種異步處理。
在事件驅(qū)動模型中,當(dāng)沒有數(shù)據(jù)可讀時,就把這個客戶端繼續(xù)放到監(jiān)聽隊列中監(jiān)聽,也是一種異步。
如果我們考慮文件IO,把IO請求丟給另外一個或一組線程(線程池)處理,處理完后通知主線程,也是一種異步。
表達(dá)式"s"的類型是const char[],表達(dá)式 'a'的類型是char。
數(shù)組是不能進(jìn)行內(nèi)置加法運算的。所以const char []會被轉(zhuǎn)換成const char *,這里的運算就變成了"指針+整型"(char是一種整型)。輸出空行的運行結(jié)果實際上是數(shù)組越界引起的。
String literal
Narrow multibyte string literal. The type of an unprefixed string literal is const char[]
Additive operators
addition. For the built-in operator, lhs and rhs must be one of the following: Both have arithmetic or unscoped enumeration type. In this case, the usual arithmetic conversions are performed on both operands and determine the type of the result. One is a pointer to complete object type, the other has integral or unscoped enumeration type. In this case, the result type has the type of the pointer
Array-to-pointer decay
There is an implicit conversion from lvalues and rvalues of array type to rvalues of pointer type: it constructs a pointer to the first element of an array. This conversion is used whenever arrays appear in context where arrays are not expected, but pointers are.
前后端分離的話,前端獲取返回的數(shù)據(jù),根據(jù)業(yè)務(wù)(也就是你的類型)進(jìn)行跳轉(zhuǎn)
未分離的情況如果用的是balde模板,改下return view('你想跳轉(zhuǎn)的頁面的名稱')即可吧
標(biāo)準(zhǔn)約定std::thread構(gòu)造時向函數(shù)對象傳遞實際參數(shù)的拷貝(支持移動語義),而不是轉(zhuǎn)發(fā)實際參數(shù)(你可以通過打印實際參數(shù)和形式參數(shù)的地址來檢測這一行為)。即fun的形式參數(shù)是被a的拷貝初始化的,所以形式參數(shù)a并不是main函數(shù)內(nèi)a的引用,在fun內(nèi)賦值自然不會改變main函數(shù)內(nèi)a的值。
如果你希望“以引用的方式傳參”,常用解決方案之一是使用std::ref,即std::thread(fun, std::ref(a));。
言歸正傳
編譯報錯是最好debug的錯誤之一,所有的錯誤編譯器都明確告訴你了
請看代碼中的這一行:
vmm[i].insert(it->first,count);
這里vmm[i] 是一個 map<int,char*>, 且不說插入值的時候需要用pair<int, char*>包裝鍵值對,it->first是一個int,count也是一個int,值的類型和map的定義不符。
如果不在乎insert的返回值的話,個人覺得用map[key] = value的方式更簡潔
var a = 1就是講a定義為全局變量,你fn1()執(zhí)行的時候,fn1函數(shù)內(nèi)部,alert(a)前面并沒有定義a,就會在全局作用域中尋找a,所以第一次是alert(1),然后你的a被改為2(第二次的a也是全局的),最下面的那個alert(a)中的a就為2
提供幾種思路:
(1)將包含 N 個數(shù)的數(shù)組打亂,然后選取前 10 個數(shù)。
(2)將每次得到的數(shù)放入 HashSet,下次取得一個數(shù)時先判斷是否存在于 Set 當(dāng)中,直到當(dāng) Set 的 size 為 10 時結(jié)束。
Bus error 表示程序要讀不可能存在的內(nèi)存地址,檢查mongod引用了什么so文件,編譯和執(zhí)行時的so文件要一樣。
extensions: ['', '.js', '.json', '.scss'];
新版本的空字符是會報錯;
改成extensions: ['*', '.js', '.json', '.scss'];
func()?哪來的func()?能不能把你的代碼補(bǔ)充完整,包括你在哪里用了this,并且把你期望這個this指向哪個對象也補(bǔ)上。我猜你可能用了箭頭函數(shù),箭頭函數(shù)沒有this關(guān)鍵字哦。
我試了一下以下代碼(手機(jī)上只有node,node的原型是__proto__。瀏覽器上跑不方便)
function Graph() {}
var Graph = new Graph();
Graph.__proto__.foo = function() {
console.log('old foo', this);
return this;
}
Graph.__proto__.fun = function() {
console.log('old fun', this);
return this;
}
Graph.__proto__.foo = function() {
console.log('new foo', this);
function subfoo() {
console.log('subfoo', this);
this.fun();
return this;
}
subfoo.call(this);
return this;
}
Graph.foo();
結(jié)果是
new foo Graph {}
subfoo Graph {}
old fun Graph {}
Graph {}
非常的正常,不知道你有沒有漏了什么信息沒有提供的,當(dāng)然也有可能是瀏覽器和node的差別。另外你在什么瀏覽器上測試的?我中午或下午可以在瀏覽器上測試一下。
你可能忘記了mybatis的xml文件可以寫ResultMap這個東西
多表查詢之后 結(jié)果映射到ResultMap里
voiceObj.pageList[index].showList=!this.data.voiceObj.pageList[index].showList放遠(yuǎn)程cnd啥的、然后大家都引用。
for(int i = 0; i < n; i++) {
if(a[i] == x) {
cout << i << endl;
break; // 這里break了,下面的flag=true不會被執(zhí)行到
flag = true;
}
}I don't have Chinese input method editor, so I will write in English(but too lazy to translate the original contexts into English, So previous Chinese wording preserved)
很不幸, 之所以你搜segmentfault都是這個論壇, 有兩個原因,
1.1. segment fault既不是linux特有的, 也不是c++特有的, 甚至從語言規(guī)範(fàn)中, 它不屬於c++, 因爲(wèi)c++的標(biāo)準(zhǔn)文檔中沒有對Segmentation fault沒有過定義. 喂雞百科中它被定義爲(wèi):
In computing, a segmentation fault (often shortened to segfault) or access violation is a fault, or failure condition, raised by hardware with memory protection, notifying an operating system (OS) the software has attempted to access a restricted area of memory (a memory access violation).
長話短說, 就是軟件訪問了不該訪問的memory, 而硬件具有內(nèi)存保護(hù)功能. 具體的說, 就是當(dāng)MMU檢測到非法內(nèi)存被訪問了, 那麼它就讓CPU產(chǎn)生一個exception.
1.2. c或者c++這種既接近底層, 又古老的語言會引起段錯誤.
1.3. 書沒什麼好推薦的, 畢竟這玩意一般第一天寫c/c++就會碰到...碰到多了自然知道了, 非要推薦的話去看些操作系統(tǒng)之類的書(CSAPP, OSTEP, etc)會有比較深刻的認(rèn)知吧,比如trap. 不過也別迷信讀書, 畢竟現(xiàn)在互聯(lián)網(wǎng)這麼發(fā)達(dá). 你把英文喂雞上的關(guān)於它的內(nèi)容看一邊也差不多了.
2.1. bus error, stack overflow(更新: 有一種說法是stack overflow本身不是錯誤(error/fault), 但是它的存在會觸發(fā)其它錯誤(error/fault), 其中之一就是Segmentation fault, 因爲(wèi)call stack溢出後, 程序有可能對非法地址進(jìn)些讀寫操作. ......好多好多呢, 你去這個列表看下,
2.2. 至於Segmentation和fault這倆詞語, 我們從操作系統(tǒng)講起:
假想下你的操作系統(tǒng)就是一個巨大的庫, 所有操作(包括應(yīng)用軟件)都只要調(diào)用這個庫(的API)就行了, 沒有任何權(quán)限限制, 這其實就是早期操作系統(tǒng)的設(shè)計形態(tài), 後來人們逐漸意識到這麼做是不安全的, 放到今天應(yīng)該會很容易明白, 比如你肯定不希望手機(jī)流氓軟件(應(yīng)用軟件)訪問你在磁盤上的個人信息吧, 但是我們依然要確保操作系統(tǒng)有權(quán)限訪問, 所以我們需要一場革命, 帶來一個新的內(nèi)存保護(hù)機(jī)制, 或者說是一個新的文件系統(tǒng), 當(dāng)然, 這個文件系統(tǒng)肯定不能作爲(wèi)一個庫, 不然還是什麼都沒有改變, 最終, 這個革命者名爲(wèi)system call, 其實現(xiàn)是通過硬件(CPU的trap)指令, 伴隨它的還有user mode, kernel mode(這兩個mode是針對CPU的, 比如, CPU可以用一個bit來表徵, 0代表kernel mode, 1代表kernel mode等. 具體的做法就是system call賦予操作系統(tǒng)更高的硬件優(yōu)先級. 應(yīng)用軟件處於user mode, 不能進(jìn)行讀寫磁盤/物理內(nèi)存等操作, 它將某些數(shù)值放在寄存器或棧幀, 表示自己希望從操作系統(tǒng)處得到那些東西, 然後應(yīng)用軟件調(diào)用trap)指令, 即執(zhí)行system call, 此時CPU轉(zhuǎn)換爲(wèi)kernel mode, 並且跳轉(zhuǎn)到一些指令處, 這些指令是屬於操作系統(tǒng)的, 他們會聆聽(通過之前的寄存器或者棧幀)應(yīng)用軟件, 然後也切換到kernel mode, 執(zhí)行這些請求.
However, how can we separate user mode from kernel mode? Two approaches:
好, 爲(wèi)了鞏固記憶, 接下來我們換一種問法, 什麼情況下system call會被執(zhí)行呢?
答案還是trap)(需要注意的是此處的trap)不同於上面的trap)指令, 是兩回事, 這裏的trap)是一個泛指, 是interrupt的子集, 特指非硬件層面的interrupt). 經(jīng)常, trap)也可以用其同義詞--falut或者exception來代替. 有些地方會將這些分開, 比如如果你關(guān)注國外各個大學(xué)的操作系統(tǒng)(設(shè)計(與實現(xiàn))的課的話, 會發(fā)現(xiàn)他們往往會對其定義有差別, 比如由硬件還是軟件觸發(fā)之類, 具體如fault有時會特指page fault, 再比如Intel microprocessor manuals裏將synchronous interrupts定義爲(wèi)exceptions, asynchronous interrupts 定義爲(wèi)interrupts, 但是很多時候大家對其區(qū)分不是很嚴(yán)格, 經(jīng)常一個interrupt signal就包括前面?zhèn)z貨了, 不過這個實現(xiàn)都是平臺相關(guān)的, 可能別的體系就有另一套說辭, 或者能更一步細(xì)化, 比如在古老的Linux/i386中, 其實現(xiàn)就是interrupt 0x80
說完fault, 我們再回到Segmentation, 其實它就是一段內(nèi)存, 但是帶有一個值來標(biāo)記內(nèi)存, 並且還包含偏移量, 當(dāng)然也分爲(wèi)物理內(nèi)存和虛擬內(nèi)存, 這裏只說虛擬內(nèi)存, 因爲(wèi)你編寫的c/c++程序用到的都是虛擬內(nèi)存而不是物理內(nèi)存. Segmentation fault]合在一起就是一個trap/exception/fault/software interrupt, 因爲(wèi)它訪問了不該訪問的內(nèi)存.
it's my typo: data->date
Thanks for Chen's answer
fgetc的返回值是int類型。一個可能的解釋是fgetc失敗了,返回了-1,導(dǎo)致你換算后的二進(jìn)制全是1。
把ch的聲明改成int
while( (ch = fgetc(fp)) != 255){
改為
while( (ch = fgetc(fp)) != -1){
while之后打印一下errno:
printf("%d %s\n", errno, strerror(errno));
看到底是什么原因?qū)е耭getc失敗.
也是遇到這樣的問題,現(xiàn)在直接放棄c++了
個人理解空間復(fù)雜度為O(1)的歸并排序是指內(nèi)存方面的空間復(fù)雜度,而忽略了堆棧里的O(logN)的空間復(fù)雜度(畢竟不在同一個空間)
//空間復(fù)雜度為O(1)的歸并排序
#include <iostream>
using namespace std;
void reverse_array(int a[], int n) {
int i = 0;
int j = n - 1;
while (i < j) {
swap(a[i], a[j]);
++i;
--j;
}
}
void exchange(int a[], int length, int length_left) {
reverse_array(a, length_left);
reverse_array(a + length_left, length - length_left);
reverse_array(a, length);
}
void Merge(int a[], int begin, int mid, int end) {
while (begin < mid && mid <= end) {
int step = 0;
while (begin < mid && a[begin] <= a[mid])
++begin;
while (mid <= end && a[mid] <= a[begin]) {
++mid;
++step;
}
exchange(a + begin, mid - begin, mid - begin - step);
}
}
void MergeCore(int a[], int left, int right) {
if (left < right) {
int mid = (left + right) / 2;
MergeCore(a, left, mid);
MergeCore(a, mid + 1, right);
Merge(a, left, mid + 1, right);
}
}
void MergeSort(int a[], int length) {
if (a == NULL || length < 1)
return;
MergeCore(a, 0, length - 1);
}
int main() {
int a[] = {1,0,2,9,3,8,4,7,6,5,11,99,22,88,11};
int length = sizeof(a) / sizeof(int);
MergeSort(a, length);
for (int i = 0; i < length; i++)
cout << a[i] << " ";
cout << endl;
return 0;
}北大青鳥APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國IT技能型緊缺人才,是大數(shù)據(jù)專業(yè)的國家
達(dá)內(nèi)教育集團(tuán)成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機(jī)構(gòu),是中國一站式人才培養(yǎng)平臺、一站式人才輸送平臺。2014年4月3日在美國成功上市,融資1
北大課工場是北京大學(xué)校辦產(chǎn)業(yè)為響應(yīng)國家深化產(chǎn)教融合/校企合作的政策,積極推進(jìn)“中國制造2025”,實現(xiàn)中華民族偉大復(fù)興的升級產(chǎn)業(yè)鏈。利用北京大學(xué)優(yōu)質(zhì)教育資源及背
博為峰,中國職業(yè)人才培訓(xùn)領(lǐng)域的先行者
曾工作于聯(lián)想擔(dān)任系統(tǒng)開發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項目經(jīng)理從事移動互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
浪潮集團(tuán)項目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺面向?qū)ο箝_發(fā)經(jīng)驗,技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點難點突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫,具有快速界面開發(fā)的能力,對瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁制作和網(wǎng)頁游戲開發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開發(fā)經(jīng)驗。曾經(jīng)歷任德國Software AG 技術(shù)顧問,美國Dachieve 系統(tǒng)架構(gòu)師,美國AngelEngineers Inc. 系統(tǒng)架構(gòu)師。