在unix下提到文件属性,不得不提的一个结构就是stat,stat结构一般定义如下:

struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};

每个字段什么意思,注释写的很详细。通过下面的函数可以获取这个结构:

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h> int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);

三个函数成功返回0,失败返回-1.其中需要注意的是lstat函数不跟随符号链接,当path是符号链接时获取符号链接本身的属性而不是符号链接所指的文件属性。下面围绕各个字段展开:

文件类型和访问权限

文件的类型和操作权限在st_mode中给出,文件的类型可以通过下面的宏获取:

S_ISREG(st_mode) //是否是普通文件

S_ISDIR(st_mode) //是否是目录文件

S_ISBLK(st_mode) //是否是块文件

S_ISCHR(st_mode) //是否是字符文件

S_ISSOCK(st_mode) //是否是socket文件

S_ISFIFO(st_mode) //是否是FIFO

S_ISLNK(st_mode)  //是否是符号链接文件

文件访问模式定义如下:

  用户 其他
S_IRUSR S_IRGRP S_IROTH
S_IWUSR S_IWGRP S_IWOTH
执行 S_IXUSR S_IXGRP S_IXOTH
综合 S_RWXU S_RWXO S_RWXO

下面是一个判断文件类型和文件访问模式的小程序:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h> int main(int argc,char* argv[])
{
int ret ;
struct stat buf;
char* ptr = NULL; for(int i=;i<argc;i++)
{
printf("%s:",argv[i]); ret = lstat(argv[i],&buf);
if(ret == -)
{
printf("lstat failed\n");
return -;
} if(S_ISREG(buf.st_mode))
{
ptr = "reguler file"; } if(S_ISDIR(buf.st_mode))
{
ptr = "dir file";
} if(S_ISBLK(buf.st_mode))
{
ptr = "block file";
} if(S_ISCHR(buf.st_mode))
{
ptr = "char file";
} if(S_ISSOCK(buf.st_mode))
{
ptr = "socket file";
} if(S_ISFIFO(buf.st_mode))
{
ptr = "fifo file";
} if(S_ISLNK(buf.st_mode))
{
ptr = "link file";
} printf("%s;privilege:",ptr); if(buf.st_mode & S_IRWXU)
ptr = "user all";
if(buf.st_mode & S_IRUSR)
ptr = "user read";
if(buf.st_mode & S_IWUSR)
ptr = "user write";
if(buf.st_mode & S_IXUSR)
ptr = "user excute";
if(buf.st_mode & S_IRWXG)
ptr = "group all";
if(buf.st_mode & S_IRGRP)
ptr = "group read";
if(buf.st_mode & S_IWGRP)
ptr = "group write";
if(buf.st_mode & S_IXGRP)
ptr = "group excute";
if(buf.st_mode & S_IRWXO)
ptr = "other all";
if(buf.st_mode & S_IROTH)
ptr = "other read";
if(buf.st_mode & S_IWOTH)
ptr = "other write";
if(buf.st_mode & S_IXOTH)
ptr = "other excute";
if(buf.st_mode & S_ISUID)
ptr = "set uid";
if(buf.st_mode & S_ISGID)
ptr = "set gid";
if(buf.st_mode & S_ISVTX)
ptr = "sticky bit on";
printf("%s\n",ptr); }
}

下面是执行结果:

$ ./test /etc/passwd /etc /dev/log  /dev/tty /dev/sr0 /dev/cdrom
/etc/passwd:reguler file;privilege:other read
/etc:dir file;privilege:other excute
/dev/log:socket file;privilege:other write
/dev/tty:char file;privilege:other write
/dev/sr0:block file;privilege:group write
/dev/cdrom:link file;privilege:other excute

调用create函数或者open创建新的文件需要指定的访问模式就是其中的一种或者几种的组合。

文件访问权限检查

每个文件都有一个所有者(stat结构中st_uid表示)以及一个所属组(stat结构中st_gid表示),而每个进程都有下面接个ID:

  • 真实用户ID 真实组ID
  • 有效用户ID 有效组ID 附加组ID
  • 保存的设置用户ID 保存的设置组ID

其中保存的设置用户ID 和保存的设置组ID由 exec函数从有效用户ID和有效组ID拷贝而来.

真实用户ID和真实组ID 表明了我们是谁,由账户文件/etc/password中读取而来.中间的三个ID用来检查进程是否可以访问文件。

一般来说进程的有效用户ID等于实际用户ID,有效组ID等于实际组ID。不过执行设置用户ID位或者设置组ID位的程序就不一样了,这种情况下有效用户ID等于程序文件所有者ID或者有效组ID等于程序文件所有组ID,典型的文件就是passwd文件。

当我们想访问某个目录下的某个文件的时候,我们必须有访问这些目录的权限。读一个目录的权限指可以获取目录下的目录项列表,写目录指能够在目录下建立文件,写文件,删除文件,执行权限指能够进入这个目录。

一般来讲一个进程是否能够访问某个文件,内核会按照以下步骤去检查:

  • 进程的有效ID是否等于文件的所有者ID,如果相等进程具有访问这个文件相应的权限(这里相应的权限指是否能够读写执行)
  • 进程的有效组ID或者附件组ID是否等于文件的所属组ID,如果相等进程具有访问这个文件的相应权限
  • 文件其他访问权限的检查

有时候也需要通过真实用户ID和真实组ID去访问文件,内核的检查顺序同上,只不过将有效用户ID和有效组ID换成了真实用户ID和真实组ID。对于通过真实用户ID和真实组ID访问文件有下面函数:

#include <unistd.h>
int access(const char *pathname, int mode);

成功返回0,失败返回-1.mode取值如下:F_OK,R_OK,W_OK,X_OK,分别是文件存在,文件读,文件写,文件执行。

下面是个说明两种访问方式区别的小程序:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h> int main(int argc,char* argv[])
{
if(argc != )
{
printf("usage:./test path\n");
return -;
} if(access(argv[],R_OK) == -)
{
printf("access error for %s\n",argv[]); }else
{
printf("access OK for %s\n",argv[]);
} if(open(argv[],O_RDONLY) < )
{
printf("open error for %s\n",argv[]);
}else
{ printf("open for read OK for %s\n",argv[]);
} return ;
}

执行结果如下:

hero@powerPC:~/source$ ls -l test
-rwxrwxr-x hero hero 10月 : test
hero@powerPC:~/source$ ./test test
access OK for test
open for read OK for test
hero@powerPC:~/source$ ls -l a
-r-------- root root 10月 : a
hero@powerPC:~/source$ ./test a
access error for a
open error for a
hero@powerPC:~/source$ su
Password:
root@powerPC:/home/hero/source# chown root test
root@powerPC:/home/hero/source# chmod u+s test
root@powerPC:/home/hero/source# exit
exit
hero@powerPC:~/source$ ls -l test
-rwsrwxr-x root hero 10月 : test
hero@powerPC:~/source$ ./test a
access error for a
open for read OK for a
hero@powerPC:~/source$

改变文件权限和所有者

下面说说怎么改变文件的权限和所有者,在Unix下通过下面的函数改变文件的权限:

#include <sys/stat.h>

 int chmod(const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);

成功返回0,失败返回-1.

改变文件权限的进程的有效用户ID必须等于文件所有者ID或者进程具有超级用户权限,此外如果进程的有效组ID或者附加组ID不等于文件的组ID,文件的设置组ID位自动关闭。在Linux上如果进程没有授权,那么写文件的时候文件的设置用户ID和设置组ID自动关闭。请看下面的小程序:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#define mode (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
int main(int argc,char* argv[])
{
int errno;
if(argc != )
{
printf("usage:./test %s",argv[]);
return -;
}
if(chmod(argv[],mode) < )
{
if(errno == EPERM)
{
printf("process euid not equal file uid or process not privilege\n");
return -;
}
printf("chmod failed\n");
}
return ;
}

下面是测试结果:

hero@powerPC:~/source$ ls -l test_file*
-rw-r--r-- root root 11月 : test_file1
-rw-rwSr-- hero root 11月 : test_file2
hero@powerPC:~/source$ ./test test_file1
process euid not equal file uid or process not privilege
hero@powerPC:~/source$ ./test test_file2
hero@powerPC:~/source$ ls -l test_file2
-rw-rw-rw- hero root 11月 : test_file2

通过下面的函数改变文件的归宿:

#include <unistd.h>

 int chown(const char *path, uid_t owner, gid_t group);
int fchown(int fd, uid_t owner, gid_t group);
int lchown(const char *path, uid_t owner, gid_t group);
return - faild, OK

只有超级用户进程能够改变文件的用户ID,文件的所有者能够将文件组改为自己所属于的任意组。如果owner或者group等于-1,文件的归宿不变。一个可执行文件如果被一个未授权进程修改,那么文件的设置用户ID和设置组ID自动清除。

新建文件的用户ID等于进程的有效ID,新建文件的组ID可能等于创建文件目录的组ID或者等于进程的有效组ID。如果创建文件的目录设置了粘住位,那么新建文件的组ID等于创建文件的目录的组ID。一个设置了粘住位的目录意味着只有对目录具有写权限同时满足下面任何一个条件才可以删除目录下的文件或者改变它们的名称:

拥有文件,拥有目录,拥有超级用户权限

进程可以通过umask函数改变进程新建文件的访问权限:

#include <sys/types.h>
#include <sys/stat.h>
mode_t umask(mode_t mask);
//Allways return OK

注意该函数不改变其他进程的umask值。请看小程序:

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h> #define RWRWRW (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
#define UMASK (S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
int main(int argc,char* argv[])
{
if(argc != )
{
printf("usage ./test %s",argv[]);
return -;
} umask(UMASK); if(creat(argv[],RWRWRW)< )
{
printf("creat file :%s failed\n",argv[]);
return -;
}
return ; }

执行结果如下:

hero@powerPC:~/source$ umask

hero@powerPC:~/source$ ./test tf
hero@powerPC:~/source$ ll
total
drwxrwxr-x hero hero 11月 : ./
drwxr-xr-x hero hero 11月 : ../
-rw-rw-r-- hero hero 11月 : chmod.c
-rwxrwxr-x hero hero 11月 : test*
-rw------- hero hero 11月 : tf
-rw-rw-r-- hero hero 11月 : umask.c
hero@powerPC:~/source$ umask

上面的程序并没有改变设立了的umask值,只影响了调用进程新建文件的权限。

文件长度

在stat结构中st_size表示文件的大小,只有普通文件,目录文件和符号链接文件有大小,普通文件的大小可以是0,但是目录文件和符号链接文件的大小绝不可能是0,因为目录文件至少有两个目录项,符号文件的大小就是它所指的文件的文件路径长度。使用下面函数可以从尾端截断普通文件。

#include <unistd.h>
#include <sys/types.h> int truncate(const char *path, off_t length);
int ftruncate(int fd, off_t length);
//On success, zero is returned. On error, -1 is returned, and errno is set appropriately.

如果原来的文件比length要长,超过的部分将不能访问,如果原来的长度比length短,那么中间就是就是\0,注意文件的offset不会改变。如果文件大小发生改变,文件的mtime和ctime发生变化,设置用户ID和设置组ID可能清除。注意文件必须是可写的。

链接

对于每个文件有多个目录项指向它的i-node,通过下面函数可以建立一个指向已有文件的硬链接。

#include <unistd.h>

int link(const char *oldpath, const char *newpath);

// On success, zero is returned.  On error, -1 is returned, and errno is set appropriately.

如果newpath已经存在返回错误,只有最后的分量会被创建,之前的路径必须已经存在。

只有超级用户可以建立指向目录文件的硬链接。

删除一个目录项可以通过unlink函数:

#include <unistd.h>

 int unlink(const char *pathname);

// On success, zero is returned.  On error, -1 is returned, and errno is set appropriately.

如果指向该目录项的链接数变为0并且没有进程打开这个文件,那么文件被删除并且释放占有的空间,如果还有进程打开那么直到进程关闭它为止才会释放文件占用的空间,但是此时文件已经看不到了,请看小程序。如果pathname是一个符号链接,那么删除符号链接本身。如果是FIFO ,SOCK那么仅仅删除名字,文件仍然可以使用。

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h> int main(int argc,char* argv[])
{
if(argc != )
{
printf("usage ./test %s",argv[]);
return -;
} if(open(argv[],O_RDWR) < )
{
printf("open file failed\n");
return -;
}
if(unlink(argv[]) < )
{
printf("unlink file %s faild\n",argv[]);
} printf("file unlinked\n"); sleep(); printf("done\n"); return ;
}

下面是验证结果:

hero@powerPC:~/source$ clear
hero@powerPC:~/source$ df /home
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda1 % /
hero@powerPC:~/source$ ./test tmpfile &
[]
hero@powerPC:~/source$ file unlinked
ls tmpfile
ls: cannot access tmpfile: No such file or directory
hero@powerPC:~/source$ df /home
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda1 % /
hero@powerPC:~/source$ done
df /home
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/sda1 % /
[]+ Done ./test tmpfile

unlink一个目录应该使用rmdir,或者一个更好的函数,remove

#include <stdio.h>

 int remove(const char *pathname);
// On success, zero is returned. On error, -1 is returned, and errno is set appropriately.

对于目录这个函数相当于rmdir对于普通文件相当于unlink,如果是符号链接文件,删除符号链接本身,如果是FIFO ,SOCK那么仅仅删除名字,文件仍然可以使用。

符号链接

创建符号链接并要求在同一文件系统也没有创建目录硬链接的限制,通过syslink创建符号链接:

#include <unistd.h>

int symlink(const char *oldpath, const char *newpath);
//On success, zero is returned. On error, -1 is returned, and errno is set appropriately.

该函数并不要求odlpath已经存在。

由于open函数跟随符号链接,所以通过readlink读符号链接:

#include <unistd.h>

ssize_t readlink(const char *path, char *buf, size_t bufsiz);
// On success, readlink() returns the number of bytes placed in buf. On error, -1 is returned and errno is set to indicate the error.

注意bufsiz必须足够大否则有可能截断,同时返回的符号链接内容不包括\0。

重命名

文件和目录可以通过rename函数重命名:

#include <stdio.h>

 int rename(const char *oldpath, const char *newpath);
// On success, zero is returned. On error, -1 is returned, and errno is set appropriately.

如果oldpath是一个文件,那么newpath如果已经存在,那么它不能是目录,如果newpath不是目录那么先删除这个文件然后将oldpath重命名为newpath。

如果oldpath是一个目录,那么newpath如果已经存在,那么它不能是文件,如果newpath是目录且为空目录,那么先删除它然后将oldpath重命名为newpath。

同时newpath 不能包含oldpath.

如果oldpath或者newpath是符号链接,那么只处理符号链接本身。

如果oldpath 和newpath一样,那么函数什么都不做。

文件时间

通过futimens可以改变文件的访问时间和修改时间:

#include <sys/stat.h>
int futimens(int fd, const struct timespec times[]);
// On success, return 0. On error, -1 is returned and errno is set to indi cate the error.

times的第一个值表示访问时间,第二个值表示修改时间。timespec结构定义如下:

struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};

随着times的取值不同函数的行为以及进程需要的权限也不一样:

1.如果times的值为NULL,那么现在的时间将被使用,进程的有效用户ID必须等于文件所有者ID,进程必须对文件具有写权限

2.如果2个值的任何一个值的tv_nsec值为 UTIME_NOW,那么对应的值设置为现在时间,进程的有效用户ID必须等于文件所有者ID,进程必须对文件具有写权限

3.如果2个值的任何一个值的tv_nsec值为 UTIME_OMIT,那么对应的值不变

4.如果2个值都不为空而且tv_nsec不是 UTIME_NOW或者UTIME_OMIT,那么设置相应的值。进程的有效用户ID必须等于文件所有者ID。

目录

通过mkdir函数可以建立目录,rmdir删除目录,在建立目录的时候一般加上可执行权限。

#include <sys/stat.h>
#include <unistd.h>
int mkdir(const char *pathname, mode_t mode);
int rmdir(const char *pathname);
//Both return: 0 if OK, −1 on error

调用rmdir,pathname 必须是空目录。

目录可以被有权限的进程读,但是只有内核可以写目录。

#include <dirent.h>
DIR *opendir(const char *pathname);
DIR *fdopendir(int fd);
//Both return: pointer if OK, NULL on error
struct dirent *readdir(DIR *dp);
//Returns: pointer if OK, NULL at end of directory or error
void rewinddir(DIR *dp);
int closedir(DIR *dp);
//Returns: if OK, − on error
long telldir(DIR *dp);
//Returns: current location in directory associated with dp
void seekdir(DIR *dp, long loc);

每个进程都有一个当前工作目录,可以通过chdir改变进程当前工作目录,注意由于当前工作目录是进程的属性,调用此函数并不会改变运行程序的目录。

#include <unistd.h>
int chdir(const char *pathname);
int fchdir(int fd);
//Both return: 0 if OK, −1 on error

下面是个使用这些函数的示例小程序:

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <dirent.h>
#include <string>
using std::string; #define BUF_SIZE 100 char* pwd()
{
char* curdir = NULL;
char buf[BUF_SIZE];
curdir = getcwd(buf,BUF_SIZE);
if(curdir)
{
printf("curdir %s\n",curdir);
} return curdir;
} int newdir(const char* path)
{
if(mkdir(path,S_IRWXU|S_IRWXG|S_IROTH|S_IXOTH) < )
{
printf("create dir failed\n");
return -;
} return ; } int newfile(const char* path)
{
if(creat(path,S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH) < )
{
printf("create file failed\n");
return -;
} return ;
} int main(int argc,char* argv[])
{
int savedfd;
DIR* dir= NULL;
struct dirent* entry = NULL;
struct stat finfo;
char buf[BUF_SIZE]; string full_path =getcwd(buf,BUF_SIZE);
full_path.append("/");
full_path.append("testdir");
string prefix = full_path;
if((savedfd = open(".",O_DIRECTORY)) < )
{
printf("save current dir faild\n");
}
if(!pwd())
{
return -;
} if(newdir("testdir"))
{
return -;
} if(chdir("testdir")< )
{
printf("change into testdir faild\n");
return -;
} if(!pwd())
{
return -;
} if(newdir("testdir1"))
{
return -;
} if(newfile("testfile"))
{
return -;
} if(fchdir(savedfd)<)
{
printf("change to ori dir failed\n");
return -;
} dir = opendir("testdir"); if(dir == NULL)
{
printf("open dir testdir failed\n");
return -;
} while((entry = readdir(dir))!= NULL )
{
printf("dir entry name:%s\n",entry->d_name);
full_path = prefix + "/"+ entry->d_name;
printf("full path:%s\n",full_path.c_str());
if(stat(full_path.c_str(),&finfo) < )
{
printf("stat file %s failed\n",entry->d_name);
return -; } if(S_ISDIR(finfo.st_mode))
{
printf("%s is dir\n",entry->d_name);
} if(S_ISREG(finfo.st_mode))
{
printf("%s is reguler \n",entry->d_name);
}
} return closedir(dir); }

unix 文件属性的更多相关文章

  1. WxWidgets与其他工具包的比较(15种方案)

    一些一般注意事项: wxWidgets不仅适用于C ++,而且具有python,perl,php,java,lua,lisp,erlang,eiffel,C#(.NET),BASIC,ruby甚至ja ...

  2. 《Linux/Unix系统编程手册》读书笔记9(文件属性)

    <Linux/Unix系统编程手册>读书笔记 目录 在Linux里,万物皆文件.所以文件系统在Linux系统占有重要的地位.本文主要介绍的是文件的属性,只是稍微提及一下文件系统,日后如果有 ...

  3. 《UNIX环境高级编程》笔记——3.文件IO

    一.引言 说明几个I/O函数:open.read.write.lseek和close,这些函数都是不带缓冲(不带缓冲,只调用内核的一个系统调用),这些函数不输入ISO C,是POSIX的一部分: 多进 ...

  4. 《UNIX环境高级编程》笔记——1.UNIX基础知识

    这一章节侧重一些基本概念和书中用到的一些名词. 一.引言 所有的操作都提供服务,典型的服务包括:执行新程序.打开文件.读写文件.分配存储区以及获得当前时间等. 二.UNIX体系结构 其实linux常见 ...

  5. Unix/Linux编程实践教程(0:文件、终端、信号)

    本来只打算读这本书socket等相关内容,但书写得实在好,还是决定把其余的内容都读一下. 阅读联机帮助的一个示例: open系统调用: read系统调用: Unix的time: 上面的printf可以 ...

  6. (三) 一起学 Unix 环境高级编程 (APUE) 之 文件和目录

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  7. 在Linux或者Unix下打开,每一行都会出多出^M这样的字符

    Windows上写好的文件,在Linux或者Unix下打开,每一行都会出多出^M这样的字符,这是因为Windows与*nix的换行符不同所致,我们看看文件格式有什么不同. 在Linux下查看文件格式: ...

  8. 《Linux/Unix系统编程手册》读书笔记 目录

    <Linux/Unix系统编程手册>读书笔记1  (创建于4月3日,最后更新4月7日) <Linux/Unix系统编程手册>读书笔记2  (创建于4月9日,最后更新4月10日) ...

  9. 《UNIX环境高级编程》学习心得 四 文件I/O(一)

    这里说的文件I/O是相对标准I/O来说的.主要介绍在UNIX系统中常用的五个文件I/O函数:open.read.write.lseek.以及close. 一.open和opennat #include ...

随机推荐

  1. HDU1180+BFS

    bfs思路:三维标记状态 && 处理好 - | 和时刻的关系即可 /* bfs 思路:三维标记状态 && 处理好 - | 和时刻的关系即可 */ #include< ...

  2. Linux---More命令 初级实现

    Linux: more已实现:more filename , quit不需要回车未实现:command | more 重定向 ,显示百分比 Waiting... /* Linux: more 已实现: ...

  3. UR #13 Yist

    第一次打UR,打了一个半小时就弃疗了QAQ 这是我唯一一道考试的时候做出来的题目,其他两道连暴力都懒得写了 很容易发现对于每个要删除的点 我们找到左边第一个比他小的不用删除的点,右边第一个比他小的不用 ...

  4. 提供几个可注册的edu邮箱链接

    旧版的邮箱大全有edu邮箱的专题页面,放出来2个国内edu.cn邮箱的注册地址:@live.shop.edu.cn和@abc.shop.edu.cn,现在已经停止开放注册了. 其实旧版中还做了个隐藏的 ...

  5. Bridging signals ZOJ 3627 POJ1631 HDU1950

    题意:给出一个从1-n的数字排列,求最长上升子序列长度. 直接说解法吧.新开一个数组d,d[i]表示的是能构成长度为i的上升子序列的在原序列中最后的那个数值.程序的主要过程:当循环到第i个的时候,如果 ...

  6. swap chain- IDirect3DSwapChain9

    交换链,对应的接口是IDirect3DSwapChain9,是整个Directx 3D中最核心的接口.D3d程序至少包含一个swap chain,在调用CreateDevice时自动创建, 其中的D3 ...

  7. 游标-Oracle游标汇总

    游标(Cursor):用来查询数据库,获取记录集合(结果集)的指针,可以让开发者一次访问一行结果集,在每条结果集上作操作.    游标可分为:    <!--[if !supportLists] ...

  8. 【剑指offer】找出数组中出现一次的两个数

    2013-09-08 10:50:46 一个整型数组中,除了两个数字之外,其他数字都出现了2次,找出这两个只出现一次的数字,要求时间复杂度是O(N),空间复杂度是O(1). 小结: 任何数与0异或,结 ...

  9. js模仿jquery里的几个方法parent, parentUntil, children

    有时工作需要, 也是接着上一章的方法, 用js模仿jquery里的几个方法parent, parentUntil, children. function parent(node){ return no ...

  10. poj 2299 Ultra-QuickSort (归并排序 求逆序数)

    题目:http://poj.org/problem?id=2299 这个题目实际就是求逆序数,注意 long long 上白书上的模板 #include <iostream> #inclu ...