【问题标题】:undefined behavior when strcatstrcat 时未定义的行为
【发布时间】:2015-07-18 15:05:49
【问题描述】:
in = "(A + B) * C - D * F + C";
#define MAXL 256

我在case ')' 的代码有问题。

我的代码未完成,因为它在某处遗漏了几行代码,以将堆栈内的所有最终char = operators 添加到tempExp,我可能很快就会弄清楚™。我现在需要的是您输入为什么这条线while(c[0] != '(') strcat(tempExp, c); 会导致未定义的行为。

非常感谢!

注意:这个混乱的代码c[0] = *((char*)pop(s)) 的原因是pop 返回一个void*,我无法在本练习中更改它。

void convertIntoPost(char * in, char ** out)
{
    int i;
    Stack * s = createStack();
    char tempExp[MAXL] = "temp: ", c[2];
    c[1] = '\0';
    printf("\n%s\n", tempExp);
    for(i = 0; i <= strlen(in); ++i)
    {
        printf("i: %d", i);
        c[0] = in[i];
        if(isalpha(c[0]) || isalnum(c[0]))
        {
            c[0] = in[i];
            printf("\nc passed isalpha OR isalnum: %s\n", c);
            strcat(tempExp, c);
        }
        else
        {
            switch(in[i])
            {
                case ' ' : break;
                case '(' :
                    push(s, &in[i]);
                    break;
                case ')' :
                    c[0] = *((char*)pop(s));
                    printf("c in case ')': %s", c); /* Show expected result */
                    printf("\n%s", tempExp); /* Just checking tempExp and see no problem */
                    while(c[0] != '(')
                        strcat(tempExp, c);
                    printf("\n%s", tempExp); /* Program stopped before it gets here */
                    break;
                default :
                    while(!isEmpty(s) && (priority(in[i]) <= priority(c[0] = *((char*)pop(s)))))
                        strcat(tempExp, c);
                    push(s, &in[i]);
            }               
        }            
    }
    printf("\nThis is in: %s", in);
    printf("\n%s", tempExp);
    *out = (char*)malloc(strlen(tempExp) + 1);
    *out = strdup(tempExp);
    makeEmpty(s);
}

int priority(char c)
{
    if(c == '(')
        return(0);
    else if(c == '+' || c == '-')
        return(1);
    else if(c == '*' || c == '/')
        return(2);
}

【问题讨论】:

  • 你应该在那个循环中有条件i &lt;= strlen(in) 吗?这将导致循环在in 中包含字符串终止符。
  • while 永远不会运行,或者永远不会停止。
  • strcat(连续地)连接整个字符串c,而不仅仅是第一个字符。它也不会切断它c。看来您来自另一种语言。
  • @Pawan 他为什么要这么做?在 Mizushima:考虑删除 undefined behavior 标签。
  • @Joachim 我测试过,strlen 返回不包括终止符的字符串长度。这是来自另一个函数的 in 的第三次传递,之前的 2 次传递没有使程序崩溃。

标签: c strcat


【解决方案1】:

除了格兰特利指出的无限循环之外,您还有其他几个问题,主要是因为两件事:

  1. 您的循环包含in 的字符串终止符,因此您将在switch 语句中以默认情况结束,实际上您将调用priority('\0'),这会导致您的第二个问题。您还将使用指向字符串终止符的指针调用 push,如果 push 假定指针未指向字符串的末尾,您也可能会遇到问题。

  2. 第二个问题与 priority 函数有关,因为如果您传递了条件中不期望的字符(例如例如字符串终止符)。您需要添加明确的else 子句。

【讨论】:

  • 在您的第一点中,我很有可能在这里出错,但是当我测试 strlen 语句时:char c = "123456789"; printf("%d", strlen(c)); 会显示 9,它是不包括终止符的长度,所以我看不到如何'\0' 将进入我的循环。请帮我看看。你的第二点,我相信你是对的,我现在正在努力。非常感谢!
  • @MizushimaHideyoshi 记住索引是从 0 开始的,所以字符串 "123456789" 的正确索引是 08(含)。
  • 哦,对了!这是一个基本错误。对不起,我很迟钝。感谢您清理它!
【解决方案2】:

循环

while(c[0] != '(')
   strcat(tempExp, c);

将无限期运行(假设 c[0] 不是 '('),超出字符串的大小(256 个字符),因为它会不断将相同的字符串 (c) 添加到 tempExp。这将导致无数错误,但通常是堆栈溢出或缓冲区溢出...未定义的行为仅在到达字符串末尾(256)时,从那时起它将不优雅地崩溃

【讨论】:

  • 就是这么简单!非常感谢你!我将 while 更改为 if,它现在可以工作了。
猜你喜欢
  • 2016-07-17
  • 1970-01-01
  • 1970-01-01
  • 2015-02-17
  • 2011-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多