昨夜西风凋碧树,独上高楼,望尽天涯路。——五代·晏殊·蝶恋花
最近学习了APUE的一系列函数,要求用ifconfig命令来获取本机的网卡ip,下面根据学长的博客复述一段代码来获取ip字段:
/*********************************************************************************
* Copyright: (C) 2017 tangyanjun<519656780@qq.com>
* All rights reserved.
*
* Filename: apue.c
* Description: This file
*
* Version: 1.0.0(05/11/17)
* Author: tangyanjun <519656780@qq.com>
* ChangeLog: 1, Release initial version on "05/11/17 20:02:56"
*
********************************************************************************/
#include <stdio.h>
#define sizeofbuf 512
int main(int argc, char **argv)
{
char buf[sizeofbuf];
FILE *fp;
char ch;
snprintf(buf, sizeof(buf), "ifconfig eth0|grep 'inet addr'|awk '{print $2}'|cut -d \":\" -f2"); //拷贝到buf中。
fp = popen(buf, "r");
if(NULL == fp)
{
printf("error!\n");
return -1;
}
while(EOF != (ch = fgetc(fp))) //读
{
fputc(ch, stdout); //写
}
}
编译之后就能输出我们的eth0的ip。
写这篇文章的任务就是分析一下这个代码的一些函数以及截取文本的命令,因为后面做的GPS定位还要获取经度纬度,估计得用到,下面就一起来学习一下这些东东。
snprintf
snprintf( )函数用于将格式化的数据写入字符串,其原型:
int snprintf(char *str, int n, char format [, argument, …]);*
参数
其中str为要写入的字符串;n为要写入的字符的最大数目,超过n会被截断;format为格式化字符串,argument为变量。
返回值
成功则返回参数str***字符串长度,失败则返回-1***,错误原因存于errno中。
snprintf( )的优点是能够控制要写入的字符串的长度,更加安全,只要稍加留意,不会造成缓冲区的溢出。
下面给一段小小的测试:
#include <stdio.h>
int main(int argc, char **agv)
{
char str[5];
int ret = snprintf(str, 3, "%s", "stupid");
printf("%d\n", ret);
printf("%s\n", str);
return 0;
}
输出:
6
st
这里注意了,既然是3个字符,为什么我们只输出st呢?因为我们的Linux下gcc会在后面补一个‘\0’字符,
而在VC中就不会多出个’\0’字符。
popen
popen( )函数通过创建一个管道,调用fork( )产生一个子进程,执行一个shell命令以运行命令来开启一个进程,这个管道由pclose( )函数关闭
pclose()函数关闭标准I/O流,等待命令执行结束,然后返回shell的终止状态。如果shell不能被执行,则pclose()返回的终止状态与shell已执行exit一样。
函数定义
#include <stdio.h>
FILE * popen(const char *command , const char *type);
int pclose(FILE *stream);
参数
type参数只能为读或写其中一种,得到的返回值也一样,如果type是”r“则文件指针连接到command的标准输出;如果type是”w“则文件指针连接到command的标准输入。
command参数是一个shell命令字符串的指针,shell将执行这个命令。
返回值
如果调用fork()或pipe()失败,或者不能分配内存将返回NULL,否则返回标准I/O流。popen()没有为内存分配失败设置errno值。如果调用fork()或pipe()时出现错误,errno被设为相应的错误类型。如果type参数不合法,errno将返回EINVAL。
下面给出一段程序来测试一下:
#include <stdio.h>
int main(int argc, char **argv)
{
FILE *fd;
char buf[20] = {0};
fd = popen("ls","r");
if(NULL == fd)
{
printf("error!\n");
return -1;
}
while(fgets(buf, 20, fd) != NULL)
{
printf("%s", buf);
}
pclose(fd);
return 0;
}
编译后执行可列出我们当前路径的文件列表。
fgetc
fgetc( )从文件中读入一个字符,其调用形式:
ch=fgetc(pFile);
当fgetc成功从文件中读入字符后,ch就是读取到的字符,如果读取失败,则ch=EOF。其中EOF为一个符号常量,当做-1来处理就行。
fputc
fputc( )将一个字符写入到文件中,其调用形式为:
fputc(ch,pFile);
ch为要写入的字符,pFile是指向FILE结构的指针,通过fopen函数打开文件可获得pFile,失败则返回EOF。
这里当读取的值为EOF时,就说明已经读完了,所以EOF在读写文件中扮演重要的角色。
下面给一个程序来测试一下这两个函数:
#include <stdio.h>
int main(int argc, char **argv)
{
char ch;
FILE *p;
FILE *q;
p = fopen("p.txt", "r");
q = fopen("q.txt", "w");
if((NULL == p) || (NULL == q))
{
printf("failed\n");
return 0;
}
ch = fgetc(p);
while(EOF != ch)
{
fputc(ch, q);
ch = fgetc(p);
}
printf("OK!\n");
fclose(p);
fclose(q);
}
这个程序我们创建一个**已有的**p.txt文档,然后打开一个新的q.txt,从p.txt中读字符,然后写入q.txt中,一个字一个字符的读,直到遇见EOF(即文件结尾),然后完成。
函数介绍完了,下面说一说我们的几个截取字段的命令。
grep
grep命令直接抓取当前文本的字符行,这里不细说了。
awk
awk '{print $2}' //默认以空格为分隔符分成几个块,这里截取第二个块
当然,我们的分隔符是根据我们的需求来划分模块的,这里要注意的是awk是每行按空格或其他字符来划分的。
下面举个基本的例子咯:
log.txt的内容:
2 this is a test
3 Are you like awk
This's a test
10 There are orange,apple,mongo
每行按空格或TAB分割,输出文本的1、4项:
1. $awk '{print $1,$4}' log.txt
2 a
3 like
This's
10 orange,apple,mongo
使用“,”分割:
2.awk -F,'{print $1,$2}' log.txt
2 this is a test
3 Are you like awk
This's a test
10 There are orange apple
3.设置变量:
awk -v
$awk -va=1 '{print $1,$1+a}' log.txt
2 3
3 4
This's 1
10 11
还有很多的功能这里就不再深入了,等要用的时候再仔细查询吧。
cut
语法:
cut [-bn] [file]
cut [-c] [file]
cut [-df] [file]
cut命令从文件的每一行剪切字节、字符和字段并将这些写至标准输出。
参数
-b :以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志。
-c :以字符为单位进行分割。
-d :自定义分隔符,默认为制表符。
-f :与-d一起使用,指定显示哪个区域。
-n :取消分割多字节字符。仅和 -b 标志一 起使用。如果字符的最后一个字节落在由 -b 标志的 List 参数指示的<br />范围之内,该字符将被写出;否则,该字符将被排除。
当然,cut命令一般与“|”连用。
好啦,cut命令非常简单实用,这里就不赘述啦。
这样,这个程序就搞定了,以后截取字符串的功能就可以用它来实现了。
本文介绍了一个简单的C程序,通过调用ifconfig命令并结合grep、awk及cut命令来获取本地网络适配器的IP地址。文中详细解释了snprintf、popen、fgetc等函数的应用,以及如何利用shell命令处理文本。
620

被折叠的 条评论
为什么被折叠?



