C编程while循环和数组结构

时间:2015-02-13 18:28:14

标签: c arrays

所以我在这里有很多代码:

#include <stdio.h>   
#include <string.h>
#include <ctype.h>
#pragma warning(disable: 4996)
#define max 100
typedef enum { diploma, bachelor, master, doctor } education;

struct person {                    // a node to hold personal details
    char name[30];
    char email[30];
    int phone;
    education degree;

};

struct person directory[max];                // an array of structures, 100 entries
int tail = 0;                         // global variable

void flush();                         // forward declaration of functions
void branching(char c);
int insertion();
int print_person(int i);
int print_all();
int search_person();
int delete_person();


int main() {  // print a menu for selection
    char ch = 'i';

    ungetc('\n', stdin); // inject the newline character into input buffer

    do {
        printf("Enter your selection\n");
        printf("\ti: insert a new entry\n");
        printf("\td: delete an entry\n");
        printf("\ts: search an entry\n");
        printf("\tp: print all entries\n");
        printf("\tq: quit \n");

        flush();    // flush the input buffer. To be discussed later
        ch = tolower(getchar());
        branching(ch);
    } while (ch != 113);

    return 0;
}

void flush() {  // flush the input buffer. To be discussed later
    int c;
    do {
        c = getchar();
    } while (c != '\n' && c != EOF);
}


void branching(char c) {    // branch to different tasks
    switch (c) {
    case 'i':
        insertion();
        break;
    case 's':
        search_person();
        break;
    case 'd':
        delete_person();
        break;
    case 'p':
        print_all();
        break;
    case 'q':
        break;
    default:
        printf("Invalid input\n");
    }
}

int insertion() {    // insert a new entry at the end
    if (tail == max) {
        printf("There are no more places to insert.\n");
        return -1;
    }
    else {
        printf("Enter name, phone, email, degree:\n");
        scanf("%s", directory[tail].name);
        // &directory[tail].name is an array. No "&" is needed
        scanf("%d", &directory[tail].phone, sizeof(directory[tail].phone));
        scanf("%s", directory[tail].email);
        scanf("%s", &directory[tail].degree);
        tail++;
        printf("The number of entries = %d\n", tail);
        return 0;
    }
}

int print_person(int i) {
    // print all information one person in the directory
    printf("\n\nname = %s\n", directory[i].name);
    printf("email = %s\n", directory[i].email);
    printf("phone = %d\n", directory[i].phone);
    printf("degree = %s\n", &directory[i].degree);
    return 0;
}

int print_all() {
    // print all information each person in the contactbook
    int i;

    if (tail == 0) {
        printf("No entries found.");
    }
    else {
        for (i = 0; i < tail; i++) {
            print_person(i);
        }
    }

    return 0;
}

int search_person() {      // print phone and email via name
    char sname[30]; int  i;
    char *p = sname;

    printf("Please enter the name to be searched for:\n");
    scanf("%s", sname);     //sname is an array, no & needed

    for (i = 0; i<tail; i++)
        if (strcmp(p, directory[i].name) == 0) {
            print_person(i);
            return i;

        }

    printf("The name does not exist.\n");
    return -1;
}
int delete_person() {
    int i, k;
    k = search_person();
    if (k == -1) {
        printf("The name does not exist.\n"); return -1;
    }
    else {
        for (i = k; i<tail; i++) {
            strcpy(directory[i].name, directory[i + 1].name);
            directory[i].phone = directory[i + 1].phone;
            strcpy(directory[i].email, directory[i + 1].email);
            printf("The index deleted is: %d\n", k);
        }
        tail--;
        return k;
    }
}

我已经设法回答了我需要的几个问题,但我似乎无法找到其中两个。

问题:

  1. 进一步修改insert()函数,以便将新人插入到人员姓名的排序位置的目录(数组)中(保持数组中的数据按名称按升序排序)。

  2. 修改search_person()函数。使用while循环替换for循环,在循环中,使用指针操作而不是数组操作来迭代数组元素。

  3. 对于问题2,这是我必须修改的代码:

    int insertion() {    // insert a new entry at the end
        if (tail == max) {
            printf("There are no more places to insert.\n");
            return -1;
        }
        else {
            printf("Enter name, phone, email, degree:\n");
            scanf("%s", directory[tail].name);
            // &directory[tail].name is an array. No "&" is needed
            scanf("%d", &directory[tail].phone, sizeof(directory[tail].phone));
            scanf("%s", directory[tail].email);
            scanf("%s", &directory[tail].degree);
            tail++;
            printf("The number of entries = %d\n", tail);
            return 0;
        }
    }
    

    我完全不知道我应该在这做什么。我坐在这里查看代码,不知道如何处理它。甚至问题本身也让我感到困惑。

    对于问题3,要修改的代码是:

    int search_person() {      // print phone and email via name
        char sname[30]; int  i;
        char *p = sname;
    
        printf("Please enter the name to be searched for:\n");
        scanf("%s", sname);     //sname is an array, no & needed
    
        for (i = 0; i<tail; i++)
            if (strcmp(p, directory[i].name) == 0) {
                print_person(i);
                return i;
    
            }
    
        printf("The name does not exist.\n");
        return -1;
    }
    

    所以我认为我设法做了指针操作部分(虽然我不是100%确定我做得正确)。我感到困惑的是如何使用while循环来替换for循环。我尝试了几个while循环,但它总是说我搜索的“名称”不存在。

    如果有人能向我解释我应该如何处理这些问题,并向我解释我应该做些什么,这将是非常好的。谢谢!

3 个答案:

答案 0 :(得分:0)

第二个(for while循环)一个更容易。 我将向您展示将for循环转换为while循环的通用方法,并让您执行代码,因为您正在尝试学习如何执行此操作。这是循环的一个例子:

int x;
for(x = 0; x < 10; x++)
{
    //do stuff here
}

现在让我们做一个做同样事情的while循环:

int x;
x = 0;
while(x < 10)
{
    //do stuff here

    x++;
}

for循环有三个部分,初始化,条件和增量。

for( initialization condition incrementor

初始化仅在首次到达for循环时发生一次。

条件在第一次初始化之后完成,然后每次再次到达循环的顶部,以查看循环是否应该再次执行,或者应该被跳过。

每次循环执行一次后,增量器就会发生。

while循环只有一个条件。可以在while循环之前添加初始化,并且可以将增量函数添加为while循环中的最后一个。

对于您的第一个问题,按名称按字母顺序插入,您实际上必须移动数组中的其他内容。假设我们在数组中有四件事:

a e i o

现在说我们要添加g。我们需要先检查它应该去哪里。因此,我们逐个查看元素,如果我们要查看的元素应该在g之后,那么我们应该在我们正在查看的元素之前放入g。在这种情况下,我们会查看ae,然后当我们查看i时,我们就会知道g应该首先出现。所以我们知道我们希望g进入i所在的位置。要使该位置为空,我们必须将数组中的其他所有内容移动到右侧,或者朝向数组的尾部移动。我们必须从头开始做这件事。我们将o移动到更高的位置,并使其成为新的尾部。然后我们也将i翻过来。这意味着我们有一个带有间隙的数组(我将使用下划线表示空白点):

a e _ i o

现在我们可以在我们制作的空位中放出新元素。

a e g i o

然后去吧!现在只需要使用该算法并对其进行编码!如果您遇到麻烦,我会很乐意与您详细了解详情。

答案 1 :(得分:0)

对于问题3,你可以使用指针算法。

int search_person() {      // print phone and email via name
char sname[30]; int  i;
char *p = sname;

printf("Please enter the name to be searched for:\n");
scanf("%s", sname);     //sname is an array, no & needed

 i = 0;
 while(i<tale){

    if (strcmp(p, ((directory + i )->name)) == 0) {
        print_person(i);
        return i;}
     i++;

    }

printf("The name does not exist.\n");
return -1;

}

答案 2 :(得分:0)

您可以使用以下方法在插入后对directory数组进行排序。

void dir_copy(struct person* src, struct person* dest)
{
    // since you are using arrays inside person structs
    // if dynamic memory is used, copy each string separately
    memcpy(src,dest,sizeof(struct person));
    return;
}

void dir_sort(struct person* dir, int dir_size)
{
    struct person temp;
    int i,j;
    for (i = 0; i < dir_size; i++) {
        for (j = 0; j < dir_size - 1; j++) {
            if (strcmp(dir[j].name, dir[j + 1].name) > 0) {
                dir_copy(&temp,&dir[j]);
                dir_copy(&dir[j],&dir[j + 1]);
                dir_copy(&dir[j + 1],&temp);
            }
        }
    }
}

int insertion() {    // insert a new entry at the end
    if (tail == max) {
        printf("There are no more places to insert.\n");
        return -1;
    }
    else {
        printf("Enter name, phone, email, degree:\n");
        scanf("%s", directory[tail].name);
        // &directory[tail].name is an array. No "&" is needed
        scanf("%d", &directory[tail].phone);
        scanf("%s", directory[tail].email);
        scanf("%s", &directory[tail].degree);
        tail++;
        printf("The number of entries = %d\n", tail);
        dir_sort(&directory,tail);
        return 0;
    }
}

并使用

scanf("%d", &directory[tail].phone, sizeof(directory[tail].phone));

将抛出编译器警告

warning: too many arguments for format [-Wformat-extra-args]
         scanf("%d", &directory[tail].phone, sizeof(directory[tail].phone));
         ^

因为它们没有形成为scanf提供的字符串以匹配第三个参数,并且无论如何它不是变量。我觉得没有必要。

如果要打印枚举,请使用getter函数来获取字符串而不是模糊的整数变量。

const char* getDegreeName(enum education degree) 
{
   switch (degree) 
   {
      case diploma: return "diploma";
      case bachelor: return "bachelor";
      /* etc... */
   }
}

同样在获取度数值时使用setDegree来比较用户输入字符串并设置枚举,而不是将字符串读取为枚举值,这是不明智的。

如果您想使用while循环代替for查看其他答案或谷歌搜索,您将获得大量材料,

最后,在C中,数组变量只是一个const指针,因此您可以随时使用指针算法而不是使用数组表示。 这意味着, directory[i]*(directory*i)

相同