Linux C编程练习(一)

1、定制自己的ls命令

#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <pwd.h>
#include <grp.h>
#include <time.h>
void do_ls(char*dir_entry);
void do_ls_filename(char*dir_entry);
void do_stat( char* filename );
void show_list( char* filename, struct stat* statinfo );
void mode_to_letters( mode_t filemode, char str[] );
void show_time( time_t filetime );
char* format_time( char* dsttime, const char* srctime );

//用户id转名称
char* uid_to_name( uid_t uid );
//组id转名称
char* gid_to_name( gid_t gid );

int flag;
int main(int argc,char*argv[])
{
    char*dir=".";
    if(argc>2)
    {
        dir=argv[3];  
    }
    //printf("%s\n",dir );
    //printf("%c\n",argv[2][1] );
    switch(argv[2][1]){
        case 'l':flag=0;do_ls(argv[3]);break;
        case 'A':flag=1;do_ls(argv[3]);break;
        case 'n':flag=2;do_ls(argv[3]);break;
        case 'a':flag=3;do_ls(argv[3]);break;
        case 'm':flag=4;do_ls(argv[3]);break;
    }
}

void do_ls(char* dir_entry) {
    DIR* pDir;
    struct dirent* pCurDir;
    if( ( pDir = opendir( dir_entry ) ) == NULL ){
        perror( "read dir" );
        exit( -1 );
    }
    else {
        while( ( pCurDir = readdir( pDir ) ) != NULL ) {
            //printf("%s\n",pCurDir->d_name );
            do_stat( pCurDir->d_name );
        }
        closedir( pDir );
    }
}

//得到文件信息
void do_stat( char* filename ){
    struct stat statinfo;
    if ( stat( filename, &statinfo ) == -1 ) {
        printf( "打开%s失败\n", filename );
        exit( -1 );
    }else {

        show_list( filename, &statinfo );
    }
}

//显示文件列表
void show_list( char* filename, struct stat* statinfo ) {
    mode_t st_mode = statinfo->st_mode;

    char str[10];
    mode_to_letters( st_mode, str );
    switch(flag){
        case 0:{
            printf( "%s\t", str );                         //文件权限和文件类型信息
            printf( "%ld\t", statinfo->st_nlink ); //该文件上硬链接个数 
            printf( "%s\t\t", uid_to_name( statinfo->st_uid ) ); //UID号转用户名
            printf( "%s\t", gid_to_name( statinfo->st_gid ) ); //GID号转组名
            printf( "%10ld", statinfo->st_size ); //文件大小
            show_time( statinfo->st_mtime ); //最后一次修改时间
            printf( "\t%s", filename );

            printf( "\n" );
                };break;
        case 1:{
            printf("%s ",filename );   
        };break;
        case 2:{
            printf( "%s\t", str );                         //文件权限和文件类型信息
            printf( "%ld\t", statinfo->st_nlink ); //该文件上硬链接个数 
            printf( "%d\t\t", statinfo->st_uid  ); //UID号
            printf( "%d\t", statinfo->st_gid  ); //GID号
            printf( "%10ld", statinfo->st_size ); //文件大小
            show_time( statinfo->st_mtime ); //最后一次修改时间
            printf( "\t%s", filename );
            printf( "\n" );
        };break;
        case 3:
            printf("%s ", filename);break;
        case 4:
            printf("%s,",filename);break;
    }
    printf("\n");
}

char* uid_to_name( uid_t uid ){
    return getpwuid( uid )->pw_name;
}

char* gid_to_name( gid_t gid ){
    return getgrgid( gid )->gr_name;
}

void mode_to_letters( mode_t filemode, char str[] ) {

    strcpy( str, "----------" );
    if( S_ISREG( filemode ) ) str[0] = '-';
    if( S_ISDIR( filemode ) ) str[0] = 'd';
    if( S_ISLNK( filemode ) ) str[0] = 'l';

    //用户权限位
    if( filemode & S_IRUSR ) str[1] = 'r';
    if( filemode & S_IWUSR ) str[2] = 'w';
    if( filemode & S_IXUSR ) str[3] = 'x';

    //组权限位
    if( filemode & S_IRGRP ) str[4] = 'r';
    if( filemode & S_IWGRP ) str[5] = 'w';
    if( filemode & S_IXGRP ) str[6] = 'x';

    //其他组权限位
    if( filemode & S_IROTH ) str[7] = 'r';
    if( filemode & S_IWOTH ) str[8] = 'w';
    if( filemode & S_IXOTH ) str[9] = 'x';
}

void show_time( time_t filetime ) {
    struct tm* ptm;
    ptm = localtime( &filetime );

    int month = ptm->tm_mon + 1;
    int day = ptm->tm_mday;
    int hour = ptm->tm_hour;
    int min = ptm->tm_min;

    char srchour[3] = "0";
    char srcmin[3] = "0";
    char dsthour[3] = "0";
    char dstmin[3] = "0";
    sprintf( srchour, "%d", hour );
    sprintf( srcmin, "%d", min );
    format_time( dsthour, srchour );
    format_time( dstmin, srcmin );

    printf( "%4d月%4d%4s:%2s", month, day, dsthour, dstmin );
}

char* format_time( char* dsttime, const char* srctime ) {
    if( strlen( srctime ) < 2 ) {
        return strcat( dsttime, srctime );
    }
    return strcpy( dsttime, srctime );
}

运行结果:

2、遍历当前目录,输出目录和文件详细信息

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <stdlib.h>
#define MAX 102
void printdir(char*dir,int depth)
{
    DIR *dp;
    struct dirent *entry;
    struct stat statbuf;

    if((dp=opendir(dir))==NULL)
    {

        //fprintf(stderr,"can't not open directory:%s\n",dir);
        return;
    }

    chdir(dir);
    while((entry=readdir(dp)) != NULL)
    {
        lstat(entry->d_name,&statbuf);
        if(S_ISDIR(statbuf.st_mode))
        {
            if(strcmp(".",entry->d_name)==0||strcmp("..",entry->d_name)==0)
                continue;
            printf("%*s%s/\n",depth,"",entry->d_name);
            printdir(entry->d_name,depth+4);
        }
        else 
            printf("%*s%s\n",depth,"",entry->d_name);
    }
    closedir(dp);
}


int main()
{
    char buffer[MAX];
    char *p=getcwd(buffer,MAX);
    printf("The current directory:%s\n",buffer);
    printdir(buffer,0);
    return 0;
}

3、对文本文件的内容进行逆序输出,要求按行,按词,同时按行和词逆序三种输出方式。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 1024
struct node{
    char *line;
    struct node *next;
};


char* getWord(char word[]);
void read_line();
void read_word();
void read_mixture();


FILE *in, *out;
char buf[MAXSIZE];
int cnt;

int main(){
    char op;
    printf("请选择文件输出形式:\n");
    printf("1、按行逆序\n");
    printf("2、按词逆序\n");
    printf("3、混合逆序\n");
    printf("请输入你的选择(按q退出):");
    while(scanf("%c",&op)&&op!='q')
    {
        switch(op){
        case '1':read_line();break;
        case '2':read_word();break;
        case '3':read_mixture();break;
        }
    }
    return 0;
}


void read_line()
{
    printf("\n");
    struct node *head = (struct node*)malloc(sizeof(struct node));

    if(NULL == (in = fopen("test.txt", "r"))){
        printf("Error while open the file\n");
        //return -1;
    }

    head->next = NULL;
    while(NULL != fgets(buf, MAXSIZE, in)){
        struct node *pnode = (struct node*)malloc(sizeof(struct node));
        pnode->line = (char*)malloc(strlen(buf));
        pnode->next = NULL;

        sprintf(pnode->line, "%s", buf);
        if(NULL != head->next){
            pnode->next = head->next;
            head->next = pnode;
        }
        else{
            head->next = pnode;
        }
    }

    while(NULL != head->next){
        struct node *pnode = head->next;
        fputs(pnode->line, stdout);
        head->next = pnode->next;
        free(pnode->line);
        free(pnode);
    }
    free(head);
}

void read_word()
{
    struct node *head = (struct node*)malloc(sizeof(struct node));
    if(NULL == (in = fopen("test.txt", "r"))){
        printf("Error while open the file\n");
        //return -1;
    }

    head->next = NULL;
    while(NULL != fgets(buf, MAXSIZE, in)){
        struct node *pnode = (struct node*)malloc(sizeof(struct node));
        pnode->line = (char*)malloc(strlen(buf));
        pnode->next = NULL;

        sprintf(pnode->line, "%s", buf);
    for(int i=strlen(pnode->line);i>=0;i--)
    {
        printf("%c",(pnode->line)[i]);
    }
        if(NULL != head->next){
            pnode->next = head->next;
            head->next = pnode;
        }
        else{
            head->next = pnode;
        }
    }
    fclose(in);
    printf("\n");
}

void read_mixture()
{
    struct node *head = (struct node*)malloc(sizeof(struct node));

    if(NULL == (in = fopen("test.txt", "r"))){
        printf("Error while open the file\n");
        //return -1;
    }

    head->next = NULL;
    while(NULL != fgets(buf, MAXSIZE, in)){
        struct node *pnode = (struct node*)malloc(sizeof(struct node));
        pnode->line = (char*)malloc(strlen(buf));
        pnode->next = NULL;

        sprintf(pnode->line, "%s", buf);
        if(NULL != head->next){
            pnode->next = head->next;
            head->next = pnode;
        }
        else{
            head->next = pnode;
        }
    }

    while(NULL != head->next){
        struct node *pnode = head->next;
        head->next = pnode->next;
    for(int i=strlen(pnode->line);i>=0;i--)
    {
        printf("%c",(pnode->line)[i]);
    }
        free(pnode->line);
        free(pnode);
    }
    free(head);
    printf("\n");
}

4、创建两个进程。父进程负责创建一个新的文本文件,并向文本文件中写入数据,当数据写入完成后,发送信号给子进程,子进程独处文件内容并显示。

#include<sys/types.h>
#include<unistd.h>
#include<stdio.h>
#include<fcntl.h>//perror()的头文件
#include<stdlib.h>
#include<string.h>
#include<signal.h>
#define MAXSIZE 1024
char buf[MAXSIZE];

int main(){
    //int fd=open("hello.txt",O_WRONLY);
    FILE *fp;
    int pid;
    char *hello="hello ";
    char *filename="hello.txt";
    if((fp=fopen(filename,"w+"))==NULL){
        perror("fopen");
        return -1;
    }
    if(fwrite(hello,strlen(hello),1,fp)<1)//fwrite返回成功写入文件的块数
            printf("fwrite hello error!\n");
    //printf("这是父进程\n");
    fclose(fp);
    pid=fork();
    if(pid==-1){//创建进程,失败返回-1
        perror("fork error");
        return -1;
    }
    if(pid==0){//子进程
        kill(getppid(),SIGALRM);
        fp=fopen("hello.txt","r");
        //printf("这是子进程\n");
        while(NULL != fgets(buf, MAXSIZE, fp)){
            fprintf(stdout,"%s\n",buf);
        }

    }
    //fclose(fp);
    return 0;
}
网上很多地方可以找到本书的下载,我唯一能够额外贡献的是,提供多格式的打包下载,包括:PDF格式,离线网页格式,在线网页格式。 如果您觉得下载比较麻烦,那么建议您直接使用在线教程,网址是:http://learn.akae.cn/media/index.html 如果您只需要一个可以打印的PDF格式文件,那么建议你下载Defonds的资源,因为我的PDF格式文件就是从他那下的,资源链接是:http://download.csdn.net/detail/defonds/2855361 如果您和我一样,希望在多种环境下都可以方便地使用本书,那么欢迎您下载我提供的这个打包资源! 对本书的描述 版权 © 2008, 2009 宋劲杉, 北京亚嵌教育研究中心 这本书最初是为北京亚嵌教育研究中心的嵌入式Linux系统工程师就业班课程量身定做的教材之一,作者宋劲松。 这是一本从零基础开始学习编程的书,不要求读者有任何编程经验,但读者应勤于思考。本书尽最大努力理清概念之间的依赖关系,力求一站式学习,读者不需要为了找一个概念的定义去翻其它书,也不需要为了搞清楚一个概念在本书中前后一通乱翻,只需从前到后按顺序学习即可。但一站式学习并不等于傻瓜式学习,有些章节有一定的难度,需要积极思考才能领会。本书可以替你节省时间,但不能替你思考,不要指望像看小说一样走马观花看一遍就能学会。 本书不是孤立地讲C语言,而是和编译原理、操作系统、计算机体系结构结合起来讲。或者说,本书的内容只是以C语言为载体,真正讲的是计算机的原理和程序的原理。 强调基本概念和基本原理,在编排顺序上非常重视概念之间的依赖关系,每次引入一个新的概念,只依赖于前面章节已经讲过的概念,而绝不会依赖后面章节要讲的概念。有些地方为了叙述得完整,也会引用后面要讲的内容,比如说“有关XX我们到XX章再仔细讲解”,凡是这种引用都不是必要的依赖,可以当它不存在,只管继续往下看就行了。 这本书定位在入门级,虽然内容很多,但不是一本百科全书,除了C语言基本要讲透之外其它内容都不深入,书中列出了很多参考资料,是读者进一步学习的起点。K&R的第一章是一个Whirlwind Tour,把全书的内容简单过了一遍,然后再逐个深入进去讲解。本书也可以看作是计算机专业课程体系的一个Whirlwind Tour,学习完本书之后有了一个全局观,再去学习那些参考资料就应该很容易上手了。 本书的主要内容包括三大部分: C语言入门。介绍基本的C语法,帮助没有任何编程经验的读者理解什么是程序,怎么写程序,培养程序员的思维习惯,找到编程的感觉。前半部分改编自《How To Think Like A Computer Scientist: Learning with C++》(Allen B. Downey.) C语言本质。结合计算机和操作系统的原理讲解C程序是怎么编译、链接、运行的,同时全面介绍C的语法。位运算的章节改编自亚嵌教育林小竹老师的讲义,链表和二叉树的章节改编自亚嵌教育朱老师的讲义。汇编语言的章节改编自《Programming from the Ground Up: An Introduction to Programming using Linux Assembly Language》(Jonathan Bartlett.)在该书的最后一章提到,学习编程有两种Approach,一种是Bottom Up,一种是Top Down,各有优缺点,需要两者结合起来。所以作者编这本书的思路是,第一部分Top Down,第二部分Bottom Up,第三部分可以算填了中间的空隙,三部分全都围绕C语言展开。 Linux系统编程。介绍各种Linux系统函数和内核的工作原理。Socket编程的章节改编自亚嵌教育卫剑钒老师的讲义。 为什么要在Linux平台上学C语言?用Windows学C语言不好吗? 用Windows还真的是学不好C语言。C语言是一种面向底层的编程语言,要写好C程序,必须对操作系统的工作原理非常清楚,因为操作系统也是用C写的,我们用C写应用程序直接使用操作系统提供的接口。既然你选择了看这本书,你一定了解:Linux是一种开源的操作系统,你有任何疑问都可以从源代码和文档中找到答案,即使你看不懂源代码,也找不到文档,也很容易找个高手教你,各种邮件列表、新闻组和论坛上从来都不缺乐于助人的高手;而Windows是一种封闭的操作系统,除了微软的员工别人都看不到它的源代码,只能通过文档去猜测它的工作原理,更糟糕的是,微软向来喜欢藏着揶着,好用的功能留着自己用,而不会写到文档里公开。本书的第一部分在Linux或Windows平台上学习都可以,但第二部分和第三部分介绍了很多Linux操作系统的原理以帮助读者更深入地理解C语言,只能在Linux平台上学习。 Windows平台上的开发工具往往和各种集成开发环境(IDE,Integrated Development Environment)绑在一起,例如Visual Studio、Eclipse等。使用IDE确实很便捷,但IDE对于初学者绝对不是好东西。微软喜欢宣扬傻瓜式编程的理念,告诉你用鼠标拖几个控件,然后点一个按钮就可以编译出程序来,但是真正有用的程序有哪个是这么拖出来的?很多从Windows平台入门学编程的人,编了好几年程序,还是只知道编完程序点一个按钮就可以跑了,把几个源文件拖到一个项目里就可以编译到一起了,如果有更复杂的需求他们就傻眼了,因为他们脑子里只有按钮、菜单的概念,根本没有编译器、链接器、Makefile的概念,甚至连命令行都没用过,然而这些都是初学编程就应该建立起来的基本概念。另一方面,编译器、链接器和C语言的语法有密切的关系,不了解编译器、链接器的工作原理,也不可能真正掌握C的语法。所以,IDE并没有帮助你学习,而是阻碍了你学习,本来要学好C编程只要把语法和编译命令学会就行了,现在有了IDE,除了学会语法和编译命令,你还得弄清楚编译命令和IDE是怎么集成的,这才算学明白了,本来就很复杂的学习任务被IDE搞得更加复杂了。Linux用户的使用习惯从来都是以敲命令为主,以鼠标操作为辅,从学编程的第一天起就要敲命令编译程序,等到你把这些基本概念都搞清楚了,你觉得哪个IDE好用你再去用,不过到那时候你可能会更喜欢vi或emacs而不是IDE了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值