利用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 小鼠标 阅读(3954) |
评论 (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 小鼠标 阅读(390) |
评论 (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 小鼠标 阅读(1194) |
评论 (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 小鼠标 阅读(187) |
评论 (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 小鼠标 阅读(168) |
评论 (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 小鼠标 阅读(478) |
评论 (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 小鼠标 阅读(605) |
评论 (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 小鼠标 阅读(279) |
评论 (0) |
编辑 收藏
求第100002个素数。(2是第一个素数)
结题思路:素数筛法
代码如下:
import java.util.Arrays;
public class Copy_2_of_Main {
static int N = 10000000;
static int count;
static int rs[] = new int[N];
static boolean tg[] = new boolean[N];//is prime
public static void main(String[] args) {
Arrays.fill(tg, true);
int ed = (int)Math.sqrt(N) + 1;
for(int i = 2; i <= ed; i++){//素数筛法
if(tg[i]){
for(int j = i * 2; j < N; j += i){// j += i
tg[j] = false;
}
}
}
count = 0;
for(int i = 2; i < N; i++){
if(tg[i] == true){
rs[count++] = i;
}
}
System.out.println("count=" + count);
System.out.println("result=" + rs[100001]);
// for(int i = 0; i < count; i++)
// System.out.println(rs[i]);
}
}
posted @
2013-07-06 19:38 小鼠标 阅读(166) |
评论 (0) |
编辑 收藏
摘要: 题目描述如下:
ABCDE五人安排工作日程,每人每星期工作5天休息2天
1) 必须有3天所有人都要上班
2) 每个人连续上班不超过3天,周日到周一是连续工作
3) &...
阅读全文
posted @
2013-07-06 15:43 小鼠标 阅读(202) |
评论 (0) |
编辑 收藏