关于一些OJ上的\r以及\n以及字符串行输入的一些警示

这篇文章详细的解释了在Windows系统和Linux系统下的换行的区别
概括的说,就是Windows系统下的“\r\n”等于Linux系统下的’\n‘
因此在一些搭建在Linux终端上的Oj,测试输入数据是在WIndows上产生的,OJ在评判输出的时候会在Linux下评判并输出
这就导致Windows上的换行行为会在Linux下表示为两个字符’\r\n‘
借用洛谷在线IDE来表示一下

这里我们仅由一个换行输入,但是却从缓冲区中读到了两个字符,与第六行中的\r\n的Ascii码值比较可以看出,Windows系统下的回车确实会被搭建在Linux下的洛谷OJ判定为两个符号即回车符(\r)和换行符’\n‘的组合。

由于这个特性,当我们做题时想清空缓冲区时,必须考虑缓冲区中的\r\n而不是仅考虑\n

插入,经过试验,大多数的OJ(蓝桥OJ,PTA,洛谷OJ)都会将单一的\r也作为换行的标志如下

但是在Windows的IDE却不会这样,我也不到为啥。汗

在我查的资料里\r不论在Windows还是在Linux系统下都只是将光标回到当前行首

以后做题注意下

/——————————————————————————————————————————————————————————————

接下来在讲一讲字符串的行输入问题

由于scanf遇到空格或回车就会停止输入(同时空格和回车不会包含在内),因此在碰到带有空格的字符串的输入会有点麻烦,这时候我们想到了gets函数

gets函数会一直读出缓冲区的内容直到遇到换行符,注意,gets会读入换行符而不像scanf不读入,同时当读入结束后,gets会将换行符销毁并替换为’\0‘

因此,在使用完gets后并不用向scanf一样担心缓冲区回车符的残留

结合上述转义字符以及gets的讲解,在OJ上我们可以发现一些神奇的事

如图,Windows下的直接输入一个回车,可以看出gets确实读到了这个回车键,而且将其销毁替换成0

而在洛谷的在线IDE上呢,就不一样了

可以看到,我输入了一个换行符,但是gets却读到了两个字符,根据上述gets读取字符的规律以及Ascii码的对照,可以知道一个回车被解读为了'\r\n'这两个字符,其中‘\n’被认为是结束标志并被销毁替换为0

由此可以看出gets是以换行符‘\n’为结束标志的,而且他会将回车符从缓冲区读入后销毁并替换为0,由于在windows下生成的测试文本的换行为‘\r\n’,因此每次gets一下,得到的字符串里就会多出一个‘\r’,表现在OJ里的输出就是会莫名其妙的换行或者读取错误

因此最好还是别用gets了(心累ing),可以用scanf看看有没有别的处理方法,或者用gets的话可以参考一下这段代码

bool Safe_Gets(char *S)
{
    if (!gets(S))return false;//若已经到文件或者缓冲区结尾,gets会返回char*型的NULL指针
    int n = strlen(S);
    if (n && S[n - 1] == '\r')S[n-1]=0;//当字符长度不为0同时又以回车符结尾时,将回车符替换为结束标志‘\0'
    return true;
}
这样的话就可以避免\r的入侵,不过使用第一个gets时别忘了清空缓冲区

 ——————————————————————————————————————————————————————

OJ上的输入回车是根据行来判定的

 

 比如这个输入,1到2需要回车,那么可以知道第一行输入完会有一个'\r\n',第2,3,4行同理,但是第五行最后并未换行,因此没有‘\r\n’的残留,可以认为在最后是通过Enter键入的,也就是纯粹的换行符‘\n',而非‘\r\n’,而且这在Windows以及Linux下都是相同的,也就是说,Enter键仅代表换行符'\n'的输入,无论是在Windows还是Linux中。

posted @ 2023-04-07 12:03  凪风sama  阅读(238)  评论(0编辑  收藏  举报