您的位置:首页 > 运维架构 > Linux

c++ 学习笔记(高级linux编程) day4

2014-08-19 18:29 579 查看
linux高级编程day04 笔记

一.IO与文件映射

1.IO的共享与效率

read与write其中数据缓冲的大小

读取数据的缓冲大小:getpagesize。

2.定位与定位读取(随机读取)

read与write在操作的时候,自动移动读取位置.

lseek改变读取位置.

pread/pwrite在指定位置读写。

2.1.lseek的函数说明:

off_t lseek(

int fd,//定位文件描述符号

off_t off,//定位位置

int whence//定位参照点:文件开始位置/文件结束位置/文件当前位置

//SEEK_SET SEEK_END SEEK_CUR

);

返回:

返回当前读取位置在文件中的绝对位置.

2.2.lseek的作用:定位文件的位置

问题:lseek的定位的位置超出文件的大小范围?

lseek移动位置只要合法,都是有效

2.3.lseek+write=pwrite

lseek+read =pread

#include <stdio.h>

#include <fcntl.h>

#include <stdlib.h>

main()

{

int fd;

float score;

int r;

int i=0;

fd=open("stu.dat",O_RDWR);

if(fd==-1) printf("open error:%m\n"),exit(-1);

//定位

/*

for(i=0;i<2;i++)

{

r=lseek(fd,i*28,SEEK_SET);

r=lseek(fd,24,SEEK_CUR);

//r=lseek(fd,i*28+24,SEEK_SET);

//读取

r=read(fd,&score,sizeof(float));

//打印输出

printf("%.2f\n",score);

}*/

/*

r=lseek(fd,-100,SEEK_SET);

printf("%d\n",r);

//write(fd,"Hello",5);

*/

for(i=0;i<2;i++)

{

pread(fd,&score,sizeof(float),i*28+24);

printf("%.2f\n",score);

read(fd,&score,sizeof(float));

printf("%.2f\n",score);

}

close(fd);

}

2.4.案例:

读取一个特殊的文件:

/proc/${pid}/mem文件程序的虚拟内存文件

#include <stdio.h>

#include <stdlib.h>

#include <fcntl.h>

int a=9999;

main()

{

char filename[100];

int fd;

int data=8888;

//得到文件名

sprintf(filename,"/proc/%d/mem",getpid());

//打开文件

fd=open(filename,O_RDWR);

if(fd==-1) printf("open error:%m\n"),exit(-1);

//读取a地址这个位置的数据

//pread(fd,&data,4,(int)&a);

//lseek(fd,(int)&a,SEEK_SET);

//read(fd,&data,4);

//write(fd,&data,4);

pwrite(fd,&data,4,(int)&a);

printf("%d\n",a);

close(fd);

}

3.文件的其他操作

fstat获取文件状态

ftruncate改变文件大小

#include <fcntl.h>

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <sys/stat.h>

main()

{

int fd;

struct stat st;

fd=open("stu.dat",O_RDONLY);

if(fd==-1) printf("err:%m\n"),exit(-1);

fstat(fd,&st);

printf("%d,%o\n",st.st_size,st.st_mode);

close(fd);

}

4.文件映射:

虚拟地址映射到内存。

虚拟地址可以映射到文件:可以用内存方式访问文件.

mmap/munmap

案例:

1.使用内存方式写入数据

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/stat.h>

#include <string.h>

#include <sys/mman.h>

struct stu

{

char name[20];

int age;

float score;

};

main()

{

int fd;

struct stu *s;//文件在虚拟内存的映射首地址

struct stat st;

int size;//文件大小

int count;//记录条数

int i;

//1.打开文件

fd=open("newstu.dat",O_RDWR|O_CREAT|O_EXCL,0666);

if(fd==-1)

{

fd=open("newstu.dat",O_RDWR);

if(fd==-1) printf("::%m\n"),exit(-1);

}

//2.得到文件大小,文件记录条数

fstat(fd,&st);

size=st.st_size;

count=size/sizeof(struct stu);

//3.文件大小改变只要在munmap之前调用都有效

//ftruncate(fd,size+sizeof(struct stu));

//4.映射到一个虚拟的地址

s=mmap(0,size+sizeof(struct stu),

PROT_READ|PROT_WRITE,

MAP_SHARED,fd,0);

//5.把数据写入虚拟地址

/*

printf("输入姓名:");

scanf("%s",s[count].name);

printf("输入年龄:");

scanf("%d",&(s[count].age));

printf("输入成绩:");

scanf("%f",&(s[count].score));

ftruncate(fd,size+sizeof(struct stu));

*/

for(i=0;i<count;i++)

{

printf("%s,\t,%d,\t%.2f\n",

s[i].name,s[i].age,s[i].score);

}

//6.卸载虚拟地址

munmap(s,sizeof(struct stu)+size);

//7.关闭文件

close(fd);

}

作业:

-+

2.使用内存方式读取数据

二.文件描述符号的操作(IO锁)

文件描述符号是整数.文件描述符号对应内核的上下文环境.

1.dup dup2拷贝文件描述符号

dup拷贝文件符号,返回系统指定的整数

dup2拷贝文件描述符号,返回用户指定的整数

2.fcntl对文件描述的属性的修改

2.1.拷贝文件描述符号

2.2.修改判定文件的描述标记

2.3.修改判定文件的状态标记

O_RDONLY O_WRONLY_ORDWR O_CREAT O_EXCL

O_APPEND O_ASYN

2.4.设置强制锁(重新编译内核)

2.5.设置建议锁(默认)

2.6.设置的信号

三.IO与Curses(介绍)

Curses:CUI

UI:User Interface.

CUI:字符界面

GUI:图形界面

使用一套封装库 libcurses.so

/usr/lib目录下

编译只需要指定-lcurses

老版本:libcurses.so

新的版本:libncurses.so

如果头文件curses.h不存在,请尝试使用ncurses.h

如果库curses不存在,尝试使用ncurses

printf /scanf标准IO

大部分标准IO重定向到终端./dev/tty /dev/pts/1

curses就是终端输出.

-lcurses -ncurses

为了防止printf重定向到终端破坏UI,禁止在curses中使用标准IO.

1.编程模型

初始化终端initscr

操作终端(输入/输出/定位/刷新....)

释放终端endwin

2.显示

2.1.图形输出

border

box

hline

vline

#include <curses.h>

int main()

{

initscr();//初始化终端

//border(0,0,0,0,0,0,0,0);

box(stdscr,0,0);

mvhline(2,10,'=',20);

mvvline(2,10,'|',10);

refresh();

//wrefrsh(stdscr);

getch();//等待一个字符输入

endwin();//释放终端

return 0;

}

属性字符:字节=属性字节+字符字节

注意:

box需要窗体.

initscr返回被初始化的窗体:标准屏幕WINDOW*

实际上curses定义一个全局变量stdscr就是标准屏幕

函数命名规则:

**** 标准屏幕stdscr

w**** 指定窗体

mv**** 指定位置

mvw**** 指定窗体的指定位置

2.2.刷屏

void refresh()

void wrefresh(WINDOW*);

从里到外刷屏

2.3.字符输出

addch

普通字符:''

属性字符: ''|属性

特殊的属性字符:比如ACS_PI

2.4.字符串输出

int addstr(const char *);

2.5.格式字符串输出

int printw(const char*,....);

#include <curses.h>

main()

{

char name[9]={0};

int r;

initscr();

//绘制UI

mvaddstr(4,10,"用户:[ ]");

//输入

r=mvgetnstr(4,16,name,8);

//name[r]=0;

//打印输入

mvprintw(7,10,"你输入的是:%s",name);

refresh();

//输入字符

getch();

endwin();

}

3.字符属性与颜色

颜色属性

3.1.判定终端是否支持颜色

bool has_colors();//都支持颜色,建议不判定

3.2.初始化颜色:

int start_color();

3.3.定义颜色对

int init_pair(short pair,short fore,shortback);

3.4.使用颜色对

COLOR_PAIR(shortpair)

3.5.设置属性

attron()开启属性

attroff()关闭属性

这组函数一定要在initscr后调用

背景函数:

bkgd();

#include <curses.h>

int main()

{

initscr();

if(has_colors()==TRUE)

{

start_color();

init_pair(1,COLOR_RED,COLOR_WHITE);

init_pair(2,COLOR_BLUE,COLOR_GREEN);

init_pair(3,COLOR_BLACK,COLOR_WHITE);

bkgd(COLOR_PAIR(3));

}

box(stdscr,0,0);

mvaddch(2,10,ACS_PI|COLOR_PAIR(1));

mvaddch(2,11,ACS_PI|COLOR_PAIR(2));

attron(COLOR_PAIR(1));

mvaddstr(5,10,"Hello 靓崽!");

attroff(COLOR_PAIR(1));

attron(COLOR_PAIR(2)|A_UNDERLINE);

mvaddstr(7,10,"Hello Fellow!");

attroff(COLOR_PAIR(2)|A_UNDERLINE);

mvprintw(9,10,"行:%d,列:%d",LINES,COLS);

getch();

endwin();

}

案例:

1.时间显示屏幕

1.初始化

2.循环显示时间,并且睡眠1秒

3.释放

#include <curses.h>

#include <time.h>

#include <unistd.h>

void init();

void drawui();

void business();

void destroy();

main()

{

init();

drawui();

business();

destroy();

}

void business()

{

time_t tt;

struct tm *t;

while(1)

{

//取时间

tt=time(0);

t=localtime(&tt);

//显示时间

mvprintw(LINES/2,(COLS-8)/2,

"%02d:%02d:%02d",

t->tm_hour,t->tm_min,t->tm_sec);

//刷新屏幕

refresh();

sleep(1);

}

}

void drawui()

{

box(stdscr,0,0);

}

void destroy()

{

endwin();

}

void init()

{

initscr();

}

2.登录界面

1.初始化

2.绘制界面



绘制用户名输入区

绘制密码输入区

3.等待输入

4.结束

View Code

4.输入

1.字符输入

int getch();

返回的是字符

禁止回显noecho

使功能键有效,使用keypad(WINDOW*,bool)

#include <curses.h>

main()

{

int ch;

//初始化

initscr();

noecho();

//循环输入

while(1)

{

ch=mvgetch(5,10);

//循环显示输入

mvprintw(8,10,"你输入的是:%c(%d)",ch,ch);

}

//释放

endwin();

}

案例:

使用键盘控制字母在屏幕上的移动

补充:

curses屏幕清除:man 3 clear

clear

erase

光标控制:

得到光标位置 getsyx

设置光标的位置 setsyx

控制光标是否可见:curs_set();

2.字符串输入

int addstr

3.格式数据输入

scanw

#include <curses.h>

main()

{

int ch;

int x=5,y=5;

initscr();

keypad(stdscr,TRUE);

curs_set(0);

noecho();

mvaddch(y,x,'A');

while(1)

{

ch=getch();

//mvaddch(y,x,' ');

//clrtoeol();

erase();

//clear();

switch(ch)

{

case KEY_UP:

y--;

break;

case KEY_DOWN:

y++;

break;

case KEY_LEFT:

x--;

break;

case KEY_RIGHT:

x++;

break;

}

mvaddch(y,x,'A');

refresh();

}

endwin();

}

5.窗口

subwin()//创建子窗体(坐标采用标准屏幕坐标)

derwin()//创建子窗体(坐标采用父窗体坐标)

#include <curses.h>

main()

{

WINDOW *w;

initscr();

box(stdscr,0,0);

w=derwin(stdscr,4,20,5,3);

box(w,0,0);

refresh();

wrefresh(w);

getch();

endwin();

}

#include <curses.h>

void init();

void drawUi();

void dealInput();

void destroy();

main()

{

init();

drawUi();

dealInput();

destroy();

}

void dealInput()

{

int a,b;

while(1)

{

mvaddstr(2,3," ");

mvscanw(2,3,"%d",&a);

mvaddstr(2,11," ");

mvscanw(2,11,"%d",&b);

mvaddstr(2,19," ");

mvprintw(2,19,"%d",a+b);

refresh();

}

}

void drawUi()

{

mvaddstr(2,2,"[ ]+[ ]=[ ]");

refresh();

}

void destroy()

{

endwin();

}

void init()

{

initscr();

}

1.在vi设置编码:

:set encoding=编码 gb2312 ios-8859-1 utf-8

2.在编译器指定源文件的编码 -finput-charset=gb2312

3.在终端指定编码:

4.系统默认编码

/etc/sysconfig/i18n配置编码

作业:(使用文件映射)

1.使用内存方式读取数据

2.使用curses+io完成:图书信息的录入

3.使用curses+io显示图书信息:

每次显示一条:

使用up down键翻滚记录数据

4.读取文件文件,使用curses 显示.

实现如下功能:

上下翻页功能

输入q,结束功能
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: