关于一些OJ上的\r以及\n以及字符串行输入的一些警示
![](https://img2023.cnblogs.com/blog/3147612/202304/3147612-20230407112639591-442044753.png)
这里我们仅由一个换行输入,但是却从缓冲区中读到了两个字符,与第六行中的\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中。