Linux C编程练习(一)

本文介绍了自制ls命令实现及多种文件操作技巧,包括目录遍历、文件逆序输出及父子进程间的信号传递。

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;
}
目 录 第篇 Linux和C编程基础  第1章 Linux系统概述   1.1 Linux操作系统介绍     1.1.1 Linux的发展历程     1.1.2 Linux的特性     1.1.3 Linux的内核版本和发行版本    1.2 C语言简介     1.2.1 C语言的发展历史     1.2.2 C语言的特点    1.3 Linux的安装、启动与关闭    1.4 Linux的基本使用     1.4.1 Linux终端     1.4.2 Linux Shell     1.4.3 Linux的常用命令    1.5 Linux下程序的开发环境和开发过程    1.6 习题   第2章 C编程基础、Vi和Emacs编辑器    2.1 C程序的结构    2.2 C语言的基本数据类型     2.2.1 整型     2.2.2 浮点型     2.2.3 字符型    2.3 运算符和表达式     2.3.1 算术运算符与算术表达式     2.3.2 赋值运算符与赋值表达式     2.3.3 逗号运算符与逗号表达式    2.4 标准输入输出函数     2.4.1 字符输出函数putchar     2.4.2 字符输入函数getchar     2.4.3 格式化输出函数printf     2.4.4 格式化输入函数scanf    2.5 Vi编辑器的使用     2.5.1 Vi的工作模式     2.5.2 启动Vi     2.5.3 保存文件和退出Vi     2.5.4 光标的移动     2.5.5 文本的删除     2.5.6 文本查找和替换     2.5.7 文本的复制与粘贴    2.6 Emacs编辑器的使用    2.7 命名规范     2.7.1 标识符     2.7.2 关键字     2.7.3 命名规范    2.8 面试题选与实例精讲     2.8.1 面试题选     2.8.2 实例精讲    2.9 习题   第3章 C程序控制结构和gcc编译器    3.1 C程序的控制结构     3.1.1 C程序语句概述     3.1.2 C程序的3种基本控制结构    3.2 分支控制结构     3.2.1 关系运算符与关系表达式     3.2.2 逻辑运算符与逻辑表达式     3.2.3 if语句     3.2.4 switch语句    3.3 循环控制结构     3.3.1 while语句     3.3.2 do...while语句     3.3.3 for语句     3.3.4 break语句和continue语句    3.4 gcc编译器     3.4.1 程序的编译过程     3.4.2 gcc的常用选项     3.4.3 gcc的报错类型及对策    3.5 面试题选与实例精讲     3.5.1 面试题选     3.5.2 实例精讲    3.6 习题   第4章 C函数、数组、指针和调试器gdb   第5章 C语言预处理、结构体和make的使用  第二篇 Linux系统编程  第6章 文件操作   第7章 进程控制   第8章 线程控制   第9章 信号及信号处理   第10章 进程间通信  第三篇 Linux网络和图形界面编程  第11章 网络编程   第12章 GTK+图形界面编程  第四篇 Linux项目实践  第13章 项目实践:BT下载软件的开发
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值