scanf,sscanf利用format跳过干扰的空格
scanf,sscanf利用format跳过干扰的空格
用了一点时间做读取配置部分的代码,希望一次记录上读取N个数据,
希望读取的格式就是一个IP地址加上端口号,希望把IP地址读取到4个短整数里面,端口号读取到另外的一个短整数。文字格式类似“192.120.1.120#8080”,但结果发现因为为了对齐,中间的空格干扰了读取。
读取的输入可能是这样“192.120.1.120 # 8080”,甚至可能是 " 192 .168 . 1 .120 # 8080 "
郁闷。google +MSDN,发现其实可以就用scanf,sscanf绕过。最后选择的format 是"%hu . %hu . %hu . %hu # %hu",请注意中间的空格。
参考文档:
http://www.cplusplus.com/reference/cstdio/scanf/ 此文档写的很细致。
http://linux.die.net/man/3/sscanf
另外发现scanf 还具有比较简单的正则能力。处理很多格式化内容其实还是挺方便的。(原来土鳖都是过滤掉空格的。)
下面是自己测试自己测试的例子,还走了一下弯路,先以为用正则可以搞点,结果发现正则的写法还是不如空格过滤好用。
scanf的format字符串:
空格:也会同样去过滤输入字符串的空格,而且会持续过滤,直到不是空格为止。(空格也包括tab,回车等)
其他字符,(不包括%):会同样在输入字符里面跳过想用的字符。
%:控制输入一个字段,根据后面的长度,控制符读取数据内容。比如%d等。
%*:会跳过一个输入字段,比如sscanf("123 456","%*d %d",&data); data读取会是456;
%[0-9]:贪婪的读取0-9的字符,作为一个string读取
%[^0-9]:贪婪的读取非0-9的字符,作为一个string读取
#include <iostream>
#include <stdio.h> using namespace std; int main()
{
int ret = ;
short ip_addr[];
unsigned short port; cout <<"============================================="<<std::endl;
port = ip_addr[] = ip_addr[] = ip_addr[] = ip_addr[] = ;
ret = sscanf("192.168.1.120#8080",
"%hu.%hu.%hu.%hu#%hu",
&ip_addr[],
&ip_addr[],
&ip_addr[],
&ip_addr[],
&port
);
//ret 5, IP 192 168 1 120Port 8080 读取正确
cout <<"ret " <<ret <<
" IP "<<ip_addr[] <<" "<<ip_addr[] <<" "<<ip_addr[] <<" "<<ip_addr[] <<" Port "<< port << endl; port = ip_addr[] = ip_addr[] = ip_addr[] = ip_addr[] = ; ret = sscanf(" 192 .168 . 1 .120 # 8080",
"%hu.%hu.%hu.%hu#%hu",
&ip_addr[],
&ip_addr[],
&ip_addr[],
&ip_addr[],
&port
);
//ret 1, IP 192 0 0 0Port 0 读取错误
cout <<"ret " <<ret <<
" IP "<<ip_addr[] <<" "<<ip_addr[] <<" "<<ip_addr[] <<" "<<ip_addr[] <<" Port "<< port << endl; cout <<"============================================="<<std::endl; port = ip_addr[] = ip_addr[] = ip_addr[] = ip_addr[] = ;
ret = sscanf("192.168.1.120#8080",
"%hu%*[^.].%hu%*[^.].%hu%*[^.].%hu%*[^#]#%hu",
&ip_addr[],
&ip_addr[],
&ip_addr[],
&ip_addr[],
&port
);
//ret 1 IP 192 0 0 0Port 0 读取错误,因为%*[^.] 是要匹配一个任何一个非.的字符。但192后面就是.
cout <<"ret " <<ret <<
" IP "<<ip_addr[] <<" "<<ip_addr[] <<" "<<ip_addr[] <<" "<<ip_addr[] <<" Port "<< port << endl; port = ip_addr[] = ip_addr[] = ip_addr[] = ip_addr[] = ;
ret = sscanf(" 192 .168 . 1 .120 # 8080",
"%hu%*[^.].%hu%*[^.].%hu%*[^.].%hu%*[^#]#%hu",
&ip_addr[],
&ip_addr[],
&ip_addr[],
&ip_addr[],
&port
);
//ret 5, IP 192 168 1 120Port 8080 读取正确
cout <<"ret " <<ret <<
" IP "<<ip_addr[] <<" "<<ip_addr[] <<" "<<ip_addr[] <<" "<<ip_addr[] <<" Port "<< port << endl; cout <<"============================================="<<std::endl; port = ip_addr[] = ip_addr[] = ip_addr[] = ip_addr[] = ;
ret = sscanf("192.168.1.120#8080",
"%hu . %hu . %hu . %hu # %hu",
&ip_addr[],
&ip_addr[],
&ip_addr[],
&ip_addr[],
&port
);
//ret 5, IP 192 168 1 120Port 8080 读取正确
cout <<"ret " <<ret <<
" IP "<<ip_addr[] <<" "<<ip_addr[] <<" "<<ip_addr[] <<" "<<ip_addr[] <<" Port "<< port << endl; port = ip_addr[] = ip_addr[] = ip_addr[] = ip_addr[] = ;
ret = sscanf(" 192 .168 . 1 .120 # 8080",
"%hu . %hu . %hu . %hu # %hu",
&ip_addr[],
&ip_addr[],
&ip_addr[],
&ip_addr[],
&port
);
//ret 5, IP 192 168 1 120Port 8080 读取正确,format中的空格的匹配输入字符串的任意空格,很好用
cout <<"ret " <<ret <<
" IP "<<ip_addr[] <<" "<<ip_addr[] <<" "<<ip_addr[] <<" "<<ip_addr[] <<" Port "<< port << endl; return ;
}
scanf,sscanf利用format跳过干扰的空格的更多相关文章
- 浅析C语言中printf(),sprintf(),scanf(),sscanf()的用法和区别
printf语法: #include <stdio.h>int printf( const char *format, ... ); printf()函数根据format(格式)给出的格式 ...
- scanf/sscanf %[]格式控制串的用法(转)
scanf/sscanf %[]格式控制串的用法 scanf中一种很少见但很有用的转换字符:[...]和[ ^...]. #include<stdio.h> int main() { ch ...
- 利用Format函数格式化时间和日期
在做机房收费系统的时候,因为需要使用到日期进行查询,所以在数据表中没有使用自动添加日期的功能,而是采用了自定义的格式插入.但由于事先没有对时间转换的格式进行统一,导致后面查询时出现的问题不断. 插入时 ...
- 利用skipList(跳表)来实现排序(待补充)
用于排名的数据结构 一般排序为利用堆排序(二叉树)和利用skipList(跳表)的方式 redis中SortedSet利用skipList(跳表)来实现排序,复杂度为O(logn),利用空间换时间,类 ...
- 利用cookies跳过登陆验证码
前言在爬取某些网页时,登陆界面时经常遇到的一个坎,而现在大多数的网站在登陆时都会要求用户填写验证码.当然,我们可以设计一套机器学习的算法去破解验证码,然而,验证码的形式多种多样,稍微变一下(有些甚至是 ...
- 利用java生成带有干扰线的网页验证码图片
package imageCreate; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import j ...
- Android开发之EditText利用键盘跳转到下一个输入框
以前做项目的时候,从来没考虑过这些.这段时间公司内部用的一款APP,就出现了这个问题,在登录或者注册的时候,点击键盘的回车按钮,可以跳到下一个输入框的功能,这个属性一直也没记住,今天就把自己一直没记过 ...
- 利用canvas绘制带干扰线的验证码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- PHP利用微信跳转的Code参数获取用户的openid
//获取微信登录用户信息function getOpenID($appid,$appsecret,$code){ $url="https://api.weixin.qq.com/sns/ ...
随机推荐
- js 字符串日期 转成 Date
只支持 2015/09/23 反斜杠这样类型 2015-09-23 单横的这种无法识别 var dateStr='${endDate}'; dateStr=dateStr.replace(/-/g,' ...
- cocos2dx开发笔记
1.帧动画:SpriteTest=>SpriteAnimationSplit 2.sourceinsight显示代码行 option->document option->editin ...
- 构建linux内核源码树
编写驱动程序时,需要内核源码树的支持.内核源码树时从内核源代码编译得到的.下面开始构造内核源代码的步骤.以Ubuntu为例子 1. 下载内源代码,位置www.kernel.org. (注意:源码树内核 ...
- hdu 4920 Matrix multiplication (矩阵计算)
题目链接 题意:给两个矩阵a, b, 计算矩阵a*b的结果对3取余. 分析:直接计算时间复杂度是O(n^3),会超时,但是下面第一个代码勉强可以水过,数据的原因. #include <iostr ...
- poj 1067 取石子游戏( 威佐夫博奕)
题目:http://poj.org/problem?id=1067 题意:有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的 ...
- WPF 用 DataTemplate 合并DataGrid列表列头<类似报表设计>及行头列头样式 - 学习
WPF中 DataGrid 列头合并,类似于报表设计.效果图如下↓ 1.新建一个WPF项目WpfApplication1,新建一个窗体DataGridTest,前台代码如下: <Window x ...
- SQL查看数据库所用用户表数量和使用的空间
SQL Server数据库管理员通常硬盘空间奋斗,不断努力清理“表”,撰写许多查询,发现该表使用的硬盘空间. 本文介绍了如何查询系统表的空间使用情况,帮助数据库管理员识别正在使用最多的空间,以便存档旧 ...
- LA 5059 (找规律 SG函数) Playing With Stones
题意: 有n堆石子,两个人轮流取,每次只能取一堆的至少一个至多一半石子,直到不能取为止. 判断先手是否必胜. 分析: 本题的关键就是求SG函数,可是直接分析又不太好分析,于是乎找规律. 经过一番“巧妙 ...
- Linux LiveCD 的制作
Knoppix,只需一张光盘, 就能够让我们在任何场所,随心所欲地使用 Linux1, 打破了操作系统只能先安装再使用的传统概念. Knoppix 最初的设计用途是教学,但由于这项技术很受欢迎,使得 ...
- hdu 4612 Warm up(缩点+树上最长链)
本来就是自己负责图论,结果水了= = 题目其实很裸,就是求桥的数量,只是要新加上一条边罢了.做法:先缩点.再在树上搜最长链(第一场多校的hdu 4607Park Visit就考了最长链,小样,套个马甲 ...