【问题标题】:Why continue causes undefined behavior为什么继续会导致未定义的行为
【发布时间】:2021-09-01 10:52:45
【问题描述】:

我用 C 语言创建了一个程序,它从文件中读取单词并将它们存储到一个链表中,但我注意到第二个 continue 会导致未定义的行为 为什么会这样?

有3个功能

第一个函数创建的列表很好

第二个函数用数据填充列表

第三个显示列表的内容

当我运行程序时,会调用未定义的行为

文件:https://gist.github.com/up1047388/b3018bc2a1fb0d66e86855a0d54baf63

我的代码:

    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    typedef struct node {
        char str[50];
        struct node *next;
    }Node;
    
    void createList(Node ** head , int len )
    {   int i=0;
        Node **lpp ;
        Node *komvos ;
        Node *komvos1;
        komvos = (Node*)malloc(sizeof(Node));
        komvos -> next = NULL;
        lpp=&komvos;
        for(i=1 ; i < len ; i++)
        {
            komvos1 = (Node*)malloc(sizeof(Node));
            komvos1 -> next = NULL;
            (*lpp) -> next = komvos1;
            lpp = &(*lpp) -> next;
        }
        
        *head = komvos ;
    }
    
    void FileList(FILE *fp  , Node *head) 
    {   char c;
        char tempStr[50];
        char str[50];
        int i = 0 , j = 0;
        Node **lpp;
        lpp=&head;
        
    for(c=fgetc(fp) ; c!=EOF ; c=fgetc(fp))
    {
        str[j]=c;
        j++;
        }   
    str[j]='\0';    
    j=0;    
    
    while(str[j]!='\0')  
    {   
        
        if (str[j] == ' ')
        {
            if (i == 0)
            {
                continue;
            }
            
            tempStr[i] = '\0';
            i = 0;
            
            
             strcpy((*lpp) -> str , tempStr);
             
             lpp = &(*lpp)  -> next ;       
            
            //continue  //This continue caused the problem
        }
        
        tempStr[i] = str[j];
        i++;
        j++;
        
        
    }   
        
    }
    
    void printList(Node *head)
    {
        Node *temp;
        temp = head;
        for(;temp!=NULL;temp=temp->next)
        {
            printf("\nthe words are  : %s", temp -> str);
        }
        
    }
    
    
    int main ()
    {   
    
        Node *head ;
        head = NULL;
        FILE *fp;
        fp = fopen ("lists4.txt","r+");
        if (fp==NULL)
        {
            printf("the file is broken");
            exit(8);
        }
        
        createList(&head , 3);
        FileList(fp,head);
        printList(head);
        
        return 0;
}

【问题讨论】:

  • 为什么只为一行提供外部链接?请直接将其粘贴到您的问题中。
  • 注释的continue 会将循环变成无限循环,因为j 在此之前没有更新。
  • 我很好奇:“导致未定义的行为”是什么意思?您是否收到包含这些单词的错误消息? (我知道未定义的行为是什么,但在这样的问题中看到它是不寻常的。它通常出现在答案中。)
  • @vg-png 可能是逻辑错误。无限循环本身并没有错。
  • 这里没有 UB,至少没有 continue; - 如果您尝试迭代字符串而不增加索引。

标签: c file linked-list continue


【解决方案1】:

注释掉的continue 将使循环无限运行,因为它会阻止j 被更新。

为避免这种情况,请在 str[j] == ' ' 案例中的 continue 之前添加更新 j 的代码。

    while(str[j]!='\0')
    {
        
        if (str[j] == ' ')
        {
            j++; /* add this to update j */
            if (i == 0)
            {
                continue;
            }
            
            tempStr[i] = '\0';
            i = 0;
            
            strcpy((*lpp) -> str , tempStr);
            
            lpp = &(*lpp)  -> next ;
            
            continue;  /* and then turn on the continue */
        }
        
        tempStr[i] = str[j];
        i++;
        j++;
        
    }

在这种情况下,我更喜欢使用if-else

    while(str[j]!='\0')
    {
        
        if (str[j] == ' ')
        {
            j++;
            if (i == 0)
            {
                continue;
            }
            
            tempStr[i] = '\0';
            i = 0;
            
            strcpy((*lpp) -> str , tempStr);
            
            lpp = &(*lpp)  -> next ;
        }
        else
        {
            tempStr[i] = str[j];
            i++;
            j++;
        }
        
    }

【讨论】:

  • 在第一个版本中你添加j++ 来更新它我明白这一点但是在第二个版本中你为什么使用j++; (没有引起问题的继续)
  • @vg-png j++; 用于完全相同的原因:让它移动到下一个元素进行处理。
  • 作为for 循环可能会更好,j++ 作为迭代表达式。这样j++ 会在每次迭代结束时执行,无论它是通过continue; 完成还是到达块的末尾,您不必在两条路径中复制它。
猜你喜欢
  • 2014-10-10
  • 2012-01-08
  • 1970-01-01
  • 2016-07-18
  • 2014-08-11
  • 2016-09-04
  • 1970-01-01
  • 2011-11-21
  • 1970-01-01
相关资源
最近更新 更多