11005:传感器批次汇总
题目
合并同一传感器的多条批次记录,检查计数溢出,计算错误率和平均延迟,并按传感器编号输出汇总结果。
解析
先检查全部记录,再复制并按 sensor_id 排序。相同编号随后会形成连续区间,因而只需一次线性扫描即可完成聚合。比较函数不能直接把两个无符号编号相减,否则差值转换为 int 时可能失真。
所有结果先写入临时数组。只有排序、容量检查、加法和内存申请全部成功后,才把临时结果复制给调用方并更新数量,从而满足失败时保持输出不变的约定。
解析
c
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
uint32_t sensor_id;
uint64_t sample_count;
uint64_t error_count;
uint64_t total_latency_us;
} SensorBatch;
typedef struct {
uint32_t sensor_id;
uint64_t sample_count;
uint64_t error_count;
uint64_t total_latency_us;
double error_rate;
double mean_latency_us;
} SensorSummary;
typedef enum {
SENSOR_SUMMARY_OK,
SENSOR_SUMMARY_INVALID,
SENSOR_SUMMARY_CAPACITY,
SENSOR_SUMMARY_OVERFLOW,
SENSOR_SUMMARY_OUT_OF_MEMORY
} SensorSummaryResult;
static int compare_sensor_id(
const void *left,
const void *right
) {
const SensorBatch *a = left;
const SensorBatch *b = right;
return (a->sensor_id > b->sensor_id)
- (a->sensor_id < b->sensor_id);
}
static bool add_u64(
uint64_t left,
uint64_t right,
uint64_t *out
) {
if (right > UINT64_MAX - left) {
return false;
}
*out = left + right;
return true;
}
SensorSummaryResult summarize_sensor_batches(
const SensorBatch batches[],
size_t batch_count,
SensorSummary summaries[],
size_t summary_capacity,
size_t *out_count
) {
if (out_count == NULL
|| (batch_count > 0 && batches == NULL)
|| (summary_capacity > 0 && summaries == NULL)) {
return SENSOR_SUMMARY_INVALID;
}
for (size_t i = 0; i < batch_count; ++i) {
if (batches[i].error_count
> batches[i].sample_count
|| (batches[i].sample_count == 0
&& batches[i].total_latency_us != 0)) {
return SENSOR_SUMMARY_INVALID;
}
}
if (batch_count == 0) {
*out_count = 0;
return SENSOR_SUMMARY_OK;
}
if (batch_count > SIZE_MAX / sizeof *batches) {
return SENSOR_SUMMARY_OUT_OF_MEMORY;
}
SensorBatch *sorted =
malloc(batch_count * sizeof *sorted);
if (sorted == NULL) {
return SENSOR_SUMMARY_OUT_OF_MEMORY;
}
memcpy(sorted, batches, batch_count * sizeof *sorted);
qsort(
sorted,
batch_count,
sizeof *sorted,
compare_sensor_id
);
size_t unique_count = 1;
for (size_t i = 1; i < batch_count; ++i) {
if (sorted[i].sensor_id != sorted[i - 1].sensor_id) {
++unique_count;
}
}
if (unique_count > summary_capacity) {
free(sorted);
return SENSOR_SUMMARY_CAPACITY;
}
if (unique_count > SIZE_MAX / sizeof *summaries) {
free(sorted);
return SENSOR_SUMMARY_OUT_OF_MEMORY;
}
SensorSummary *temporary =
malloc(unique_count * sizeof *temporary);
if (temporary == NULL) {
free(sorted);
return SENSOR_SUMMARY_OUT_OF_MEMORY;
}
size_t input_index = 0;
size_t output_index = 0;
while (input_index < batch_count) {
SensorSummary current = {
.sensor_id = sorted[input_index].sensor_id,
.sample_count = 0,
.error_count = 0,
.total_latency_us = 0,
.error_rate = 0.0,
.mean_latency_us = 0.0
};
while (
input_index < batch_count
&& sorted[input_index].sensor_id
== current.sensor_id
) {
uint64_t samples;
uint64_t errors;
uint64_t latency;
if (!add_u64(
current.sample_count,
sorted[input_index].sample_count,
&samples
)
|| !add_u64(
current.error_count,
sorted[input_index].error_count,
&errors
)
|| !add_u64(
current.total_latency_us,
sorted[input_index].total_latency_us,
&latency
)) {
free(temporary);
free(sorted);
return SENSOR_SUMMARY_OVERFLOW;
}
current.sample_count = samples;
current.error_count = errors;
current.total_latency_us = latency;
++input_index;
}
if (current.sample_count != 0) {
current.error_rate =
(double)current.error_count
/ (double)current.sample_count;
current.mean_latency_us =
(double)current.total_latency_us
/ (double)current.sample_count;
}
temporary[output_index++] = current;
}
memcpy(
summaries,
temporary,
unique_count * sizeof *temporary
);
*out_count = unique_count;
free(temporary);
free(sorted);
return SENSOR_SUMMARY_OK;
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191