进行for循环以编辑数据结构中的列表

时间:2019-03-08 00:33:30

标签: c data-structures

我要编写的代码应该由用户获取给定的数据,并将其放入一个数据结构中,该结构可以完美地工作。出问题的是,当我尝试删除条目时(if(choice == 2)。它所要做的就是将该条目取为空,但我不喜欢使用空格的想法。for循环我试图做的是获取最上面的条目,然后将所有内容向下移动,但是要做的就是获取第一个条目,然后将其复制到第二个条目,而其他的则留给其他人。将它们向下移动会很棒。

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

typedef struct  book  {     //This is the data structure
    char personName[15];
    char personLname[15];
    char phoneNumber[15];
    char null[4];
} Book;

static int loopValue;// this is going to loop the program forever until the 
    //loop is broke
main()
{

    int index = 0;
    int choice;
    Book *ptrBook = (Book*)malloc(sizeof(Book));
    int i,j;
    int stopValue = 1;

    while(stopValue=0)
    {
        printf("\t\tPhone Book Application\n");
        printf("\t1. Add Contact\t\t2. Remove Contact\n");
        printf("\t3. Show Contacts\t10. Exit\n");
        printf("\tChoice: ");
        scanf("%i",&choice);
        printf("\n\n");

        if(choice == 1)     // this is the add person, it takes the print if 
                /and puts it into the data structure
    {
        ptrBook = (Book*)realloc(ptrBook, sizeof(Book)*(index + 1));
        printf("What is the FIRST name: ");
        scanf("%s",ptrBook[index].personName);
        printf("What is the LAST name: ");
        scanf("%s",ptrBook[index].personLname);
        printf("What is the number: ");
        scanf("%s",ptrBook[index].phoneNumber);
        printf("\nAdded to the Phone Book.\n");
        printf("\nName: %s %s\n",ptrBook[index].personName, 
ptrBook[index].personLname);
        printf("Phone Number: %s",ptrBook[index].phoneNumber);
        index++;
    }
    else if (choice == 2)       // this removes people from the data 
                         //structure
    {
        loopValue == 0;
        printf("Who would you like to remove?\n\n");
        for(i=0;i<index;i++)        // this loops prints out the names to 
                               //choose from
        {

     printf("%i. %s %s\n",i+1,ptrBook[i].personName,ptrBook[i].personLname);
        }
        printf("Who would you like to remove? ");
        scanf("%i",choice);
        for(i=choice;i<0;i--)  //THIS IS WHAT NEED HELP WITH PLZ
        {                       //
            strcpy(ptrBook[i-2].personName,ptrBook[i-1].personName);    //
            strcpy(ptrBook[i-2].personLname,ptrBook[i-1].personLname);  //
            strcpy(ptrBook[i-2].phoneNumber,ptrBook[i-1].phoneNumber);  //
        }                   `//
        printf("\n");
        scanf("%i",&choice);
    }
    if(choice == 3)     // this loops to print out all the values in the 
                  //data structure
    {
        for(i=0;i<index;i++)
        {
            printf("%s %s\n",ptrBook[i].personName,ptrBook[i].personLname);
            printf("%i. %s\n\n\n",index,ptrBook[i].phoneNumber);
        }
    }
    else if(choice == 4)
    {
        //make code to sort names
    }
    else if(choice == 5)
    {
        //find a phone number for a given name
    }
    else if(choice == 6)
    {
        //random person for you to call
    }
    else if(choice== 7)
    {
        //delete everyone
    }
    else if(choice == 8)        // this exits the program by changing the 
                      //loop variable to something that makes the loop false
    {
        printf("Exiting");
        stopValue = 0;
    }
}
}

2 个答案:

答案 0 :(得分:0)

您的代码有很多问题。将来,请确保在发布问题之前彻底彻底清理代码。我花时间清理了很多东西,因为我讨厌自己,所以希望您能体谅。首先,一个错误列表:

1和2)您在while循环中的条件实际上是一个赋值:请在编译器上打开警告,因为它们将捕获类似这样的内容。您对stopValue的初始化也有误。

3)loopValue在整个代码中使用不一致,而不是控制while循环的东西。

4)在if (choice == 2)中,loopValue == 0表示将其与0进行比较,而不是将其设置为0。这对您的程序没有影响,但是您现在两次出现了=,==错误。那是您必须牢牢掌握的非常基本的东西。

5)在同一if部分中,设置choice的scanf在选择前没有&,这意味着该变量实际上不会设置为键入的值。

6)同一部分,最后的printf和scanf可能不存在吗?在任何情况下,它们都会使输入变得不直观,从而使该程序对没有源代码的任何人都无效。

7)如果不是if (choice == 3)

8)退出选项在源代码中为8,但菜单显示为10。

毕竟,这是代码(其中很多东西与您解决的问题没有任何关系)

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

typedef struct book {     //This is the data structure
    char personName[15];
    char personLname[15];
    char phoneNumber[15];
    char null[4];
} Book;

static int loopValue;
int main(void) {
    int index = 0;
    int choice;
    Book *ptrBook = (Book*) malloc(sizeof(Book));
    int i, j;
    int stopValue = 0; // was 1

    while (stopValue == 0) { // was =
        printf("\t\tPhone Book Application\n");
        printf("\t1. Add Contact\t\t2. Remove Contact\n");
        printf("\t3. Show Contacts\t8. Exit\n");
        printf("\tChoice: ");
        scanf("%i", &choice);
        printf("\n\n");

        if (choice == 1) {
            ptrBook = (Book*) realloc(ptrBook, sizeof(Book)*(index + 1));
            printf("What is the FIRST name: ");
            scanf("%s",ptrBook[index].personName);
            printf("What is the LAST name: ");
            scanf("%s",ptrBook[index].personLname);
            printf("What is the number: ");
            scanf("%s",ptrBook[index].phoneNumber);
            printf("\nAdded to the Phone Book.\n");
            printf("\nName: %s %s\n",ptrBook[index].personName,
            ptrBook[index].personLname);
            printf("Phone Number: %s",ptrBook[index].phoneNumber);
            index++;
        } else if (choice == 2) {
            loopValue = 0; // was ==
            printf("Who would you like to remove?\n\n");
            for (i = 0; i < index; i++) {
                printf("%i. %s %s\n", i+1, ptrBook[i].personName, ptrBook[i].personLname);
            }
            printf("Who would you like to remove? ");
            scanf("%d", &choice); // didn't have &
            for (int i = (choice - 1); i < (index - 1); i++) {
                ptrBook[i] = ptrBook[i + 1];
            }
            index--;
            // used to be redundant/confusing/wrong printf and scanf
        } else if (choice == 3) { // used to not be else if
            for (i = 0; i<index; i++) {
                printf("%s %s\n", ptrBook[i].personName, ptrBook[i].personLname);
                printf("%i. %s\n\n\n", index, ptrBook[i].phoneNumber);
            }
        } else if (choice == 8) { // Should've been 10
            printf("Exiting");
            stopValue = 1;
        }
    }
}

答案 1 :(得分:0)

您的代码有很多小问题,很难知道从哪里开始。可能最明显的是无法验证scanf的返回结果,以及您在每次输入后都没有清空stdin任何多余的字符,从而使程序仅等待在第一个错误处进入无穷循环击键。您不能使用"%s"转换说明符来读取名称(许多名称由两部分组成),并且您将在第一个空格处停止读取,并将其余名称用作下一个输入。读取电话号码也是如此(如果包含空格和标点符号,则会触发无限循环)。

对于所有面向行的输入(例如接受用户输入),提出了使用fgets而不是scanf的更大建议。您可以使用sscanf来解析输入中的整数值,并且可以避免使用scanf进行输入的新C程序员固有的许多陷阱。不要忽略缓冲区大小。例如,#define MAXC 1024然后char buf[MAXC];就足以满足大多数用户的输入。

接下来,在执行菜单时,请考虑使用switch () { case 1: ...; break; case 2: ...; break }而不是if (...) {...} else if (...) {...}, etc...的长链。它提供了更具可读性的代码;

您的代码有很多很多更正,下面的注释中对此进行了解释,例如

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

#define NULLSZ    4     /* if you need a constant #define one (or more) */
#define MAXNMNUM 15

typedef struct book {
    char personName[MAXNMNUM];  /* use constants for array sizes */
    char personLname[MAXNMNUM];
    char phoneNumber[MAXNMNUM];
    char null[NULLSZ];  /* no clue what this is for */
} Book;

/* helper function to empty extraneous characters from stdin */
void empty_stdin (void)
{
    int c = getchar();

    while (c != EOF && c != '\n')
        c = getchar();
}

int main (void) /* See http://port70.net/~nsz/c/c11/n1570.html#5.1.2.2.1p1 */
{
    int index = 0;
    Book *ptrBook = malloc (sizeof *ptrBook);  /* do NOT cast malloc return */

    for (;;) {      /* loop continually */
        int rtn,    /* return for scanf */
            choice = 0;
        /* you only need a single fputs - not muliple printf calls
         * there is no conversion taking place, so printf not neeeded.
         */
        fputs ( "\nPhone Book Application\n\n"
                " 1. Add Contact       2. Remove Contact\n"
                " 3. Show Contacts ... 8. Exit\n"
                "\nChoice: ", stdout);
        rtn = scanf ("%d", &choice);    /* ALWAYS VALIDATE EVERY INPUT */
        if (rtn == EOF) {   /* check if user canceled input with Ctrl+d */
            fputs ("(user canceled input)\n", stderr);
            break;
        }
        else if (rtn < 1) { /* check for matching or input failure */
            fputs ("error: invalid integer input.\n", stderr);
            empty_stdin();  /* always empty stdin before next input */
            continue;
        }
        empty_stdin();  /* ditto */

        if (choice == 1) {  /* add book */
            char *p;
            /* don't realloc every addition - very inefficient.
             * don't realloc the pointer itself, use a temp pointer
             * or you create memory leak on failure.
             */
            void *tmp = realloc (ptrBook, sizeof *ptrBook * (index + 1));
            if (!tmp) {
                perror ("realloc-ptrBook");
                break;
            }
            ptrBook = tmp;  /* assign new block to ptrBook */

            fputs ("What is the FIRST name: ", stdout);
            /* don't read line-oriented input with scanf, use fgets
             * if (scanf ("%s", ptrBook[index].personName) != 1) {
             */
            if (!fgets (ptrBook[index].personName, MAXNMNUM, stdin)) {
                fputs ("(user canceled input.)\n", stderr);
                break;
            }
            p = ptrBook[index].personName;  /* set convenience pointer */
            p[strcspn (p, "\r\n")] = 0;     /* trim '\n' from end of str */

            fputs ("What is the LAST name: ", stdout);
            if (!fgets (ptrBook[index].personLname, MAXNMNUM, stdin)) {
                fputs ("(user canceled input.)\n", stderr);
                break;
            }
            p = ptrBook[index].personLname; /* set convenience pointer */
            p[strcspn (p, "\r\n")] = 0;     /* trim '\n' from end of str */

            fputs ("What is the number: ", stdout);
            if (!fgets (ptrBook[index].phoneNumber, MAXNMNUM, stdin)) {
                fputs ("(user canceled input.)\n", stderr);
                break;
            }
            p = ptrBook[index].phoneNumber; /* set convenience pointer */
            p[strcspn (p, "\r\n")] = 0;     /* trim '\n' from end of str */

            printf ("\nAdded to the Phone Book.\n"
                    "\nName: %s %s\nPhone Number: %s\n", 
                    ptrBook[index].personName,
                    ptrBook[index].personLname, 
                    ptrBook[index].phoneNumber);

            index++;    /* increment index */
        }
        else if (choice == 2) {     /* remove entry */
            putchar ('\n');
            for (int i = 0; i < index; i++) {
                printf (" %d. %s %s\n", i + 1, ptrBook[i].personName,
                        ptrBook[i].personLname);
            }

            fputs ("\nWho would you like to remove? ", stdout);
            rtn = scanf ("%d", &choice);
            if (rtn == EOF) {
                fputs ("(user canceled input)\n", stdout);
                break;
            }
            else if (rtn < 1) {
                fputs ("error: invalid integer input.\n", stderr);
                empty_stdin();
                continue;
            }
            else if (choice - 1 < 0 || index - 1 < choice - 1) {
                fputs ("error: out of range of valid indexes.\n", stderr);
                empty_stdin();
                continue;
            }
            /* remvove entry with memmove copying over removed entry */
            memmove (ptrBook + choice - 1, ptrBook + choice,
                    (index - choice) * sizeof *ptrBook);
            index -= 1; /* decrement index */
            /* realloc to remove entry */
            void *tmp = realloc (ptrBook, index * sizeof *ptrBook);
            if (!tmp) {
                perror ("realloc-index");
                break;
            }
            ptrBook = tmp;
        }
        if (choice == 3) {  /* output the entries */
            putchar ('\n');
            for (int i = 0; i < index; i++) {
                printf ("%s %s\n%d. %s\n\n", ptrBook[i].personName,
                        ptrBook[i].personLname, i + 1, 
                        ptrBook[i].phoneNumber);
            }
        } else if (choice == 4) {
            //make code to sort names
        } else if (choice == 5) {
            //find a phone number for a given name
        } else if (choice == 6) {
            //random person for you to call
        } else if (choice == 7) {
            //delete everyone
        } else if (choice == 8) {
            printf ("Exiting\n");
            break;
        }
    }
}

注意:使用p作为临时指针只是为了方便和易于阅读,而不必键入,例如一遍又一遍的完整ptrBook[index].personLname并导致strcspn命令跨越多行)

另外,请考虑从结构中删除null(不知道这是什么意思),并考虑添加indexnentries作为成员,因此条目数始终是struct本身(在与其他函数之间传递或返回struct(或指向它的指针)时,使事情变得更加便利)

以下说明该程序现在如何从无效输入中恢复。在菜单上尝试输入与您的代码相同的内容,例如"I don't know",看看会发生什么...

使用/输出示例

$ ./bin/book_remove

Phone Book Application

 1. Add Contact       2. Remove Contact
 3. Show Contacts ... 8. Exit

Choice: I don't know
error: invalid integer input.

Phone Book Application

 1. Add Contact       2. Remove Contact
 3. Show Contacts ... 8. Exit

Choice: 1
What is the FIRST name: Mark
What is the LAST name: Twain
What is the number: (444) 555-1212

Added to the Phone Book.

Name: Mark Twain
Phone Number: (444) 555-1212

Phone Book Application

 1. Add Contact       2. Remove Contact
 3. Show Contacts ... 8. Exit

Choice: 1
What is the FIRST name: Samuel
What is the LAST name: Clements
What is the number: (444) 555-1213

Added to the Phone Book.

Name: Samuel Clements
Phone Number: (444) 555-1213

Phone Book Application

 1. Add Contact       2. Remove Contact
 3. Show Contacts ... 8. Exit

Choice: 1
What is the FIRST name: Won Hung
What is the LAST name: Lo
What is the number: (444) 555-1214

Added to the Phone Book.

Name: Won Hung Lo
Phone Number: (444) 555-1214

Phone Book Application

 1. Add Contact       2. Remove Contact
 3. Show Contacts ... 8. Exit

Choice: 1
What is the FIRST name: Fred
What is the LAST name: Flintstone
What is the number: (444) 555-1215

Added to the Phone Book.

Name: Fred Flintstone
Phone Number: (444) 555-1215

Phone Book Application

 1. Add Contact       2. Remove Contact
 3. Show Contacts ... 8. Exit

Choice: 3

Mark Twain
1. (444) 555-1212

Samuel Clements
2. (444) 555-1213

Won Hung Lo
3. (444) 555-1214

Fred Flintstone
4. (444) 555-1215


Phone Book Application

 1. Add Contact       2. Remove Contact
 3. Show Contacts ... 8. Exit

Choice: 2

 1. Mark Twain
 2. Samuel Clements
 3. Won Hung Lo
 4. Fred Flintstone

Who would you like to remove? 2

Phone Book Application

 1. Add Contact       2. Remove Contact
 3. Show Contacts ... 8. Exit

Choice: 3

Mark Twain
1. (444) 555-1212

Won Hung Lo
2. (444) 555-1214

Fred Flintstone
3. (444) 555-1215


Phone Book Application

 1. Add Contact       2. Remove Contact
 3. Show Contacts ... 8. Exit

Choice: 8
Exiting

仔细检查一下,确保您了解更改的内容和原因。如果没有,则要求进一步澄清。