首页 > 解决方案 > 如果 struct 中的字符大小为 30 或更大,则程序终止

问题描述

头文件 - 如果我将 char 大小从 30 更改为 20 或更少,代码可以正常工作,但如果它的 30 或更高,它不会在主代码中的第 5 种情况的 for 循环之后执行。

struct Data
{
    int Emp_id;
    char Emp_name[30];
    char Emp_city[30];
};

void input(struct Data emp[], int n)
{

    for (int i = 0; i < n; i++)
    {
        printf("enter employee id of %d employee: \n", i + 1);
        scanf("%d", &emp[i].Emp_id);

        fflush(stdin);
        printf("enter employee name of %d employee: \n", i + 1);
        gets(emp[i].Emp_name);

        fflush(stdin);
        printf("enter employee city of %d employee: \n", i + 1);
        gets(emp[i].Emp_city);
    }
}

主代码-添加函数在第 5 种情况下执行,如果头文件结构中的字符大小为 30 或更多,则循环停止。如果我少做一次迭代,那么代码也可以工作 - for(int i=n-5;i<n-1;i++) 但包括最后一次迭代会终止程序并且显示函数不执行。

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

void find(struct Data emp[], int n);
void sortid(struct Data emp[], int n);
void sortAlp(struct Data emp[], int n);
void count(struct Data emp[], int n);
void add(struct Data emp[], int n);
void display(struct Data emp[], int n);

int main(void)
{
    int n;
    int a;

    printf("enter the number of employees:\n");
    scanf("%d", &n);

    struct Data emp[n];

    input(emp, n);

    printf("enter the operation you want to perform:\n");
    printf("1 - to find employee record from employee id\n");
    printf("2 - to sort employee record on basis of employee id\n");
    printf("3 - to alphabetically sort array of characters\n");
    printf("4 - to count the number of employees in database\n");
    printf("5 - to add 5 more records\n");

    scanf("%d", &a);

    switch (a)
    {
    case 1:

        find(emp, n);

        break;

    case 2:
        sortid(emp, n);
        display(emp, n);
        break;

    case 3:
        sortAlp(emp, n);
        display(emp, n);
        break;

    case 4:
        count(emp, n);

        break;

    case 5:
        add(emp, n);

        break;
    }

    return 0;
}

void find(struct Data emp[], int n)
{
    int a;
    int count = 0;

    printf("Enter the employee id: ");
    scanf("%d", &a);

    for (int i = 0; i < n; i++)
    {
        if (a == emp[i].Emp_id)
        {
            printf("Employee id: %d\n", emp[i].Emp_id);
            printf("Employee name: %s\n", emp[i].Emp_name);
            printf("Employee city: %s\n", emp[i].Emp_city);
            count++;
        }
    }
    if (count == 0)
    {
        printf("Employee id does not exist");
    }
}

void sortid(struct Data emp[], int n)
{
    int temp;
    char temp2[30];
    char temp3[30];

    for (int i = 0; i < n; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            if (emp[i].Emp_id > emp[j].Emp_id)
            {

                temp = emp[i].Emp_id;
                emp[i].Emp_id = emp[j].Emp_id;
                emp[j].Emp_id = temp;

                strcpy(temp2, emp[i].Emp_name);
                strcpy(emp[i].Emp_name, emp[j].Emp_name);
                strcpy(emp[j].Emp_name, temp2);

                strcpy(temp3, emp[i].Emp_city);
                strcpy(emp[i].Emp_city, emp[j].Emp_city);
                strcpy(emp[j].Emp_city, temp3);
            }
        }
    }
}

void sortAlp(struct Data emp[], int n)
{
    int temp2;
    char temp[30];
    char temp3[30];

    for (int i = 0; i < n; i++)
    {
        for (int j = i + 1; j < n; j++)
        {
            if (emp[i].Emp_name[0] > emp[j].Emp_name[0])
            {
                strcpy(temp, emp[i].Emp_name);
                strcpy(emp[i].Emp_name, emp[j].Emp_name);
                strcpy(emp[j].Emp_name, temp);

                temp2 = emp[i].Emp_id;
                emp[i].Emp_id = emp[j].Emp_id;
                emp[j].Emp_id = temp2;

                strcpy(temp3, emp[i].Emp_city);
                strcpy(emp[i].Emp_city, emp[j].Emp_city);
                strcpy(emp[j].Emp_city, temp3);
            }
        }
    }
}

void count(struct Data emp[], int n)
{
    int k;

    for (int i = 0; i < n; i++)
    {
        k = i;
    }

    printf("number of employees: %d\n", k + 1);
}

void add(struct Data emp[], int n)
{
    n = n + 5;

    for (int i = n - 5; i < n; i++)
    {
        printf("enter employee id of %d employee: \n", i + 1);
        scanf("%d", &emp[i].Emp_id);

        fflush(stdin);
        printf("enter employee name of %d employee: \n", i + 1);
        gets(emp[i].Emp_name);

        fflush(stdin);
        printf("enter employee city of %d employee: \n", i + 1);
        gets(emp[i].Emp_city);
    }
    //Program stops here without executing display
    display(emp, n);
}

void display(struct Data emp[], int n)
{
    for (int i = 0; i < n; i++)
    {
        printf("employee id of %d employee: %d \n", (i + 1), emp[i].Emp_id);

        printf("employee name of %d employee: %s \n", (i + 1), emp[i].Emp_name);

        printf("employee city of %d employee: %s \n", (i + 1), emp[i].Emp_city);
    }
}

标签: arrayscstruct

解决方案


对数组大小的依赖是一个巧合,缓冲区溢出总是发生在第 5 种情况下。

在您的程序中,您读取,然后分配一个条目n数组。n以后的更改n,如果有的话(实际上没有,add更改副本的操作)不会更改数组大小。这样,add将数据写入数组,这是被禁止的,并且可能会使程序崩溃,或者更糟。

您需要的是动态内存分配,例如:

// create an array of n entries
struct Data *emp = malloc(n * sizeof(struct Data));

// grow it (or shrink) to new_n entries
emp = realloc(emp, new_n * sizeof(struct Data));
n = new_n;

// destroy it
free(emp);
emp = NULL; // safeguard, should be right after free

请注意,在增加数组时,您需要更改实际的empn在代码中使用的,而函数只获取副本(在 的情况下是指针的副本,而emp不是整个数组的副本)。因此,要么main在调用之前立即执行此操作add,要么将其更改为接受指向这些变量的指针,让它自己完成这项工作。


推荐阅读