差异 b/w 使用 i<strlen() 和 str[i] != '\0'

Adi*_*jha 1 c arrays string algorithm runtimeexception

当我使用时,for(i=0;i<strlen(s);i++)我收到时间限制超过错误。当我使用for(i=0;s[i]!='\0';i++)我的代码获得成功提交。为什么?

我还提供了来自 codechef 的问题链接 - https://www.codechef.com/problems/LCPESY

类型 1:

    for (i = 0; i < strlen(s1); i++) {
        f1[s1[i]]++;
    }
    for (i = 0; i < strlen(s2); i++) {
        f2[s2[i]]++;
    }
Run Code Online (Sandbox Code Playgroud)

类型 2:

    for (i = 0; s1[i] != '\0'; i++) {
        f1[s1[i]]++;
    }
    for (i = 0; s2[i] != '\0'; i++) {
        f2[s2[i]]++;
    }
Run Code Online (Sandbox Code Playgroud)

完整代码:

#include <stdio.h>
#include <string.h>

long int min(long int a, long int b) {
    if (a >= b)
        return b;
    else
        return a;
}

int main(void) {
    // your code goes here
    int t;
    scanf("%d", &t);
    while (t--) {
        char s1[10001], s2[10001];
        scanf("%s%s", s1, s2);
        long int f1[200] = { 0 }, f2[200] = { 0 }, i, count = 0;
    
        for (i = 0; i < strlen(s1); i++) {
            f1[s1[i]]++;
        }
        for (i = 0; i < strlen(s2); i++) {
            f2[s2[i]]++;
        }
        
        for (i = 0; i < 200; i++) {
            count += min(f1[i], f2[i]);
        }
        printf("%ld\n", count);
    }
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

Ant*_*ala 5

如果使用非优化编译器,则可以在strlen每次迭代中重新评估一次。strlen然后需要检查字符串中的每个字符是否与0. 这导致二次运行时,其中O(n²)检查终止空值,而不仅仅是必要的O(n)时间。在strlen代码中发生超时是因为它可能执行了 2,000,000 次空检查和 10,000 次其他操作;其他代码将执行 2,000 次空检查和相同的 10,000 次其他操作,并且不会超时。


然而,这不一定是一种情况。由于as-if规则,C 编译器可以为这些情况生成完全等效的机器

for (i = 0; i < strlen(s1); i++){
    f1[s1[i]] ++;
}
Run Code Online (Sandbox Code Playgroud)

for (i = 0; s1[i] != '\0'; i++) {
    f1[s1[i]] ++;
}
Run Code Online (Sandbox Code Playgroud)

因为编译器可以很容易地证明内循环不可能改变s1,因此两种形式的行为都是相同的。

  • 我认为“惯用的”C 语言是 `for (char cp* const = s1; *cp; ++cp) f1[*cp]++; ` 而不是使用索引。这当然是我会写的(除了我会使用“unsigned char”来避免“f1”可能出现负索引)。 (3认同)
  • 好答案。更深入:只需要稍微复杂一点的代码,编译器就不能轻易地使 `i &lt; strlen(s1)` 与 `s1[i] != '\0'` 相同。因此,在 IMO 中,`s1[i] != '\0'` 或 `s1[i]` 是首选且更惯用的 C。 (2认同)