sscanf小技巧-洛谷P7911 网络连接

sscanf小技巧-洛谷P7911 网络连接


序言

本题解来源:本蒟蒻上课摸鱼 (别学我)
最近学了一个挺好用的函数——sscanf(),结合洛谷P7911 网络连接讲一下。
(点击查看题目)


推荐几首纯音乐,拿走不谢↓
  1. Bloom of Youth
  2. Windy Hill
  3. Love Is Gone
  4. 所念皆星河

- 这题其实挺简单的, 让不少人 (包括本蒟蒻) 头大并WA掉的主要是这几点:

1 . 把数字和字符 拆开 分开判断
2 . 判断前导0
3 . 查找、判断重复
4 . …


题目分析


  • 本题为洛谷 P7911 网络连接
  • 题目虽然比较长,但比较简单,耐心看很容易就能看懂

  • 输入类型、地址↓
    string s, t;
    cin>>s>>t;
  • 若地址不符合要求,输出“ERR”,判断下一个↓
    if(!check(t)){
      cout<<"ERR"<<endl;
      continue;
    }
  • 若为服务机(Server)↓
if(s == "Server")
  1. 若地址没有出现过,输出“OK”↓
    if(server[t] == 0){
      server[t] = i;
      cout<<"OK"<<endl;
    }
  1. 若与先前某台已经成功建立连接的服务机的地址相同,输出“FAIL”↓
    else{
      cout<<"FAIL"<<endl;
    }
  • 若为客户机(Client)↓
else
  1. 若与先前某台已经成功建立连接的服务机的地址相同,输出服务机的地址↓
    if(server[t] > 0)
        cout<<server[t]<<endl;
  1. 若找不到这样的服务机,则这台客户机无法成功加入连接↓
    else
      cout<<"FAIL"<<endl;

正文(— _ —)

一、介绍一个函数—— sscanf()

(别看我,我没打错,就是 sscanf)

头文件 (万能头)↓

#include <bits/stdc++.h>

sscanf 的用法

  • sscanf
    的用法类似一个字符串格式化工具
  1. 从一个字符串中读进与指定格式相符的数据
    char ch[101];
    sscanf("12345", "%s", ch);  //读入字符串
    cout<<ch;  //输出12345
    
  2. 取指定长度的字符串
    char ch[101];
    sscanf("12345", "%3s", ch);  //取指定长度的字符串
    cout<<ch;  //输出123
    
  3. 取到指定字符为止的字符串
    char ch[101];
    sscanf("12345abcd", "%[^a]", ch);  //读到a
    cout<<ch;  //输出12345
    
  4. 取到指定字符集为止的字符串
    char ch[101];
    sscanf("123m45abcd", "%[^a-z]", ch);  //读到m
    cout<<ch;  //输出123
    
  5. 补充介绍一个sprintf()
    ·既然sscanf是把字符串拆开,那sprintf就是把字符串拼起来

这样用↓

char ch[101];
sprintf(ch,"%d.%d.%d.%d:%d",1,2,3,4,5);
cout<<ch;  //输出 1.2.3.4:5

二、介绍一种数据结构——map

map是啥??

就是一个能以任意数据结构为下标的数组。

所以怎么用??

举个栗子:我们要建一个以字符串即 string
为下标、存 int的名为 a
数组,就可以这样写↓

map<string, int>a;

那么这样存值↓

string str = "-_-";
a[str] = 4;

这样我们就可以直接判断地址是否出现过

是不是很神奇?

三、一个判断前导0的小方法

我们现在已经有了 sscanf()sprintf(),就可以把字符串里的数字拆出来,前导0就会省略,再拼回去,与原字符串比较,如果不同就是有前导0

四、讲完技巧,开始写代码

  • 这题思路十分的简单,直接模拟就行

直接上标程↓

#include<bits/stdc++.h>
using namespace std;
int n;
map<string, int>server;
bool check(string ip){
	int t[6] = {0, -1, -1, -1, -1, -1};
	int cnt = sscanf(ip.c_str(), "%d.%d.%d.%d:%d", &t[1], &t[2], &t[3], &t[4], &t[5]);
	if(cnt != 5) return 0;
	for(int i=1;i<=4;i++)
		if(t[i] < 0 || t[i] > 255) return 0;
	if(t[5] < 0 || t[5] > 65536) return 0;
	char ch[50];
	sprintf(ch, "%d.%d.%d.%d:%d", t[1], t[2], t[3], t[4], t[5]);
	if(ip != string(ch)) return 0;
	return 1;
}
int main(){
	freopen("network.in", "r", stdin);
	freopen("network.out", "w", stdout);
	cin>>n;
	string s, t;
	for(int i=1;i<=n;i++){
		cin>>s>>t;
		if(!check(t)){
			cout<<"ERR"<<endl;
			continue;
		}
		if(s == "Server"){
			if(server[t] == 0){
				server[t] = i;
				cout<<"OK"<<endl;
			}
			else{
				cout<<"FAIL"<<endl;
			}
		}
		else{
			if(server[t] > 0)
				cout<<server[t]<<endl;
			else
				cout<<"FAIL"<<endl;
		}
	}
	return 0;
} 

写在最后

感谢耐心看完这136行的题解!

希望你们能学到东西 (# ^ . ^ #)

( 没用的小知识又增加啦 )

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值