【问题标题】:Break out of this while loop跳出这个while循环
【发布时间】:2015-04-08 17:32:33
【问题描述】:

我同样从文本文件中读取:

George Washington, 2345678
John Adams, 3456789
Thomas Jefferson, 4567890
James Madison, 0987654
James Monroe, 9876543
John Quincy Adams, 8765432
Andrew Jackson, 7654321
Martin Van Buren, 6543210
William Henry Harrison, 5432109
John Tyler, 4321098

删除名称的功能有效,但是当它成功时, printf 语句将继续在命令窗口中循环。我尝试在循环结束时使用 break 语句,但这只会导致说找不到名称。有人可以提供任何见解吗?

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

//Creates node for holding student's information
struct node
{
    char name [50];
    int id;
    struct node *next;
}*head;

//Create Function Prototypes
void readDataFile ();
void insert(char *inName, char *inID);
void display(struct node *d);
int deleteID(int num);
void deleteName(char *delete_name);


//Main function
int main()
{
    //Declare variables
    int i, num, delete_id, id;
    char *name;
    char nameDelete [50];
    char nameInsert [50];
    struct node *n;

    //initialize link list
    head = NULL;

    //Read in file
    readDataFile();

    //Create list of operations utilized in program
    while (1)
    {
        printf("\nList Operations\n");
        printf("===============\n");
        printf("1.Insert\n");
        printf("2.Display\n");
        printf("3.Delete by ID\n");
        printf("4.Delete by Name\n");
        printf("5.Exit\n");
        printf("Enter your choice : ");

        if(scanf("%d", &i) <= 0)
        {
            printf("Enter only an Integer\n");
            exit(0);
        }
        else
        {
            switch(i)
            {
                case 1:
                    getchar();
                    printf("Enter the name to insert:");
                    scanf("%[^\n]s", nameInsert);
                    printf("\nEnter the ID associated with the name: ");
                    scanf("%d", &id);
                    break;
                case 2:
                    if (head == NULL)
                        printf("List is Empty\n");
                    else
                    {
                        printf("Elements in the list are:\n");
                    }
                    display(n);
                    break;
                case 3:
                    if(head == NULL)
                        printf("List is Empty\n");
                    else
                    {
                        printf("Enter the ID number to delete: ");
                        scanf("%d", &delete_id);
                    }

                    if(deleteID(delete_id))
                        printf("%d deleted successfully \n", delete_id);
                    else
                        printf("%d not found in the list\n", delete_id);
                    break;
                case 4:
                    getchar();
                    if(head == NULL)
                        printf("List is Empty\n");
                    else
                    {
                        printf("Enter name to delete: ");
                        scanf("%[^\n]s", nameDelete);
                        printf("Checking for name %s...\n", nameDelete);
                        printf("%s not found in the list\n", nameDelete);
                        deleteName(nameDelete);
                    }
                    break;
                case 5:
                    return 0;
                default:
                    printf("Invalid option\n");
            }
        }
    }
    return 0;
}

//Define the functions
//Function to delete by name
void deleteName(char *delete_name)
{
    //Create temporary and helper node
    struct node *temp, *helper;

    //Set temp equal to head
    temp = head;

    //Loop until the end of the list
    while(temp != NULL)
    {
        if(strcmp(temp->name, delete_name) == 0)
        {
            if(temp == head)
            {
                head = temp->next;
                free(temp);
                printf("Found %s!\n", delete_name);
                printf("%s deleted successfully\n", delete_name);
            }
            else
            {
                helper->next = temp->next;
                free(temp);
                printf("Found %s!\n", delete_name);
                printf("%s deleted successfully\n", delete_name);
            }
        }
        else
        {
            helper = temp;
            temp = temp->next;
        }
    }
break;
}

【问题讨论】:

  • 为什么不在deleteName() 中的while 循环内的if (temp == head) { … } else { … } 语句后面加上break;(或return;)?
  • 问题在于 while 循环条件。 temp 可能没有到达链表的末尾。更正以匹配逻辑
  • 能否请您说明您尝试将break 放置在何处?没有它,很难看出你为什么出错了。
  • 删除识别出的节点后需要break。! :)
  • 我实际上发现了哪里出错了。谢谢大家的见解!

标签: c function loops while-loop linked-list


【解决方案1】:

break 关键字将跳出最近的开关或循环。因此,你可以试试这个:

while(temp != NULL)
{
    if(strcmp(temp->name, delete_name) == 0)
    {
        if(temp == head)
        {
            head = temp->next;
            free(temp);
            printf("Found %s!\n", delete_name);
            printf("%s deleted successfully\n", delete_name);
            break;
        }
        else
        {
            helper->next = temp->next;
            free(temp);
            printf("Found %s!\n", delete_name);
            printf("%s deleted successfully\n", delete_name);
            break;
        }
    }
    else
    {
        helper = temp;
        temp = temp->next;
    }
}

另一种解决方案是在释放 temp 后将其设置为 NULL(无论如何这是一个好习惯,所以这可能是另一个想法)

【讨论】:

    【解决方案2】:

    请了解如何制作 MCVE (How to create a Minimal, Complete, and Verifiable Example?) 或 SSCCE (Short, Self-Contained, Correct Example) — 两个名称和链接代表相同的基本理念。

    这是从您的代码派生的 MCVE。我从deleteName() 的循环中添加了缺少的break;return;。我基本上完全重写了main(),但它运行良好:

    #include <assert.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    struct node
    {
        char name[50];
        int id;
        struct node *next;
    } *head;
    
    void deleteName(char *delete_name);
    
    int main(void)
    {
        struct node *n;
    
        head = NULL;
    
        head = malloc(sizeof(*head));
        assert(head != 0);
        strcpy(head->name, "Abraham Lincoln");
        head->id = 1;
        head->next = 0;
    
        n = malloc(sizeof(*n));
        strcpy(n->name, "George Washington");
        n->id = 2;
        n->next = head;
        head = n;
    
        n = malloc(sizeof(*n));
        strcpy(n->name, "John Adams");
        n->id = 3;
        n->next = head;
        head = n;
    
        deleteName("George Washington");
        deleteName("John Adams");
        deleteName("Abraham Lincoln");
    
        return 0;
    }
    
    void deleteName(char *delete_name)
    {
        struct node *temp, *helper = 0;
    
        temp = head;
    
        while (temp != NULL)
        {
            if (strcmp(temp->name, delete_name) == 0)
            {
                if (temp == head)
                {
                    head = temp->next;
                    free(temp);
                    printf("Found %s!\n", delete_name);
                    printf("%s deleted successfully\n", delete_name);
                }
                else
                {
                    helper->next = temp->next;
                    free(temp);
                    printf("Found %s!\n", delete_name);
                    printf("%s deleted successfully\n", delete_name);
                }
                return;  // The key change!
            }
            else
            {
                helper = temp;
                temp = temp->next;
            }
        }
    }
    

    这在 valgrind 和带有 GCC 4.9.1 的 Mac OS X 10.10.2 下干净利落地运行。

    Found George Washington!
    George Washington deleted successfully
    Found John Adams!
    John Adams deleted successfully
    Found Abraham Lincoln!
    Abraham Lincoln deleted successfully
    

    在创建 MCVE 时,学习如何残酷地去除不相关的代码非常重要。

    【讨论】:

      【解决方案3】:

      找到要删除的名称后,在 if 块末尾添加 return 语句

      void deleteName(char *delete_name)
      {
          //Create temporary and helper node
          struct node *temp, *helper;
      
          //Set temp equal to head
          temp = head;
      
          //Loop until the end of the list
          while(temp != NULL)
          {
              if(strcmp(temp->name, delete_name) == 0)
              {
                  if(temp == head)
                  {
                      head = temp->next;
                      free(temp);
                      printf("Found %s!\n", delete_name);
                      printf("%s deleted successfully\n", delete_name);
                  }
                  else
                  {
                      helper->next = temp->next;
                      free(temp);
                      printf("Found %s!\n", delete_name);
                      printf("%s deleted successfully\n", delete_name);
                  }
                  return; 
              }
              else
              {
                  helper = temp;
                  temp = temp->next;
              }
          }
      }
      

      您还打算如何表明该名称不是列表的一部分,而不是被发现和删除。您可以更改修改函数,使其在未在列表中找到名称时返回错误代码,然后用于指示该名称从未在列表中开头。

      【讨论】:

        【解决方案4】:
        I did not really look at the delete() function,
        however, the following code illustrates how the 
        code should be formatted, etc.
        
        notice the checking for input errors, which should always be performed
        notice the separation of the struct definition from the struct declaration
        notice the easy readability of the switch cases
            by incorporating some vertical white space
        notice the simple comments after the closing braces
        notice that no call to an action is performed if the linked list is empty
        
        
        
        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
        
        //define node for holding student's information
        struct node
        {
            char name [50];
            int id;
            struct node *next;
        };
        
        // create head pointer for linked list of student info
        // and initialize
        struct node *head = NULL;
        
        // Function Prototypes
        // note: if all these functions are only accessed within this file
        //       then they should be declared with the 'static' modifier
        void readDataFile (void);
        void insert (char *inName, char *inID);
        void display (struct node *d);
        void deleteID (int delete_ID);
        void deleteName (char *delete_name);
        
        
        //Main function
        int main()
        {
            //Declare local variables
            // notice use of meaningful names
            // notice, for readability and documentation, 
            //         only one variable declared per line
            int i;  // receives user menu selection input
            int idDelete;
            int idInsert;
            char nameDelete [50];
            char nameInsert [50];
            // struct node *n; // unused variable
            int done = 0; // used to exit when user enters '5'
        
        
        
            //Read in file
            readDataFile();
        
            //Create list of operations utilized in program
            while (!done)
            {
                printf("\nList Operations\n");
                printf("===============\n");
                printf("1.Insert\n");
                printf("2.Display\n");
                printf("3.Delete by ID\n");
                printf("4.Delete by Name\n");
                printf("5.Exit\n");
                printf("Enter your choice : ");
        
                if( 1 != scanf("%d", &i) )
                { // then, scanf failed
                    perror( "scanf for choice failed");
                    exit( EXIT_FAILURE );
                }
        
                // implied else, scanf successful
        
                switch(i)
                {
                    case 1:
                        int ch;
                        while(EOF != (ch = getchar()) && (ch != '\n'));
        
                        printf("Enter the name to insert:");
        
                        if( 1 != (scanf("%[^\n]s", nameInsert) ) )
                        { // then scanf failed
                            perror( "scanf for new student name failed");
                            exit( EXIT_FAILURE );
                        }
        
                        // implied else, scanf successful
        
                        printf("\nEnter the ID associated with the name: ");
        
                        if( 1 != (scanf("%d", &idInsert) ) )
                        { // then scanf failed
                            perror( "scanf for new student ID failed");
                            exit( EXIT_FAILURE );
                        }
        
                        // implied else, scanf successful
        
                        insert( nameInsert, idInsert );
                        break;
        
                    case 2:
                        if (head == NULL)
                            printf("List is Empty\n");
                        else
                        {
                            printf("Elements in the list are:\n");
                            display(n);
                        } // end if
                        break;
        
                    case 3:
                        if(head == NULL)
                            printf("List is Empty\n");
                        else
                        {
                            printf("Enter the ID number to delete: ");
        
                            if( 1 != (scanf("%d", &idDelete) ) )
                            { // then, scanf failed
                                perror( "scanf for ID to delete failed");
                                exit( EXIT_FAILURE );
                            } 
        
                            // implied else, scanf successful
        
                            deleteID(idDelete);
                        } // end if
                        break;
        
                    case 4:
                        int ch;
                        while(EOF != (ch = getchar()) && (ch != '\n'));
        
                        if(head == NULL)
                            printf("List is Empty\n");
                        else
                        {
                            printf("Enter name to delete: ");
        
                            if( 1 != (scanf("%[^\n]s", nameDelete) ) )
                            { // then, scanf failed
                                perror( "scanf for name to delete failed");
                                exit( EXIT_FAILURE );
                            }
        
                            // implied else, scanf successful
        
                            printf("Checking for name %s...\n", nameDelete);
        
                            deleteName(nameDelete);
                        } // end if
                        break;
        
                    case 5:
                        done = 1; // this will cause while() loop to exit
                        break;
        
                    default:
                        printf("Invalid option\n");
                        break;
                } // end switch
            } // end while
            return 0;
        } // end of function: main 
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-08-25
          • 2021-08-31
          • 2020-01-03
          • 2013-05-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多