最近,我写了一段在 2∼n 范围内分解质因数、打印质数的代码。
#include<bits/stdc++.h>
using std::vector;
void w(int x,char c){
char s[10]="",l=-1;
while(x)s[++l]=x%10,x/=10;
while(putchar(s[l]+48),l--);
putchar(c);
}//快写
int main(){
char c;
while(c=getchar(),c<48||c>57);
int n=c-48;
while(c=getchar(),c>47&&c<58)n=n*10+c-48;//快读
int*p=new int[n+1]{},l=0;vector<int>q;
freopen("times.txt","wb",stdout);//由于输出量较大,故采用文件输出
for(int i=2;i<=n;i++){
if(!p[i])q.push_back(p[i]=i),l++;
w(i,61);
for(int j=i;;j/=p[j])if(j^p[j])w(p[j],42);
else{w(p[j],10);break;}
for(int j=0;j<l&&q[j]*i<=n;j++)if(!(i%(p[q[j]*i]=q[j])))break;
}//欧拉筛法
delete[]p;
freopen("primes.txt","wb",stdout);
for(int i=0;i<l;i++)w(q[i],10);
}
在 Windows 7,10 电脑上编好代码后,我输入了 100,程序也给出了正确结果。但是,当我输入了一个 106 以后,虽然 times.txt 的输出正确,但 primes.txt 却是大量乱码(此为图片)。我又更换了输入,看一下会不会出现这样的问题。最终,我发现,当 n⩽1408 时,primes.txt 是正确的,但只要 n⩾1409(1409 是 1400 后的第 1 个质数,也是从小到大第 223 个质数),primes.txt 就是乱码。
看到如此令人惊讶的结果,我想:这是不是和文件操作格式有关呢?我将打印到 times.txt 中的代码注释掉,又更改了格式,果然不出所料,只要文件格式中含有字符 b(wb,ab,rb+,wb+,ab+),就会出现雷同的乱码,否则(w,a,r+,w+,a+)就是正确。
在上述结果中,只有输入含字符 b 的文件操作格式,程序才会出错。但是,在只打印 1 与 \n 的情况下,不管是用什么追加操作,primes.txt 都有字符 റ,但其它操作却能让它安然无恙;而与此同时,times.txt 却一点问题都没有。这样的结果让我十分奇怪:为什么在不同的情况下,安全性高的文件操作格式会如此不同?一定得打印到第 223 个质数,才会出现乱码吗?难道电脑就对 primes.txt 那么“有仇”(总想让它全是乱码),而对 times.txt 那么“友好”?