微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

当我希望它返回到菜单时,为什么我的 Do-While 循环不断中断

如何解决当我希望它返回到菜单时,为什么我的 Do-While 循环不断中断

我希望当我为一个案例输入一个数字时,我的 do-while 循环不断重复。例如,如果我想在数组中插入一个元素,我会输入 1,然后我会输入我想要插入的元素和索引。然后它应该再次显示菜单,但由于某种原因,它只是跳出了 do-while 循环?

#include <iostream>
using namespace std;

struct Array
{
    int *A;
    int size;
    int length;
};

void display(struct Array *arr)
{
    int i;
    printf("\nElements: ");
    for(i = 0; i < arr->length; i++)
        printf("%d ",arr->A[i]);
};

struct Array *mergeArrays(struct Array *array1,struct Array *array2)
{
    int i = 0;
    int j = 0;
    int k = 0;

    struct Array *array3;

    int length = array1->length + array2->length;
    array3 = new Array[length];

    while(i < array1->length && j < array2->length)
    {
        if(array1->A[i] < array2->A[j])
        {   
            array3->A[k++] = array1->A[i++];
        }
        else
        {
            array3->A[k++] = array2->A[j++];
        }
    }

    for(; i < array1->length; i++)
        array3->A[k++] = array1->A[i];
    for(; j < array2->length; j++)
        array3->A[k++] = array2->A[j];

    array3->length = length;

    return array3;
};

struct Array *Union(struct Array *array1,struct Array *array2)
{
    int i = 0;
    int j = 0;
    int k = 0;

    struct Array *array3;

    int length = array1->length + array2->length;
    array3 = new Array[length];

    while(i < array1->length && j < array2->length)
    {
        if(array1->A[i] < array2->A[j]) {   
            array3->A[k++] = array1->A[i++];
        }
        else if(array2->A[j] < array1->A[i]){
            array3->A[k++] = array2->A[j++];
        } else {
            array3->A[k++] = array1->A[i++];
            j++;
        }
    }

    for(; i < array1->length; i++)
        array3->A[k++] = array1->A[i];

    array3->length = k;
    array3->size = 10;

    return array3;
};

struct Array *Intersection(struct Array *array1,struct Array *array2)
{
    int i = 0;
    int j = 0;
    int k = 0;

    struct Array *array3;

    int length = array1->length + array2->length;
    array3 = new Array[length];

    while(i < array1->length && j < array2->length)
    {
        if(array1->A[i] < array2->A[j]) {
            i++;
        } else if(array2->A[j] < array1->A[i]) {
            j++;
        } else {
            array3->A[k++] = array1->A[i++];
            j++;
        }
    }

    array3->length = k;
    array3->size = 10;

    return array3;
};

struct Array *Difference(struct Array *array1,struct Array *array2)
{
    int i = 0;
    int j = 0;
    int k = 0;

    struct Array *array3;

    int length = array1->length + array2->length;
    array3 = new Array[length];

    while(i < array1->length && j < array2->length)
    {
        if(array1->A[i] < array2->A[j]) {   
            array3->A[k++] = array1->A[i++];
        }
        else if(array2->A[j] < array1->A[i]){
            j++;
        } else {
            i++;
            j++;
        }
    }

    for(; i < array1->length; i++)
        array3->A[k++] = array1->A[i];

    array3->length = k;
    array3->size = 10;

    return array3;
};

int Delete(struct Array *array1,int index)
{
    int x = 0;
    int i = 0;

    if(index >= 0 && index < array1->length)
    {
        x = array1->A[index];
        for(i = index; i < array1->length-1; i++)
            array1->A[i] = array1->A[i+1];
        array1->length--;
    }
    return x;
};

void Append(struct Array *array1,int value)
{  
    if(array1->length < array1->size)
        array1->A[array1->length++] = value;
};

void Insert(struct Array *array1,int index,int element)
{   
    int i;
    if(index >= 0 && index <= array1->length)
    {
        for(i = array1->length; i > index; i--)
            array1->A[i] = array1->A[i-1];

        array1->A[index] = element;
        array1->length++;
        
    }
}

bool Search(struct Array *array1,int element)
{
    for(size_t i{0}; i < array1->length; i++) {
        if(array1->A[i] == element)
            return true;
    }
    return false;
};

void Sum(struct Array array1)
{
    int arraySum = 0;

    for(int i{0}; i < array1.length; i++)
    {
        arraySum+=array1.A[i];
    }

    cout << arraySum << endl;
}


int main()
{
    int index;
    int x;
    int ch;

    struct Array array1;
    printf("Enter Size Of Array: ");
    scanf("%d",&array1.size);
    array1.A=(int *)malloc(array1.size*sizeof(int));

    do
    {
    printf("display Menu\n");
    printf("1. Insert\n");
    printf("2. Delete\n");
    printf("3. Search\n");
    printf("4. Sum\n");
    printf("5. display\n");
    printf("6. Exit \n");

    printf("Enter Your Choice: ");
    scanf("%d",&ch);

    switch(ch)
    {
        case 1: printf("Enter Element First And Then Index: ");
            scanf("%d%d",&x,&index);
            Insert(&array1,index,x);
            break;

        case 2: printf("Enter Index To Be Deleted: ");
            scanf("%d",&index);
            x = Delete(&array1,index);
            printf("Deleted Element is %d|n",x);
            break;

        case 3: printf("Enter Element To Be Searched: ");
            scanf("%d",x);
            x = Search(&array1,x);
            break;

        case 4: printf("Array Sum: ");
            Sum(array1);
            break;
        
        case 5: display(&array1);
    }
    } while(ch < 6);
      return 0;
}

解决方法

首先,不要将输入与 std::cin 和 C scanf() 混合在一起,这只会导致灾难。选择 C++ iosteam 或 C stdio.h,但不能同时选择两者。无论您选择哪个,都由您来验证每个输入,方法是检查输入函数的返回 .在 C++ 中,您正在检查流状态,在 C 中,您正在验证函数返回。在 C 和 C++ 都失败的情况下,遇到错误时会停止从输入流中提取字符。在尝试下一次输入之前,由您来处理错误并从输入流中提取有问题的字符(在 C++ 中,您还必须 .clear() 流状态)

接受用户输入

如果您使用 scanf(),您将:

        if (scanf ("%d",&ch) != 1) {    /* validate EVERY input */
            fputs ("  error: invalid integer input.\n",stderr);
            empty_stdin();              /* on invalid input,you must empty stdin */
            continue;
        }

辅助函数 empty_stdin() 的写法如下:

void empty_stdin (void)
{
    int c = getchar();
    
    while (c != '\n' && c != EOF)
        c = getchar();
}

注意:这适用于您程序中的每个输入...如果您使用 C 输入,请考虑使用 fgets() 将所有输入读入固定数组并解析所需的值从带有 sscanf() 的数组中。这消除了在匹配失败的情况下留在输入流中的有问题的字符的可能性。)

在 C++ 中使用 iostream,您可以:

        if (!(std::cin >> ch)) {    /* validate EVERY input,handle error */
            std::cerr << "  error: invalid integer input.\n";
            std::cin.clear();   /* clear failbit steam state */
            /* empty offendinding characters from stdin */
            std::cin.ignore (std::numeric_limits<std::streamsize>::max(),'\n');
            continue;
        }

其中提供 std::cin.ignore() 用于清除带有 std::numeric_limits 中提供的 limits 的违规字符。

new 还是 malloc()?

在 C++ 中使用 malloc() 时必须非常小心。例如,在 C++ 中使用 stuct 分配 malloc() 将失败。 malloc() 对对象构造函数一无所知,因此如果在 C++ 中使用 struct Arraymalloc() 分配,最终会得到一个部分构造的对象。在分配对象时,在 C++ 中使用 newdelete 而不是 malloc()free()。您的老师不应该鼓励在 C++ 中使用 malloc()

您可以使用 array1.Amalloc() 有效分配的唯一原因是 A 是指向 int 的普通旧指针。没有与为 int 分配存储相关联的构造函数,因此在这种情况下允许(但不明智)使用 malloc()。然后问题就变成记住你用 malloc() 分配的内容和你用 new 分配的内容,因为 free()delete 不能互换。

你做的 { ... } while();循环

从表面上看,没有任何理由您的 do 循环不会执行您预期的操作——只要每个输入都是完美的。然而,一个错误的字符或一个手指从钥匙上滑落,你的整个易碎卡片屋就会崩溃。如果用户滑向 '4' 并点击 'r' 会发生什么? (真的很糟糕)。如果您退出任何大于 default: 的有效整数(您不能),您如何处理 5 情况以通常处理错误。

通过使用 while (ch < 6); 控制循环,您可以消除默认情况下可以提供的所有错误处理。如果您想在 6 上退出,请创建一个 case 6: 并使用它来控制退出循环。然后你可以循环 while (true);do { ... } while (true);

无论您使用 C stdio.h 还是 C++ iostream,都没有理由为了显示您的菜单而进行八个单独的函数调用。您需要一次呼叫 fputs()std::cout。为什么?在编译期间,编译器会将所有相邻的字符串文字连接成一个字符串。因此,您可以将菜单显示为:

        fputs ("\nDisplay Menu\n"
               "  1. Insert\n"
               "  2. Delete\n"
               "  3. Search\n"
               "  4. Sum\n"
               "  5. Display\n"
               "  6. Exit \n\n"
               "Enter Your Choice: ",stdout);

        std::cout << "\nDisplay Menu\n"
                     "  1. Insert\n"
                     "  2. Delete\n"
                     "  3. Search\n"
                     "  4. Sum\n"
                     "  5. Display\n"
                     "  6. Exit \n\n"
                     "Enter Your Choice: ";

(它也更容易阅读...)

C++ 使用 C malloc() 和 stdio.h

考虑到这些修复并删除所有未使用的函数,您可以使用 struct Arraymalloc()stdio.h I/O 函数编写 C++ 代码,您可以:

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

struct Array {
    int *A,size,length;
};

void display (struct Array *arr)
{
    int i;
    
    fputs ("\nElements: ",stdout);
    
    for(i = 0; i < arr->length; i++)
        printf (i ? " %d" : "%d",arr->A[i]);
    putchar ('\n');                             /* tidy up with newline */
}


int Delete (struct Array *array1,int index)
{
    int x = 0;
    int i = 0;

    if (index >= 0 && index < array1->length)
    {
        x = array1->A[index];
        for(i = index; i < array1->length-1; i++)
            array1->A[i] = array1->A[i+1];
        array1->length--;
    }
    
    return x;
}

void Insert(struct Array *array1,int index,int element)
{   
    int i;
    if(index >= 0 && index <= array1->length)
    {
        for(i = array1->length; i > index; i--)
            array1->A[i] = array1->A[i-1];

        array1->A[index] = element;
        array1->length++;
        
    }
}

bool Search(struct Array *array1,int element)
{
    for(int i = 0; i < array1->length; i++) {
        if(array1->A[i] == element)
            return true;
    }
    return false;
}

void Sum(struct Array array1)
{
    int arraySum = 0;

    for(int i = 0; i < array1.length; i++)
    {
        arraySum+=array1.A[i];
    }

    printf ("%d\n",arraySum);
}

void empty_stdin (void)
{
    int c = getchar();
    
    while (c != '\n' && c != EOF)
        c = getchar();
}

int main (void)
{
    int index,x,ch;
    struct Array array1;
    
    fputs ("Enter Size Of Array: ",stdout);
    if (scanf("%d",&array1.size) != 1) {                   /* validate EVERY input */
        fputs ("error: invalid integer input.\n",stderr);
        return 1;
    }
    
    /* you cannot MIX malloc & new,you do not cast malloc in C,you do in C++ */
    array1.A = (int *)malloc(array1.size*sizeof(int));
    
    if (!array1.A) {    /* validate EVERY allocation using malloc */
        perror ("malloc-array1.A");
        return 1;
    }

    do
    {
        fputs ("\nDisplay Menu\n"
               "  1. Insert\n"
               "  2. Delete\n"
               "  3. Search\n"
               "  4. Sum\n"
               "  5. Display\n"
               "  6. Exit \n\n"
               "Enter Your Choice: ",stdout);
        
        if (scanf ("%d",you must empty stdin */
            continue;
        }
    
        switch(ch)
        {
            case 1: fputs ("Enter Element First And Then Index: ",stdout);
                if (scanf ("%d %d",&x,&index) != 2) {
                    fputs ("  error: invalid element or index.\n",stderr);
                    empty_stdin();
                    continue;
                }
                Insert (&array1,index,x);
                break;
    
            case 2: fputs ("Enter Index To Be Deleted: ",stdout);
                if (scanf ("%d",&index) != 1) {
                    fputs ("  error: invalid index to delete.\n",stderr);
                    empty_stdin();
                    continue;
                }
                x = Delete (&array1,index);
                printf ("Deleted Element is %d\n",x);
                break;
    
            case 3: printf ("Enter Element To Be Searched: ");
                if (scanf ("%d",&x) != 1) {
                    fputs ("  error: invalid search element.\n",stderr);
                    empty_stdin();
                    continue;
                }
                if (Search (&array1,x)) 
                    puts ("element found.");
                else
                    puts ("element not found.");
                break;
    
            case 4: fputs ("Array Sum: ",stdout);
                Sum (array1);
                break;
            
            case 5: display (&array1);
                break;
            
            case 6: puts ("\nend program");
                return 0;
                break;
            /* always provide a default case to catch invalid case requests */
            default: fputs ("  error: invalid selection.\n",stderr);
                break;
        }
    } while (1);
    
    free (array1.A);        /* don't forget to free the memory you allocate */
    
    return 0;
}

您使用 C++ 和 std::vector 的代码

您的老师没有教您在 C++ 中使用 stdio.hmalloc()。是的,那是 90 年代初期的 C++,当时 C++ 是 C 的超集,但今天,C++ 本身就是一种语言,无需依赖其大部分 C 基础。没有理由使用 struct Array 持有指向 int*sizelength 的指针,std::vector 提供了所有这些功能(以及更多).

使用 std::vector<int> 替换您的 struct Array,您可以如下简化和改进您的程序:

#include <iostream>
#include <string>
#include <vector>
#include <limits>

void display (std::vector<int>& arr)
{
    std::cout << "\nElements: ";
    
    for (int a : arr)
        std::cout << " " << a;
    std::cout.put ('\n');
}

void Delete (std::vector<int>& arr,size_t index)
{
    arr.erase (arr.begin() + index);
}

void Insert (std::vector<int>& arr,int element,size_t index)
{   
    if (index <= arr.size()) {
        arr.insert (arr.begin() + index,element);
    }
    else {
        std::cerr << "  error: index out of range,appending element.\n";
        arr.push_back (element);
    }
}

bool Search (std::vector<int>& arr,int element)
{
    for (int a : arr)
        if (a == element)
            return true;
    
    return false;
}

void Sum (std::vector<int>& arr)
{
    int arraySum = 0;

    for (int a : arr)
    {
        arraySum += a;
    }

    std::cout << arraySum << '\n';
}

int main (void)
{
    int ch = 0,x = 0;
    size_t ndx = 0;
    std::vector<int> array1{};
    
    do
    {
        std::cout << "\nDisplay Menu\n"
                     "  1. Insert\n"
                     "  2. Delete\n"
                     "  3. Search\n"
                     "  4. Sum\n"
                     "  5. Display\n"
                     "  6. Exit \n\n"
                     "Enter Your Choice: ";
        
        if (!(std::cin >> ch)) {    /* validate EVERY input,'\n');
            continue;
        }
    
        switch (ch)
        {
            case 1: std::cout << "Enter Element and index: ";
                /* validate EVERY input,handle error */
                if (!(std::cin >> x >> ndx)) {
                    std::cerr << "  error: invalid input for insert.\n";
                    std::cin.clear();   /* clear failbit steam state */
                    /* empty offendinding characters from stdin */
                    std::cin.ignore (std::numeric_limits<std::streamsize>::max(),'\n');
                    continue;
                }
                Insert (array1,ndx);
                break;
    
            case 2: std::cout << "Enter Index To Be Deleted: ";
                if (!(std::cin >> ndx)) {  /* validate EVERY input,handle error */
                    std::cerr << "  error: invalid index input to delete.\n";
                    std::cin.clear();   /* clear failbit steam state */
                    /* empty offendinding characters from stdin */
                    std::cin.ignore (std::numeric_limits<std::streamsize>::max(),'\n');
                    continue;
                }
                if (ndx < array1.size()) {
                    x = array1[ndx];                /* index < size */
                    std::cout << "Deleted Element is " << x << '\n';
                    Delete (array1,ndx);
                }
                else {  /* ndx not a valid index */
                    std::cerr << "  error: invalid index.\n";
                }
                break;
    
            case 3: std::cout << "Enter Element To Be Searched: ";
                if (!(std::cin >> x)) {    /* validate EVERY input,handle error */
                    std::cerr << "  error: invalid integer input to search.\n";
                    std::cin.clear();   /* clear failbit steam state */
                    /* empty offendinding characters from stdin */
                    std::cin.ignore (std::numeric_limits<std::streamsize>::max(),'\n');
                    continue;
                }
                if (Search (array1,x)) 
                    std::cout << "element found.\n";
                else
                    std::cout << "element not found.\n";
                break;
    
            case 4: std::cout << "Array Sum: ";
                Sum (array1);
                break;
            
            case 5: display (array1);
                break;
            
            case 6: std::cout << "\nend program\n";
                return 0;
                break;
            /* always provide a default case to catch invalid case requests */
            default: std::cerr << "  error: invalid selection.\n";
                break;
        }
    } while (true);
}

评论中还包含并指出了一些其他更改,但基本上,除了了解过去的工作方式之外,您还想将 C++ 学习集中在当今 C++ 的使用方式上。否则,学习 C 将涵盖您在问题中发布的全部内容。

检查一下,如果您还有其他问题,请告诉我。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。