我要编写的代码应该由用户获取给定的数据,并将其放入一个数据结构中,该结构可以完美地工作。出问题的是,当我尝试删除条目时(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;
}
}
}
答案 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
(不知道这是什么意思),并考虑添加index
或nentries
作为成员,因此条目数始终是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
仔细检查一下,确保您了解更改的内容和原因。如果没有,则要求进一步澄清。