zoukankan      html  css  js  c++  java
  • Linux网络编程综合运用之MiniFtp实现(五)

    转眼兴奋的五一小长假就要到来了,在放假前夕还是需要保持一颗淡定的心,上次中已经对miniFTP有基础框架进行了搭建,这次继续进行往上加代码,这次主要还是将经历投射到handle_child()服务进程上来,其它的先不用关心:

    而它主要是完成FTP协议相关的功能,所以它的实现放在了ftpproto.c,目前连接成功之后效果是:

    其中"USER webor2006"后面是包含" "的,FTP的协议规定每条指令后面都要包含它,这时handle_child()函数就会收到这个命令并处理,再进行客户端的一些应答,客户端才能够进行下一步的动作,由于目前还没有处理该命令,所以客户端阻塞了,接下来读取该指令来打印一下:

    编译运行:

    接下来命令中的 ,接下来的操作会涉及到一些字符串的处理,所以先来对其进行封装一下,具体字符串的处理函数如下:

    这里创建一个新的字符串模块,来将上面相关的函数都放一起:

    str.h:

    #ifndef _STR_H_
    #define _STR_H_
    
    void str_trim_crlf(char *str);
    void str_split(const char *str , char *left, char *right, char c);
    int str_all_space(const char *str);
    void str_upper(char *str);
    long long str_to_longlong(const char *str);
    unsigned int str_octal_to_uint(const char *str);
    
    
    #endif /* _STR_H_ */

    str.c:

    #include "str.h"
    #include "common.h"
    
    void str_trim_crlf(char *str)
    {
    
    }
    
    void str_split(const char *str , char *left, char *right, char c)
    {
    
    }
    
    int str_all_space(const char *str)
    {
        return 1;
    }
    
    void str_upper(char *str)
    {
    }
    
    long long str_to_longlong(const char *str)
    {
        return 0;
    }
    
    unsigned int str_octal_to_uint(const char *str)
    {
        unsigned int result = 0;
        return 0;
    }

    接下来一个个函数实现:

    ①:去除字符串 :rhstr_trim_crlf()

    实现思路:

    void str_trim_crlf(char *str)
    {
        char *p = &str[strlen(str)-1];
        while (*p == '
    ' || *p == '
    ')
            *p-- = '';
    }

    接下来来测试一下该函数是否管用:

    这时得在Makefile中增加字符串模块了:

    编译运行:

    ②:解析FTP命令与参数:str_split()

    接下来将命令进行分割:

    下面则实现该函数:

    void str_split(const char *str , char *left, char *right, char c)
    {
        //首先查找要分割字符串中首次出现字符的位置
        char *p = strchr(str, c);
        if (p == NULL)
            strcpy(left, str);//表示没有找到,该命令没有参数,则将一整串拷贝到left中
        else
        {//表示找到了,该命令有参数
            strncpy(left, str, p-str);
            strcpy(right, p+1);
        }
    }

    【说明】:上面用到了几个跟字符串相关的处理函数,需要熟悉一下:strchr、strncpy、strcpy。

    下面编译运行一下:

    包含头文件:

    再次编译运行:

    ③:判断所有的字符是否为空白字符:str_all_space()

    编写一下测试代码:

    编译运行:

    查看man帮助将其加上:

    再次编译运行:

    ④:将字符串转换成大写:str_upper()

    编写测试函数:

    编译运行:

    加入头文件:

    再次编译运行:

    发生这种错误不用怕, 交给gdb:

    其实这个错误是一个很好检验C语言基本功的,修改程序如下:

    再次编译运行:

    ⑤:将字符串转换为长长整型:str_to_longlong()

     可能会想到atoi系统函数可以实现,但是它返回的是一个整型:

    但是也有一个现成的函数可以做到:atoll:

    所以可以先用它来实现:

    long long str_to_longlong(const char *str)
    {
        return atoll(str);
    }

    编写测试代码并运行:

    但是不是所有的系统都支持它,因此这里我们自己来实现,其实现思路也比较简单,规则如下:

    12345678=8*(10^0) + 7*(10^1) + 6*(10^2) + ..... + 1*(10^7)

    所以实现如下:

    long long str_to_longlong(const char *str)
    {
        long long result = 0;
        long long mult = 1;//这个表示乘法系数
        unsigned int len = strlen(str);
        unsigned int i;
    
        if (len > 15)//对长度进限制,因为long long也是有大小限制的
            return 0;
    
    
        for (i=0; i<len; i++)
        {
            char ch = str[len-(i+1)];
            long long val;
            if (ch < '0' || ch > '9')//如果里面是非数字字符,则直接返回0
                return 0;
    
            val = ch - '0';
            val *= mult;
            result += val;
            mult *= 10;//系数乘以10
        }
        return result;
        //return atoll(str);
    }

    下面编译运行:

    其中计算方式是从后往前的,所以可以将for循环进行修改一下变得更加简单一些:

     再次编译运行:

    这里面是个坑,跟无符号整形有关,也就是这句话:

    这里来打印一下i的变化就明白了:

    输出如下:

    其原因是:

    所以要解决此问题,很简单,直接将无符号给去掉既可:

    再编译运行:

    ⑥:将八进制的整形字符串转换成无符号整型str_octal_to_uint()

    其实现原理跟上面的差不多:

    123456745=5*(8^0) + 4*(8^1) + 7*(8^2) + .... + 1*(8^8)

    代码编写也跟上面函数一样,这里采用另外一种方式来实现,从高位算起:

    先拿10进制来进行说明,好理解:

    123456745可以经过下面这个换算得到:

    0*10+1=1

    1*10+2=12

    12*10+3=123

    123*10+4=1234

    ....

    所以换算成八进制,其原理就是这样:

    0*8+1=1

    1*8+2=12

    12*8+3=123

    123*8+4=1234

    ....

    所以依照这个原理就可以进行实现了,由于八进制可能前面为0,如:0123450,所以需要把第一位0给过滤掉,如下:

    而公式里面应该是result*8+digit来进行计算,这里用位操作来改写,也就是result*8=result <<= 3,移位操作效率更加高效,所以最终代码如下:

    下面则编写测试代码,来看下是否有效:

    编译运行:

    下面我们手动来验证下结果是否等于457:

    711计算如下:

    ①、7*8+1=57

    ②、57*8+1=456+1=457

    所以结果是正常的。

    以上就是关于字符串需要用到的工具模块,最后回到主程序来:

    好了,下节继续完善~~

  • 相关阅读:
    Parameter Binding in ASP.NET Web API
    Which HTTP methods match up to which CRUD methods?
    ErrorHandling in asp.net web api
    HttpStatusCode
    Autofac Getting Started(默认的构造函数注入)
    Autofac Controlling Scope and Lifetime
    luvit 被忽视的lua 高性能框架(仿nodejs)
    undefined与null的区别
    VsCode中使用Emmet神器快速编写HTML代码
    字符串匹配---KMP算法
  • 原文地址:https://www.cnblogs.com/webor2006/p/4458899.html
Copyright © 2011-2022 走看看