结构实施建议

时间:2014-11-27 21:45:06

标签: c struct

我有一些非常基本的想法 struct 是什么以及它是如何工作的。

我的目标是使用结构创建一个考勤计划:

  • 输入:工人,他上班的时间,他离开的时间 - 他可以多次出发(例如午休)

  • 输出:每个最长的工人工作了多少小时,他是谁。

例如:

+ 8:00:00 100

+ 8:50:00 105

- 9:30:00 100

- 18:20:00 105

- 19:00:00 100

- 17:00:00 100

+ 18:00:00 100

+ 9:00:00 200

+ 10:00:00 100

- 15:00:00 200

输出:

Longest work time: 9:30:00 

Longest workers: 100, 105    

我最初的想法是以这种方式使用struct:

typedef struct work {
    int *arrivals;
    int *departures;
    int *result;
} WORK;
WORK 66, 100, 105, 200;    

然后我会为到达和离开动态分配记忆,对它们进行排序并比较arrival[i]departure[i]的元素。

问题在于元素(工作者)的数量可能会有所不同,您无法动态地将新元素添加到结构中。

那么我该如何改变结构以满足我的需求呢?

3 个答案:

答案 0 :(得分:2)

如果提前知道工作人员的数量,但一旦知道将被修复,则动态分配WORK的数组。除了你使用arrival结构而不是work结构之外,这将以与time完全相同的方式完成。

如果数字会随着时间的推移而改变,您可以使用realloc执行上述操作,但在需要时更改其大小,或使用更动态的结构(如链接列表)。 reallocmalloc类似,只是它需要一个指针&一个新的大小,并修改它指向的东西(可能移动它),使其成为新的大小。对于链接列表,您需要(至少)向struct添加一个字段,该字段是指向同一类struct的指针,用于告诉您列表中下一个项目的位置是

答案 1 :(得分:1)

正如您所看到的,有很多方法可以解决这个问题。主要的考虑归结为我如何处理我的结构?一个结构数组?或指向struct的指针数组?。两者都有优点和缺点。

选择结构数组的最大缺点是,您将承担跟踪与数组关联的所有索引以及每个结构中的时间数组的负担。通过允许您初始化指向NULL的指针块,选择指向struct 的指针数组会有所帮助。当你添加一个worker而不是NULL时,你的指针中有一个地址。这允许您使用简单的while (!NULL) {do stuff...}

遍历指针数组

第二个小问题是使用calloc而不是malloc。通过使用calloc,您可以初始化分配给zero/NULL的内存。这同样适用于结构数组结构指针数组。这提供了使用while (!NULL) {do stuff...}迭代的能力。 (索引与结构数组相关)

代码的其余部分应该是相当可读和直接的。在这里,我们定义一个INITWKR25,以在struct的初始指针块中分配。结构定义了一些其他成员,这些成员在工作人员中有用,计算时间最长。实际上,除了跟踪time in/time out之外,没有理由在每个worker的结构中存储一组值。在代码中,虽然(每个班次工作的分钟数)存储在每个结构的time数组中,但实际的date/time代码被省略。为了示例的目的,这只会使逻辑混乱。

当输入每个新worker时,为他分配一个新结构,指针值存储在struct的指针数组中。输入循环检查该名称是否已存在(具有结构),如果是,则添加额外时间并且不需要新的结构分配。在每次输入迭代期间,您需要检查是否已经耗尽了已分配的指针或已分配的时间数组,并根据需要realloc。我在代码中添加了注释并包含了必要的测试变量,但省略了重新分配代码以防止工作/时间逻辑混乱。

当输入循环完成时(只需点击[enter]而不是提供输入),将打印所有次工作的工作人员,并显示大部分时间的工作人员。< / strong>程序然后注意释放所有动态分配的内存,然后退出。

看一下,代码评论得相当好。如果您遇到困难,请发表评论。

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

#define INITWKR 25

typedef struct {
    char *name;         /* worker name      */
    int *time;          /* time array (min) */  /* optional     */
    unsigned entries;   /* entries in time  */
    unsigned size;      /* allocated size   */  /* realloc test */
    unsigned total;     /* total time (min) */
} worker;

int main () {

    char *name = NULL;  /* name input       */
    int tio = 0;        /* time input       */
    int idx = 0;        /* workers index    */
    int idxmax = 0;     /* index max time   */
    int tdx = 0;        /* time index       */
    int tmax = 0;       /* max worker time  */
    char exist = 0;     /* wkr exists flag  */
    int wkrsz = INITWKR;/* num of wkr ptrs  */

    /* create INITWKR pointers to struct (initialize NULL) */
    worker **wkrs = calloc (INITWKR, sizeof (*wkrs));

    printf ("\nPunch the clock, enter name & minutes worked ([enter] alone to end)\n");

    /* input loop, read name and minutes worked for each shift */
    while (printf ("\n  name: ") && scanf ("%m[^\n]%*c", &name) >= 1 &&
            printf ("  time: ") && scanf ("%d%*c", &tio) >= 1 )
    {
        idx = 0;            /* reset loop vars  */
        exist = 0;

        while (wkrs[idx])   /* check each filled worker */
        {
            /* check if already has struct  */
            if (strcmp (wkrs[idx]->name, name) == 0) {
                exist = 1;
                break;
            }
            idx++;          /* idx points to first avail pointer at end */
        }
        /* if (idx >= INITWKR - 1) reallocate poiner array */

        if (!exist) {
            /* add new worker */
            wkrs[idx] = malloc (sizeof (**wkrs));
            wkrs[idx]-> name = strdup (name);
            wkrs[idx]-> time = calloc (INITWKR, sizeof (int));
            wkrs[idx]-> entries = 0;
            wkrs[idx]-> size = INITWKR;
            wkrs[idx]-> total = 0;
        }

        /* add time to worker */
        tdx = 0;
        while ((wkrs[idx]-> time)[tdx])
            tdx++;
        /* if (tdx >= wkrs[idx]-> size - 1) reallocate wkrs[idx]-> time, increment size */
        (wkrs[idx]-> time)[tdx] = tio;
        wkrs[idx]-> entries++;
        wkrs[idx]-> total += tio;
        if (wkrs[idx]-> total > tmax) {
            tmax = wkrs[idx]-> total;
            idxmax = idx;
        }
    }

    if (name) free (name);  /* free memory allocated by scanf    */

    printf ("\nWorker Time Summary:\n\n");

    idx = 0;
    while (wkrs[idx]) {     /* output worker name/time & max    */
        if (idx == idxmax)
            printf ("  Worker[%2d] : %-24s   time: %d  (max time)\n", idx, wkrs[idx]->name, wkrs[idx]->total);
        else
            printf ("  Worker[%2d] : %-24s   time: %d\n", idx, wkrs[idx]->name, wkrs[idx]->total);
        idx++;
    }
    printf ("\n");

    idx = 0;
    while (wkrs[idx]) {     /* free dynamically allocated mem   */
        if (wkrs[idx]->name) free (wkrs[idx]->name);
        if (wkrs[idx]->time) free (wkrs[idx]->time);
        if (wkrs[idx]) free (wkrs[idx++]);
    }

    return 0;
}

示例:

$ ./bin/workers

Punch the clock, enter name & minutes worked ([enter] alone to end)

  name: JD Clark
  time: 38

  name: Mike Wu
  time: 34

  name: JD Clark
  time: 39

  name: Mike Wu
  time: 53

  name: JD Clark
  time: 64

  name: Tim Taylor
  time: 55

  name:

Worker Time Summary:

  Worker[ 0] : JD Clark                   time: 141  (max time)
  Worker[ 1] : Mike Wu                    time: 87
  Worker[ 2] : Tim Taylor                 time: 55

答案 2 :(得分:0)

我给你写了一些代码,告诉你这是怎么回事。想法是为workersarrivals / departures提供动态数组。

如果您知道如何为某个数组a动态分配内存,例如:

int *a;
a = (int*) malloc(100*sizeof(int));

然后你知道怎么用struct s:

来做
struct s_name *my_s; // s_name is some random name of structure
my_s = (s_name*) malloc(100*sizeof(s_name));

因此,您知道如何为结构内的某些数组分配内存。

以下是代码:

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

typedef struct {
  int h, m, s; // hour, minutes, seconds
} time;

typedef struct {
  time *arrival;
  time *departure;
  time result;

  int n_of_arrivals; // to keep track how many we have
  int n_of_departures;

} work;

work *workers;

int main(void) {
  int N;

  printf("How many entries do you have?\n> ");
  scanf("%d", &N);

  // initially create space for 100 workers
  workers = (work*) malloc(100*sizeof(work));
  int number_of_workers = 100;

  for (int n = 0; n < N; n++) {
    char event; // this is '+' or '-'
    int h, m, s, id;

    scanf(" %c %d:%d:%d%d", &event, &h, &m, &s, &id);

    // last position where we can put our worker is number_of_workers - 1
    if (id > number_of_workers - 1) {
      number_of_workers = id + 1;
      // realloc memory for storing workers
      workers = (work*) realloc(workers, number_of_workers*sizeof(work));
    }

    if (event == '+') {
      // add 1 to amount of arrivals
      workers[id].n_of_arrivals += 1;

      int len = workers[id].n_of_arrivals;

      // realloc memory for keeping arrivals of worker
      workers[id].arrival = (time*) realloc(workers[id].arrival, len*sizeof(time));

      // finally store new time
      time *arrival = workers[id].arrival;
      arrival[len - 1].h = h;
      arrival[len - 1].m = m;
      arrival[len - 1].s = s;
    } else {
      // this is the same as for adding arrivals
      workers[id].n_of_departures += 1;
      int len = workers[id].n_of_departures;
      workers[id].departure = (time*) realloc(workers[id].departure, len*sizeof(time));
      time *departure = workers[id].departure;
      departure[len - 1].h = h;
      departure[len - 1].m = m;
      departure[len - 1].s = s;
    }
  }

  for (int i = 0; i < number_of_workers; i++) {
    // skip worker who doesn't have track of any arrivalls or depratures
    if (!workers[i].n_of_arrivals && !workers[i].n_of_departures)
      continue;

    printf("Worker %d:\n", i);

    // print nicely arrivals
    if (workers[i].n_of_arrivals) {
      int len = workers[i].n_of_arrivals;
      printf("Arrivals:\n");
      for (int k = 0; k < len; k++)
        printf("%d:%d:%d\n", workers[i].arrival[k].h, workers[i].arrival[k].m, workers[i].arrival[k].s);
    }

    // // print nicely depratures
    if(workers[i].n_of_departures) {
      int len = workers[i].n_of_departures;
      printf("Departures:\n");
      for (int k = 0; k < len; k++)
        printf("%d:%d:%d\n", workers[i].departure[k].h, workers[i].departure[k].m, workers[i].departure[k].s);
    }

    printf("\n");
  }

  return 0;
}

我没有编写用于计算结果的算法。我会把它留给你。 :)