【题解】洛谷P1580 yyy loves Easter_Egg I——一个回车‘\r‘引发的惨案

题目链接: P1580 yyy loves Easter_Egg I

题解

  模拟题。按照题意讨论不同情形,然后输出答案即可。因为比较思路显然,具体的模拟思路略去。这里着重讨论一下该题的坑点。
  坑: 这题使用 getline 函数读取一行,字符串的末尾会出现一个回车符 '\r' (具体原因后面会解释)。所以我们在提取第一个人所@的名字时,如果那个名字出现在句子末尾,后面极有可能紧跟着一个 '\r'。因此要注意判断一下,防止把字符 '\r' 加入人名,造成错误。后面给出的代码中会有对应的注释。
  为什么字符串的末尾会出现回车符呢?
  众所周知,在不同的操作系统的文件中,在一行的末尾,换行符是不同的。例如:

  • Unix/Linux 系统中,行末使用 '\n' 表示换行
  • Windows 系统中,行末使用 '\r\n' 表示换行
  • Mac 系统中,行末使用 '\r' 表示换行

  因此一个系统上生成的文本文件,在另一个不同的系统上用文本编辑器打开,就可能出现一些问题,这是由不同的系统差异导致的。如果生成输入文件的系统是Windows,测评机的系统是Linux,那么在Linux的环境下, getline 默认以 '\n' 作为行的结束符,它不会自动剔除 '\r',而是把回车放到读取的字符串中,最终导致错误。这个错误本质上应该是出题者的锅,是生成文件的系统和测评机系统不一致导致的。
  更进一步地,如果测评机也是Windows系统, getline 函数在Windows上的实现,使得它在Windows系统上可以自动去除多余 '\r',应该不会导致这样的错误。这一点我做了测试,并得到了验证。
  实现的代码见下,变量的命名可能比较随意,不太直观。

#include <iostream>
#include <string>

using namespace std;

int main() {
	int nline, fg = 0, pos = -1;
	string ignr, info, name, speaker;
	
	nline = 1;
	getline(cin, info);
	for (int i = 0, len = info.size(); i < len; ++i) {
		if (info[i] == '@') {
			i += 11;
			name = "";
			
			// !!! 注意判断回车符 '\r' 
			while (i < len && info[i] != ' ' && info[i] != '\r')
				name += info[i], ++i;
				
			break;
		}
	}
	
	while (cin >> ignr && ignr.size() > 0) {
		++nline;
		if (fg) {
			getline(cin, info);
			continue;
		}
		cin >> ignr >> speaker;
		getline(cin, info);
		if (speaker == name) {
			fg = 1;
		} else {
			int atnum = 0;
			for (int i = 0, len = info.size(); i < len; ++i) {
				if (info[i] == '@') {
					if (++atnum != 1 || info.substr(i, 11 + name.size()) != "@yyy loves " + name) {
						atnum = -1;
						break;
					}
				}
			}
			if (atnum != 1) {
				fg = 2;
				pos = nline;
			}
		}
	}
	
	if (fg == 0) {
		cout << "Unsuccessful @yyy loves " + name + " attempt" << endl;
		cout << nline << endl;
		cout << "Good Queue Shape" << endl;
	} else if (fg == 1) {
		cout << "Successful @yyy loves " + name + " attempt" << endl;
	} else if (fg == 2) {
		cout << "Unsuccessful @yyy loves " + name + " attempt" << endl;
		cout << pos << '\n';
		cout << "yyy loves " + speaker << '\n';
	}
	
	return 0;
} 

总结

  本来是觉得这题比昨天做的那题水,没必要写题解的,但是这题遇到的错误却值得花一些篇幅介绍一下。也算是深化了对换行符的认识吧。不得不说,这个错误确实是非常鬼畜(做模拟题果然可以看到一些不一样的东西)。这也算是一道至少需要两次提交才可AC的题目了吧。(如果你是个正常人的话(笑

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值