利用select函數可以完成非阻塞通信,它可以在用戶指定的時間內監聽一些句柄(文件描述符?)(一個句柄就是你給一個文件,設備,套接字(socket)或管道的一個名字, 以便幫助你記住你正處理的名字, 并隱藏某些緩存等的復雜性。),當readfds或writefds中映象的文件可讀或可寫或超時,本次select()就結束返回。程序員利用一組系統提供的宏在select()結束時便可判斷哪一文件可讀或可寫。
。
函數原型:
int select(int nfds, fd_set *readfds, fd_set *writefds,
fd_set *exceptfds, struct timeval *timeout);
ndfs:select監視的文件句柄數,視進程中打開的文件數而定,一般設為你要監視各文件
中的最大文件號加一。
readfds:select監視的可讀文件句柄集合。
writefds: select監視的可寫文件句柄集合。
exceptfds:select監視的異常文件句柄集合。
timeout:本次select()的超時結束時間。
函數返回值:
0表示超時
-1表示出錯
正數表示文件可讀或可寫
相關的宏:
FD_ZERO(fd_set *fdset):清空fdset與所有文件句柄的聯系。
FD_SET(int fd, fd_set *fdset):建立文件句柄fd與fdset的聯系。
FD_CLR(int fd, fd_set *fdset):清除文件句柄fd與fdset的聯系。
FD_ISSET(int fd, fd_set *fdset):檢查fdset聯系的文件句柄fd是否可讀寫,當>0表示可讀寫。
select只能監聽文件描述符(file descriptors),文件指針是不行的。通過int fileno(FILE* fp)函數可以完成文件指針到文件描述符的轉換。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/time.h>
#include<sys/types.h>
#include<unistd.h>
int main(){
int fno = fileno(stdin);
// 得到sdtin的文件描述符
fd_set fdR;
struct timeval timeout = {.tv_sec = 10, .tv_usec = 0};
FD_ZERO(&fdR);
FD_SET(fno, &fdR);
char str[64];
int goOn = 1;
while(goOn){
printf("goOning
\n");
switch(select(fno + 1, &fdR, NULL, NULL, &timeout)){
case -1:
printf("select fail\n");
goOn = 0;
break;
case 0:
printf("select end\n");
goOn = 0;
break;
default:
scanf("%s", str);
printf("str=%s\n", str);
}
}
}
代碼片段1:在指定時間內讀取stdin的數據。
代碼片段2:服務器在一定時間內接收子節點發來的數據報。
int socketfd = socket(AF_INET, SOCK_DGRAM, 0);
…

…

fd_set fdR;
struct timeval timeout = {tv_sec:10, tv_usec:0};// 等待接收一定時間之后結束
int goOn = 1;
FD_ZERO(&fdR);
FD_SET(sockfd, &fdR);
while(goOn){
switch(select(sockfd + 1, &fdR, NULL, NULL, &timeout)){
case -1:
printf("select fail\n");
goOn = 0;
break;
case 0:
printf("select timeout\n");
goOn = 0;
break;
default:
// 正常情況,讀取信息
if((numbytes = recvfrom(sockfd, &cdt, sizeof(cdt), 0,
(struct sockaddr *)&their_addr, &addr_len)) == -1){
printf("recvfrom fail\n");
}
}
參閱:
http://www.tuicool.com/articles/Rfeaie
posted @
2014-03-26 16:25 小鼠標 閱讀(3980) |
評論 (0) |
編輯 收藏
脫氧核糖核酸即常說的DNA,是一類帶有遺傳信息的生物大分子。它由4種主要的脫氧核苷酸(dAMP、dGMP、dCMT和dTMP)通過磷酸二酯鍵連接而成。這4種核苷酸可以分別記為:A、G、C、T。
DNA攜帶的遺傳信息可以用形如:AGGTCGACTCCA.... 的串來表示。DNA在轉錄復制的過程中可能會發生隨機的偏差,這才最終造就了生物的多樣性。
為了簡化問題,我們假設,DNA在復制的時候可能出現的偏差是(理論上,對每個堿基被復制時,都可能出現偏差):
1. 漏掉某個脫氧核苷酸。例如把 AGGT 復制成為:AGT
2. 錯碼,例如把 AGGT 復制成了:AGCT
3. 重碼,例如把 AGGT 復制成了:AAGGT
如果某DNA串a,最少要經過 n 次出錯,才能變為DNA串b,則稱這兩個DNA串的距離為 n。
例如:AGGTCATATTCC 與 CGGTCATATTC 的距離為 2
你的任務是:編寫程序,找到兩個DNA串的距離。
【輸入、輸出格式要求】
用戶先輸入整數n(n<100),表示接下來有2n行數據。
接下來輸入的2n行每2行表示一組要比對的DNA。(每行數據長度<10000)
程序則輸出n行,表示這n組DNA的距離。
例如:用戶輸入:
3
AGCTAAGGCCTT
AGCTAAGGCCT
AGCTAAGGCCTT
AGGCTAAGGCCTT
AGCTAAGGCCTT
AGCTTAAGGCTT
則程序應輸出:
1
1
2
結題思路:參閱百度百科http://baike.baidu.com/view/2020247.htm
代碼如下:
import java.util.*;



public class Main
{
static String instr0;
static String instr1;
public static void main(String[] args)

{
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
sc.nextLine();

for(int ii = 0; ii < N; ii++)
{
instr0 = sc.nextLine();
instr1 = sc.nextLine();
int rs = pro();
System.out.println(rs);
}
}

static int pro()
{
int[][] dis = new int[instr0.length()][instr1.length()];
for(int i = 0; i < instr0.length(); i++)
dis[i][0] = i;
for(int j = 0; j < instr1.length(); j++)
dis[0][j] = j;

for(int i = 1; i < instr0.length(); i++)
{

for(int j = 1; j < instr1.length(); j++)
{
int cost = 0;
if(instr0.charAt(i) != instr1.charAt(j))
cost = 1;
dis[i][j] = min3(dis[i - 1][j] + 1, dis[i][j - 1] + 1,
dis[i - 1][j - 1] + cost);
}
}
return dis[instr0.length() - 1][instr1.length() - 1];
}

static int min3(int a, int b, int c)
{
return Math.min(Math.min(a, b), c);
}

}
posted @
2013-07-09 19:26 小鼠標 閱讀(399) |
評論 (0) |
編輯 收藏
在很多軟件中,輸入拼音的首寫字母就可以快速定位到某個詞條。比如,在鐵路售票軟件中,輸入: “bj”就可以定位到“北京”。怎樣在自己的軟件中實現這個功能呢?問題的關鍵在于:對每個漢字必須能計算出它的拼音首字母。
GB2312漢字編碼方式中,一級漢字的3755個是按照拼音順序排列的。我們可以利用這個特征,對常用漢字求拼音首字母。
GB2312編碼方案對每個漢字采用兩個字節表示。第一個字節為區號,第二個字節為區中的偏移號。為了能與已有的ASCII編碼兼容(中西文混排),區號和偏移編號都從0xA1開始。
我們只要找到拼音a,b,c,...x,y,z 每個字母所對應的GB2312編碼的第一個漢字,就可以定位所有一級漢字的拼音首字母了(不考慮多音字的情況)。下面這個表給出了前述信息。請你利用該表編寫程序,求出常用漢字的拼音首字母。
a 啊 B0A1
b 芭 B0C5
c 擦 B2C1
d 搭 B4EE
e 蛾 B6EA
f 發 B7A2
g 噶 B8C1
h 哈 B9FE
j 擊 BBF7
k 喀 BFA6
l 垃 C0AC
m 媽 C2E8
n 拿 C4C3
o 哦 C5B6
p 啪 C5BE
q 期 C6DA
r 然 C8BB
s 撒 C8F6
t 塌 CBFA
w 挖 CDDA
x 昔 CEF4
y 壓 D1B9
z 匝 D4D1
【輸入、輸出格式要求】
用戶先輸入一個整數n (n<100),表示接下來將有n行文本。接著輸入n行中文串(每個串不超過50個漢字)。
程序則輸出n行,每行內容為用戶輸入的對應行的漢字的拼音首字母。
字母間不留空格,全部使用大寫字母。
例如:
用戶輸入:
3
大家愛科學
北京天安門廣場
軟件大賽
則程序輸出:
DJAKX
BJTAMGC
RJDS
結題思路:
C語言中的一個漢字占兩個字節(兩個char),我們只需把這兩個字節對應的int型數字算出來,然后到編碼表里去比較即可。計算該數字時要用到
移位,與,或等位運算操作。
代碼如下:
#include<stdio.h>
#include<string.h>
int N;
char str[200];

void pro()
{
for(int i = 0; i < strlen(str) - 1; )

{
char c0 = str[i++];
char c1 = str[i++];
int t = (int)c0 << 8;//得到高八位
t = t | (0x000000ff & (int)c1);//得到低八位
t &= 0x0000ffff;//去掉負號

if(t >= 0xB0A1 && t < 0xB0C5)
{
printf("A");
}
else if(t < 0xB2C1)
printf("B");
else if(t < 0xB4EE)
printf("C");
else if(t < 0xB6EA)
printf("D");
else if(t < 0xB7A2)
printf("E");
else if(t < 0xB8C1)
printf("F");
else if(t < 0xB9FE)
printf("G");
else if(t < 0xBBF7)
printf("H");
else if(t < 0xBFA6)
printf("J");
else if(t < 0xC0AC)
printf("K");
else if(t < 0xC2E8)
printf("L");
else if(t < 0xC4C3)
printf("M");
else if(t < 0xC5B6)
printf("N");
else if(t < 0xC5BE)
printf("O");
else if(t < 0xC6DA)
printf("P");
else if(t < 0xC8BB)
printf("Q");
else if(t < 0xC8F6)
printf("R");
else if(t < 0xCBFA)
printf("S");
else if(t < 0xCDDA)
printf("T");
else if(t < 0xCEF4)
printf("W");
else if(t < 0xD1B9)
printf("X");
else if(t < 0xD4D1)
printf("Y");
else
printf("Z");
}
printf("\n");
}

int main()


{
scanf("%d", &N);
getchar();
for(int i = 0; i < N; i++)

{
gets(str);
pro();
}
//getchar();
}

posted @
2013-07-09 11:04 小鼠標 閱讀(1212) |
評論 (0) |
編輯 收藏
1949年的國慶節(10月1日)是星期六。
今年(2012)的國慶節是星期一。
那么,從建國到現在,有幾次國慶節正好是星期日呢?
不多說了,直接上代碼:
import java.util.*;



public class Main
{
public static void main(String[] args)

{
int count = 0;
int weekd = 5;

for(int i = 1950; i < 2013; i++)
{
int y = 365;
if(isRN(i))
y++;
weekd = (weekd + y) % 7;

if(weekd == 6)
{
count++;
System.out.println("i=" + i);
}
}
System.out.println("count=" + count);
}

static boolean isRN(int y)
{
if(y % 4 == 0 && y % 100 != 0 || y % 400 == 0)
return true;
return false;
}

}
posted @
2013-07-09 09:22 小鼠標 閱讀(200) |
評論 (0) |
編輯 收藏
截取JDK文檔中的一部分,感覺這些東西我以后會用到。
字符類 |
[abc] |
a、b 或 c(簡單類) |
[^abc] |
任何字符,除了 a、b 或 c(否定) |
[a-zA-Z] |
a 到 z 或 A 到 Z,兩頭的字母包括在內(范圍) |
[a-d[m-p]] |
a 到 d 或 m 到 p:[a-dm-p](并集) |
[a-z&&[def]] |
d、e 或 f(交集) |
[a-z&&[^bc]] |
a 到 z,除了 b 和 c:[ad-z](減去) |
[a-z&&[^m-p]] |
a 到 z,而非 m 到 p:[a-lq-z](減去) |
Greedy 數量詞 |
X? |
X,一次或一次也沒有 |
X* |
X,零次或多次 |
X+ |
X,一次或多次 |
X{n} |
X,恰好 n 次 |
X{n,} |
X,至少 n 次 |
X{n,m} |
X,至少 n 次,但是不超過 m 次 |
這些目前來說夠用啦。
posted @
2013-07-09 09:00 小鼠標 閱讀(175) |
評論 (0) |
編輯 收藏
【編程題】(滿分21分)
Excel是最常用的辦公軟件。每個單元格都有唯一的地址表示。比如:第12行第4列表示為:“D12”,第5行第255列表示為“IU5”。
事實上,Excel提供了兩種地址表示方法,還有一種表示法叫做RC格式地址。 第12行第4列表示為:“R12C4”,第5行第255列表示為“R5C255”。
你的任務是:編寫程序,實現從RC地址格式到常規地址格式的轉換。
【輸入、輸出格式要求】
用戶先輸入一個整數n(n<100),表示接下來有n行輸入數據。
接著輸入的n行數據是RC格式的Excel單元格地址表示法。
程序則輸出n行數據,每行是轉換后的常規地址表示法。
例如:用戶輸入:
2
R12C4
R5C255
則程序應該輸出:
D12
IU5
結題思路:字符串處理,26進制轉換。特別注意26要被轉換成Z,因為A表示的是1而不是0。
代碼如下:
(代碼實現了兩種格式的互換問題)
import java.util.*;



public class Main
{
static int N;
static String instr1;
public static void main(String[] args)

{
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
sc.nextLine();

for(int i = 0; i < N; i++)
{
instr1 = sc.nextLine();

if(isRC(instr1))
{
toAN();
}

else
{
toRC();
}
}
}

static void toRC()
{

/**//*
* D12-->R12C4
*/
int i = 0;
int numc = 0;

while(Character.isLetter(instr1.charAt(i)))
{
numc *= 26;
numc += instr1.charAt(i) - 'A' + 1;
i++;
}
int numr = Integer.parseInt(instr1.substring(i));
System.out.println("R" + numr + "C" + numc);
}

static void toAN()
{

/**//*
* R12C4-->D12
*/
StringBuffer sbuf = new StringBuffer();
String[] strs = instr1.split("[RC]");//正則式很有趣
int numc = Integer.parseInt(strs[2]);

while(numc > 0)
{
char c = (char)((numc - 1) % 26 + 'A');//num - 1,避免26被轉換為A
sbuf.append(c);
numc = (numc - 1) / 26;//num - 1,避免26被轉換為AZ
}
System.out.println(sbuf.reverse() + strs[1]);
}

static boolean isRC(String instr)
{
int count = 0;
boolean isnumbg = false;

for(int i = 0; i < instr.length(); )
{

if(Character.isDigit(instr.charAt(i)))
{

if(isnumbg)
{
i++;
}

else
{
isnumbg = true;
count++;
i++;
}
}

else
{

if(isnumbg)
{
isnumbg = false;
}
i++;
}
}
if(count == 2)
return true;
return false;
}
}
posted @
2013-07-07 20:27 小鼠標 閱讀(497) |
評論 (0) |
編輯 收藏
某少年宮引進了一批機器人小車。可以接受預先輸入的指令,按指令行動。小車的基本動作很簡單,只有3種:左轉(記為L),右轉(記為R),向前走若干厘米(直接記數字)。
例如,我們可以對小車輸入如下的指令:
15L10R5LRR10R20
則,小車先直行15厘米,左轉,再走10厘米,再右轉,...
不難看出,對于此指令串,小車又回到了出發地。
你的任務是:編寫程序,由用戶輸入指令,程序輸出每條指令執行后小車位置與指令執行前小車位置的直線距離。
【輸入、輸出格式要求】
用戶先輸入一個整數n(n<100),表示接下來將有n條指令。
接下來輸入n條指令。每條指令只由L、R和數字組成(數字是0~100之間的整數)
每條指令的長度不超過256個字符。
程序則輸出n行結果。
每條結果表示小車執行相應的指令前后位置的直線距離。要求四舍五入到小數后2位。
例如:用戶輸入:
5
L100R50R10
3LLL5RR4L12
LL
100R
5L5L5L5
則程序輸出:
102.96
9.06
0.00
100.00
0.00
結題思路:
模擬機器人行走即可,用數字表示機器人的方向,向上為0,向右為1,下為2,左為3。設初始狀態機器人方向為0,則遇到R就將當前方向加1,遇到L將當前方向減1。x軸向右增大,y軸向上增大。
代碼如下:
import java.util.*;


public class Main
{
static int x = 0;
static int y = 0;
static int nowdir = 0;
static int N;
static String instr;
public static void main(String[] args)

{
Scanner sc = new Scanner(System.in);
N = sc.nextInt();
sc.nextLine();

for(int i = 0; i < N; i++)
{
instr = sc.nextLine();
x = 0;
y = 0;
nowdir = 0;
pro();
double dis0 = Math.sqrt(x * x + y * y);
System.out.printf("%.2f\n", dis0);
}
}

static void pro()
{
boolean isnumbg = false;
int numbgp = 0;
instr = instr + "#";

for(int i = 0; i < instr.length();)
{

if(Character.isDigit(instr.charAt(i)))
{

if(isnumbg)
{
i++;
continue;
}

else
{
numbgp = i++;
isnumbg = true;
}
}

else
{

if(isnumbg)
{
isnumbg = false;
String str1 = instr.substring(numbgp, i);
int dis = Integer.parseInt(str1);

if(nowdir == 0)
{
y += dis;
}

else if(nowdir == 2)
{
y -= dis;
}

else if(nowdir == 1)
{
x += dis;
}
else
x -= dis;
}

else
{
char c = instr.charAt(i);

if(c == 'R')
{
nowdir = (nowdir + 1) % 4;
}

else if(c == 'L')
{
nowdir = (nowdir + 3) % 4;
}
i++;
}
}
}
}
}
posted @
2013-07-07 17:16 小鼠標 閱讀(632) |
評論 (0) |
編輯 收藏
看這個算式:
☆☆☆ + ☆☆☆ = ☆☆☆
如果每個五角星代表 1 ~ 9 的不同的數字。
這個算式有多少種可能的正確填寫方法?
173 + 286 = 459
295 + 173 = 468
173 + 295 = 468
183 + 492 = 675
以上都是正確的填寫法!
注意:
111 + 222 = 333 是錯誤的填寫法!
因為每個數字必須是不同的!
也就是說:1~9中的所有數字,每個必須出現且僅出現一次!
結題思路:
排列1~9,寫出符合條件的結果。
代碼如下:


public class Main
{

static int bs[] =
{1, 2, 3, 4, 5, 6, 7, 8, 9};
static int count = 0;
public static void main(String[] args)

{
count = 0;
DFS(0);
System.out.println("count=" + count);
}

static void DFS(int nowp)
{

if(nowp == bs.length)
{
int n1 = bs[0] * 100 + bs[1] * 10 + bs[2];
int n2 = bs[3] * 100 + bs[4] * 10 + bs[5];
int n3 = bs[6] * 100 + bs[7] * 10 + bs[8];

if(n1 + n2 == n3)
{
System.out.println(n1 + " + " + n2 + " = " + n3);
count++;
}
}

else
{

for(int i = nowp; i < bs.length; i++)
{
swap(nowp, i);
DFS(nowp + 1);
swap(nowp, i);
}
}
}

static void swap(int a, int b)
{
int t = bs[a];
bs[a] = bs[b];
bs[b] = t;
}
}
posted @
2013-07-07 16:08 小鼠標 閱讀(286) |
評論 (0) |
編輯 收藏