【问题标题】:Why does strlen function not work in this for loop condition?为什么 strlen 函数在这种 for 循环条件下不起作用?
【发布时间】:2017-08-25 19:37:54
【问题描述】:

我正在学习 C,但我有疑问。在这个练习中,我必须编写一个名为 double dutch 的游戏,您可以在其中学习使用弦乐练习。我遇到的问题是程序由于 for 循环条件(在第一个 for 循环中)而停止执行。当我打印字符串的长度时,strlen() 函数在 main 和 ayInFrontOfConsonant 函数中运行良好,但我不明白程序为什么停止工作。在 Xcode 中,我收到消息:线程 1:EXC_BAD_ACCESS。很感谢任何形式的帮助。

void ayInFrontOfConsonant(char *str) 
{
    char consonants[42] = { 'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 
'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z', 'B', 
'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 
'T', 'V', 'W', 'X', 'Y', 'Z'};


    int a=(int)strlen(str);

    printf("\n Length of str in ay function:   %d\n",a);

    int i=0,j=0;
    for(i=0;i<strlen(str);i++)      //problem is here
    {
        for(j=0;j<strlen(consonants);j++)
        {
            if(str[i]==consonants[j])
            {
                //insertChar(str, 'a', i);

            }
        }
    }
}

int main()
{
    int a=0;
    printf("** Welcome to the Double Dutch game **\n");
    char myString[36];
    printf("Please enter a string: ");
    scanf("%[^\n]s", myString);

    a=strlen(myString);
    printf("Length of string in main: %d\n",a);

    ayInFrontOfConsonant(myString);


    printf("Double dutch traslation: %s\n",myString);


    return 0;

}

【问题讨论】:

  • 你有什么意见?
  • 我使用的输入是:“我喜欢写C代码”
  • 问题可能出在strlen(consonants),其中字符串未正确终止。
  • scanf("%[^\n]s", ... 表示“匹配非空字符序列,而不是换行符后跟s”。这是不可能的,因为除了换行符之外的一系列字符必须后跟换行符或出现在文件末尾。
  • @Urke 如果您要多次使用42,甚至一次,它是一个应该定义的“幻数”。

标签: c for-loop strlen


【解决方案1】:

您的数组没有null 终止符。

取而代之的是,使用sizeof consonants / sizeof *consonants——或者在这种特殊情况下,因为sizeof *consonants肯定是1,那么就只是sizeof consonants

您不应该在for 循环的条件下使用strlen(),因为它每次都会遍历字符串,直到找到您的中缺少的null 终止符

char consonants[42] = { 'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 
    'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z', 'B', 
    'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 
    'T', 'V', 'W', 'X', 'Y', 'Z'};

如果你使用

const char *consonant = "bcdf ...";

相反,编译器会添加 '\0' 终止符,您也可以显式添加它

char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 
        'l', 'm', 'n', 'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z', 'B', 
        'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 'Q', 'R', 'S', 
        'T', 'V', 'W', 'X', 'Y', 'Z', '\0'};

程序员可能会写这个,

#include <stdlib.h>

void ayInFrontOfConsonant(char *str) 
{
    char consonants[] = {
        'b', 'c', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'm', 'n', 
        'p', 'q', 'r', 's', 't', 'v', 'w', 'x', 'y', 'z', 'B', 
        'C', 'D', 'F', 'G', 'H', 'J', 'K', 'L', 'M', 'N', 'P', 
        'Q', 'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z'
    };

    for (size_t i = 0; str[i] != '\0'; i++) {
        for (size_t j = 0; j < sizeof consonants; ++j) {
            if (str[i] == consonants[j]) {
                // Do here whatever you wanted to do
            }
        }
    }
}

但并非如此,因为不需要扫描整个辅音数组,因为它们可以排序,并且您可以使用 二分搜索,这将大大改进算法。

【讨论】:

  • 请注意,sizeof(constonants)/sizeof(*constonant) 技术仅在常量是数组时才有效。将它作为参数传递给函数,它将被转换为指针,并且该技术将不起作用(因此需要以不同的方式传递长度)。
【解决方案2】:

当您编写像char consonants [42] = { ... } 这样的语句时,会发生以下三种情况之一:

如果您有 43 个或更多字符,编译器会给您一个错误。

如果您有 41 个或更少的字符,编译器将用零填充数组的其余部分,并且 strlen() 将起作用,因为字符后面有一个 nul 字节。

如果您正好有 42 个字符,编译器会将数组完全填充到末尾。没有尾随零字节。 strlen 将不起作用。

实际上,你没有理由去数字符。

char consonants [] = "bcdfgh..." 

会做你想要的。

【讨论】:

  • Re "would do exactly what you want",更好的解决方法实际上是保留数组,但使用sizeof 而不是strlen
猜你喜欢
  • 2019-07-23
  • 2013-12-13
  • 1970-01-01
  • 2023-01-28
  • 2021-05-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多