c - 低效地使用 strstr 和 strchr

标签 c

在审查我的代码时,我的教授说我使用 strstrstrchr 会导致大量资源浪费,因为它们中的每一个都会扫描字符串。

我可以减少函数的数量吗?

此代码扫描一个字符串,并根据设置的参数决定输入是否有效。
ch1'@'ch2'.', (email[i]) 是字符串。

    for (i = 0; email[i] != 0; i++) {
        {
            if (strstr(email, "@.") ||
                strstr(email, ".@") ||
                strstr(email, "..") ||
                strstr(email, "@@") ||
                email[i] == ch1 ||
                email[i] == ch2 ||
                email[strlen(email) - 1] == ch1 ||
                email[strlen(email) - 1] == ch2) {
                printf("The entered e-mail '%s' does not pass the required parameters, Thus it is invalid\n", email);
            } else {
                printf("The email '%s' is a valid e-mail address\n",email);
            }
            break;
        }
    }

这就是我所说的片段。

我应该编写自己的代码来执行一次检查吗?如果是这样,你能给我一些这方面的指示吗? 谢谢你。

编辑:非常感谢您的回复,我确实了解到我的代码中的错误,希望我能从中吸取教训。
再次感谢!

编辑:2:我想再次感谢您的回复,他们对我帮助很大,我相信我写出了更好的代码

int at_count = 0, dot_count = 0, error1 = 0, error2 = 0;
int i;
size_t length = strlen(email);
int ch1 = '@', ch2 = '.';

for ( i = 0; email[i] != '\0'; i++)  /* for loop to count the occurance of the character '@' */
    {
    if ( email[i] == ch1)
        at_count++;
    }

for ( i = 0; email[i] != '\0'; i++)  /* for loop to count the occurance of the character '.' */
    {
    if ( email[i] == ch2)
        dot_count++;
    }

if ( email[0] == ch1 || email[0] == ch2 || email[length-1] == ch1 || email[length-1] == ch2 )
        {
    error1++;
        }
else
        {
    error1 = 0;
        }


if ( strstr(email,".@") || strstr(email, "@.") || strstr(email, "..") || strstr(email, "@@"))
        {
    error2++;
        }
else
        {
    error2 = 0;
        }

if ( (at_count != 1) || (dot_count < 1) || (error1 == 1) || (error2 == 1))
    {
    printf("The user entered email address '%s' is invalid\n", email);
    }
else
    {
    printf("'%s' is a valid email address\n", email);
    }

我觉得这样的代码更优雅、更简单,也更高效。
我的主要灵感来自@chqrlie,因为我觉得他的代码非常好并且易​​于阅读。 无论如何,我可以改进吗?
(电子邮件检查只是为了练习,不要介意!) 非常感谢大家!

最佳答案

你的代码确实有多个问题:

for (i = 0; email[i] != 0; i++) {   // you iterate for each character in the string.
    {   //this is a redundant block, remove the extra curly braces
        if (strstr(email, "@.") ||  // this test only needs to be performed once
            strstr(email, ".@") ||  // so does this one
            strstr(email, "..") ||  // so does this one
            strstr(email, "@@") ||  // again...
            email[i] == ch1 ||      // this test is only performed once
            email[i] == ch2 ||      // so is this one
            email[strlen(email) - 1] == ch1 ||  // this test is global
            email[strlen(email) - 1] == ch2) {  // so is this one
            printf("The entered e-mail '%s' does not pass the required parameters, Thus it is invalid\n", email);
        } else {
            printf("The email '%s' is a valid e-mail address\n", email);
        }
        break;  // you always break from the loop, why have a loop at all?
    }
}

您扫描字符串 4 次以测试各种模式,另外扫描 2 次以测试 strlen()。应该可以在单次扫描过程中执行相同的测试。

另请注意,还有更多问题未被注意到:

  • 应该有一个@存在
  • 不能有空格
  • 更一般地说,地址中允许的字符是有限的。

一些测试似乎有些矫枉过正:为什么拒绝 @ 之前的 ..,为什么拒绝 @ 之前的尾随 . ?

这是一个更高效的版本:

int at_count = 0;
int has_error = 0;
size_t i, len = strlen(email);

if (len == 0 || email[0] == ch1 || email[0] == ch2 ||
    email[len - 1] == ch1 || email[len - 1] == ch2) {
    has_error = 1;
}

for (i = 0; !has_error && i < len; i++) {
    if (email[i] == '.') {
        if (email[i + 1] == '.' || email[i + 1] == '@') {
            has_error = 1;
        }
    } else if (email[i] == '@') {
        at_count++;
        if (i == 0 || i == len - 1 || email[i + 1] == '.' || email[i + 1] == '@') {
            has_error = 1;
        }
    }
    // should also test for allowed characters         
}

if (has_error || at_count != 1) {
    printf("The entered e-mail '%s' does not pass the required tests, Thus it is invalid\n", email);
} else {
    printf("The email '%s' is a valid e-mail address\n", email);
}

关于c - 低效地使用 strstr 和 strchr,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54062352/

相关文章:

c - 我应该将一个接受参数的函数分配给接受 void 的函数指针吗?

c - 从 C 中的结构构建字符串

使用 "Set prompt"命令在 C 中创建简单的 shell

c - 为 C 代码覆盖率分析生成定义使用路径

python - 从 C Windowsx64 调用 Cython 函数

c++ - 如何根据用户请求安全地停止正在运行的线程?

c - MS VS 2008 和 C99

c - 如何通过 C 代码增加 net.core.rmem_max 值

c - 为什么要使用变量的地址来改变变量的值?

c - 在C程序中使用fabs、fmin、fmax时,如果不包含math.h,为什么编译器/链接器不报错?