C++ 字符数组和printf使程序变慢

C++ 字符数组和printf使程序变慢,c++,C++,(嗯,我的英语不好):) 我的朋友现在正在学习C++,他发现了一个我无法解释为什么的问题。 第一个代码,运行时间超过2000毫秒 #include <cstdlib> #include <cstdio> #include <cstring> using namespace std; int ans[2000000]; char a[2000000]; int main() { scanf("%s\n",a); int l=1,r=str

(嗯,我的英语不好):)

我的朋友现在正在学习C++,他发现了一个我无法解释为什么的问题。 第一个代码,运行时间超过2000毫秒

#include <cstdlib>
#include <cstdio> 
#include <cstring>

using namespace std;

int ans[2000000];
char a[2000000];

int main()
{
    scanf("%s\n",a);
    int l=1,r=strlen(a);
    for (int i=0;i<strlen(a);i++) 
        if (a[i]=='l')
            ans[r--] = i+1;
        else
            ans[l++] = i+1;
    for (int i=1;i<=strlen(a);i++)
        printf("%d\n",ans[i]);
    return 0;
}
#include <cstdlib>
#include <cstdio>
#include <cstring>

using namespace std;

int ans[2000000];
char a[2000000];
int size;

int main()
{
    scanf("%s",a);
    int l=1,r=strlen(a);
    size = r;
    for (int i=0;i<size;i++) 
        if (a[i]=='l') ans[r--]=i+1;else ans[l++]=i+1;
    for (int i=1;i<=strlen(a);i++)
        printf("%d\n",ans[i]);
    return 0;
}
#包括
#包括
#包括
使用名称空间std;
int ans[2000000];
char a[2000000];
int main()
{
scanf(“%s\n”,a);
int l=1,r=strlen(a);

对于(int i=0;i当循环中有函数时,每次都必须通过循环执行
strlen
函数。这是一个额外的函数调用,它必须遍历整个字符串才能找到它的长度

将长度缓存为
大小
,这意味着每次通过循环时都不必重做任何内容


因此,没有错误。这是预期的行为。

通过在循环条件中写入
strlen
——一个有200万次迭代的循环——您正在扫描一个2兆字节的字符串200万次。当然,这需要一些时间

只要预先计算一次字符串长度,延迟就会消失


此外,您可能会发现,将2MB的文本流传输到控制台的速度会明显“缓慢”在任何情况下。

你都想知道为什么要将
strlen
超过2MB,两百万次,需要一两秒钟?你似乎希望
a
中基于1的“l”字符索引填充在
ans
的最高索引中,而非
l
字符填充在较低的索引中。但是,
ans[r--]是一个太远到<代码> ANS>代码>——在 ANS<代码>中间,你可能会遇到一个不需要的<代码> 0代码/>值。如果不需要,用<代码> ANS[-R] < /代码>替换<代码> ANS [R- ] /代码>。正如其他人所说的,你只需要代码> const siZetht Le= StLLEN(a)
在循环上方,然后用
len
替换所有其他
strlen(a)
。您是否将所有程序运行多次(至少几十次)并取平均值以确保计时合理可靠?@molbdnilo是的,我将程序提交给OnlineJudge(Codeforces)很多时候,它使用g++4.7.2来判断我的程序。@volz.kz.g这不是一种非常可靠的计时方法。你应该在自己的机器上运行这些程序,并对所有程序使用相同的输入。由“l”控制的输入字符串可能比只有几个“l”的输入字符串慢(因为你访问
ans
),反之亦然(由于分支预测),I/O时间将随输入而变化。除非控制输入,否则无法得出任何结论。嗯,但当我将第一个for循环的strlen函数更改为size时,它运行得很快。这是因为
size
只是一个变量。但是
strlen
是一个函数。因此,您存储了
strlen()的结果
size
strlen(
)中的
只被调用一次。如果不使用
size
存储结果,
strlen()
每次通过循环都会被调用。如果你知道结果不会改变,那么将函数的结果保存在变量中是一个很好的加速方法!对不起,我的描述是错误的。应该是当我只将第二个for循环的strlen函数更改为size时,它运行得很快。但是当我只将第一个for循环的strlen函数更改为size时StLLN函数的大小,它运行缓慢。@ Valz。kz。G:你试图应用简单化的逻辑来从你看到的结果中得出结论,但是没有考虑一系列的因素,比如缓存,写进数组,以及你仍然在处理二百万个元素。我的建议是:你能看一下汇编吗?r运行探查器?这将揭示为什么优化不同的循环会得到不同的结果。最后,虽然你不应该期望循环可以优化到相同的程度。它们是不同的。谢谢你,但这不是我想知道的。我已经测试了当我只为循环创建第一个strlen时,它运行得很快
#include <cstdlib>
#include <cstdio>
#include <cstring>

using namespace std;

int ans[2000000];
char a[2000000];
int size;

int main()
{
    scanf("%s",a);
    int l=1,r=strlen(a);
    size = r;
    for (int i=0;i<size;i++) 
        if (a[i]=='l') ans[r--]=i+1;else ans[l++]=i+1;
    for (int i=1;i<=strlen(a);i++)
        printf("%d\n",ans[i]);
    return 0;
}
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <string>

using namespace std;

int ans[2000000];
string a;

int main()
{
cin >>a;
    int l=1,r=a.size();
    for (int i=0;i<a.size();i++) 
        if (a[i]=='l') ans[r--]=i+1;else ans[l++]=i+1;
    for (int i=1;i<=a.size();i++)
        printf("%d\n",ans[i]);
    return 0;
}