C语言基础深入之常用常错函数新读

初入职场,才发现自己的C基础是多么的欠缺。晚上加班没事,作为程序员提升自身技术的一部分,走读公司代码,才发现简单的一个功能要是让自己来实现的话,却也是漏洞百出。

先说说原有代码的功能,根据MAC地址来更新维护的ARP表。

原理很简单:读取文件“proc/net/arp”,然后对文件内容进行解析,后续进行相应的操作。这里只是根据自己的回忆对模糊的知识点进行总结。

新手们可以拿来学习学习,大牛们看看亦可,加深印象,欢迎提意见,喷子就不用来了。

1)打开文件proc/net/arp,获取ARP信息。具体如下图:
这里写图片描述
这里比较简单,需要注意的就是文件操作完毕后记得fclose()释放相关资源。
2)getline()按行读取文件内容
gcc扩展定义的函数。

它会生成一个包含一串从输入流读入的字符的字符串,直到以下情况发生会导致生成的此字符串结束。1)到文件结束,2)遇到函数的定界符,3)输入达到最大限度。

函数定义如下:

ssize_t getline(char **lineptr, size_t *n, FILE *stream);

需要注意的是参数指向存放该行字符的指针,如果是NULL,则有系统帮助malloc,请在使用完成后free释放
3)strtok()使用
字符串分割函数,不可重入,函数原型如下:

char* strtok (char* str,constchar* delimiters );

函数返回值:
当s中的字符查找到末尾时,返回NULL;
如果查不到delimiter所标示的字符,则返回当前strtok的字符串的指针。
请注意,并不是不存在要查找的分隔符时才返回NULL
4)strtol()函数的使用
完成不同进制之间的转换。
5)ssanf()的使用
其作用是按照固定格式读取字符串。常见的用法相信大家都比较熟悉了,这里简单复习一下。常见的用法如下:

char buf[512] = {0};
sscanf("123456 ", "%s", buf);//123456

自己很少用的是有关sscanf中相关正则匹配。sscanf()函数原型如下:
int sscanf( string str, string fmt, mixed var1, mixed var2 ... );
其中,format可以是一个或多个 {%[*] [width] [{h | l | I64 | L}]type | ’ ’ | ‘/t’ | ‘/n’ | 非%符号}。

  1、 * 亦可用于格式中, (即 %d 和 %*s) 加了星号 () 表示跳过此数据不读入. (也就是不把此数据读入参数中)
  2、{a|b|c}表示a,b,c中选一,[d],表示可以有d也可以没有d。
  3、width表示读取宽度。
  4、{h | l | I64 | L}:参数的size,通常h表示单字节size,I表示2字节 size,L表示4字节size(double例外),l64表示8字节size。
  5、type :这就很多了,就是%s,%d之类。
  6、特别的:%*[width] [{h | l | I64 | L}]type 表示满足该条件的被过滤掉,不会向目标参数中写入值
  支持集合操作:
  %[a-z] 表示匹配a到z中任意字符,贪婪性(尽可能多的匹配)
  %[aB’] 匹配a、B、’中一员,贪婪性
  %[^a] 匹配非a的任意字符,贪婪性

例如本程序中

sscanf(szLine, "%s%*s%*s%s", szIPAddr, szHWAddr);

将szLine中的第二个,第三个字符串过滤掉。
完整代码如下:

#include <stdio.h>
#include <vector>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#define ARP_FILE_PATH "/proc/net/arp"

int main()
{
    FILE *pFile = NULL;
    char *szLine = NULL;
    char szIPAddr[64] = { 0 };
    char szHWAddr[128] = { 0 };
    char *pMacAddr = NULL;
    int nLineLen = 0;
    std::vector<int> vecMacAddr;

    pFile = fopen(ARP_FILE_PATH, "r");
    if (NULL == pFile)
    {
        printf("open file error, %s\n", strerror(errno));
        return -1;
    }
    while ( -1 != getline(&szLine, (size_t *)&nLineLen, pFile))
    {
        sscanf(szLine, "%s%*s%*s%s", szIPAddr, szHWAddr);
        printf("%s\n", szLine);
        printf("szIPAddr = %s, szHWAddr = %s\n", szIPAddr, szHWAddr);
        if (NULL != szLine)
        {
            free(szLine);
            szLine = NULL;
        }
        nLineLen = 0;
        if (NULL == strstr(szHWAddr, ":"))
        {
            continue;
        }
        pMacAddr = strtok(szHWAddr, ":");
        while (NULL != pMacAddr)
        {
            vecMacAddr.push_back(strtol(pMacAddr, NULL,16));        
            pMacAddr = strtok(NULL, ":");
        }
    }
    fclose(pFile);
    printf("MAC Addr:\n");
    for (int i = 0;i < vecMacAddr.size();i++)
    {
        printf("%d\n",vecMacAddr.at(i));
    }
    return 1;
}

函数运行结果如下:
这里写图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值