Это модификация моей предыдущей версии.
Мне нужен совет по улучшению алгоритма FIFO для двумерного массива, который я разработал на ANSI C.
Я написал код, который использует этот алгоритм в тестовых целях. Случайные числа помещаются в массив, пока все элементы не заполнятся. Затем программа спрашивает пользователя, какие числа необходимо ввести в 2D-массив, чтобы обновить его. Затем код удаляет самый старый массив, сдвигает все оставшиеся массивы на единицу вверх, а затем добавляет новый массив (как введенный пользователем).
Я прошу проверить код FIFO, fifo_algorithm
; окружающий код предназначен только для тестирования. Буду признателен за любые предложения, в которых используется только стандартный C.
код:
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
void random_num_input(void);
void print_random_num_input(void);
void print_new_array(void);
void fifo_algorithm(void);
int user_num[5] = { 0 };
uint16_t big_array[10][5] = { 0 };
uint16_t big_array_copy[10][5] = { 0 };
uint16_t array_print[1] = { 0 };
uint8_t count = 0;
int main()
{
random_num_input();
printf("These are the original numbers in the big array:n");
print_random_num_input();
while (count < 10)
{
printf("Please enter values to swap in:n");
for (int i = 0; i < 5; i++)
{
scanf("%d", &user_num[i]);
}
printf("nn");
fifo_algorithm();
count++;
}
}
//stores random numbers between 0-255 into big_array and big_array_copy
void random_num_input(void)
{
for (int j = 0; j < 10; j++)
{
for (int i = 0; i < 5; i++)
{
big_array[j][i] = rand() % 255;
}
}
}
//prints the random values within the big_array
void print_random_num_input(void)
{
for (int j = 0; j < 10; j++)
{
for (int i = 0; i < 5; i++)
{
array_print[0] = big_array[j][i];
printf("%d,", array_print[0]);
}
printf("n");
}
}
//This algorithm removes the oldest array in big_array_copy (element 9), shifts every
//element up by 1 and stores the user inputted array into element 0. Thus a fifo that updates
//the 2d array with the user input values every time
void fifo_algorithm(void)
{
for (int j = 0; j < 10; j++)
{
for (int i = 0; i < 5; i++)
{
big_array_copy[j][i] = big_array[j][i];
}
}
for (int k = 0; k < 5; k++)
{
big_array_copy[10 - 1][k] = 0;
}
for (int j = 9; j > 0; j--)
{
for (int i = 0; i < 5; i++)
{
big_array_copy[j][i] = big_array[j - 1][i];
}
}
for (int i = 0; i < 5; i++)
{
big_array_copy[0][i] = user_num[i];
}
print_new_array();
for (int j = 0; j < 10; j++)
{
for (int i = 0; i < 5; i++)
{
big_array[j][i] = big_array_copy[j][i];
}
}
}
//simply prints the new, updated values in big_array_copy
void print_new_array(void)
{
printf("These array values have been swapped:n ");
for (int j = 0; j < 10; j++)
{
for (int i = 0; i < 5; i++)
{
array_print[0] = big_array_copy[j][i];
printf("%d,", array_print[0]);
}
printf("n");
}
}
Спасибо
1 ответ
Хорошее форматирование
Хорошее использование (u)intN_t
типы
При печати используйте соответствующий описатель формата: printf("%" PRI16u , array_print[0]);
Избегайте голых магических чисел
Определите константы для гибкости и ясности
// int user_num[5] = { 0] };
//uint16_t big_array[10][5] = { 0 };
#define BIG_ARRAY_MAXJ 10
#define BIG_ARRAY_MAXI 5
int user_num[BIG_ARRAY_MAXI] = { 0 };
uint16_t big_array[BIG_ARRAY_MAXJ][BIG_ARRAY_MAXI] = { 0 };
Вместо 9
, использовать BIG_ARRAY_MAXJ - 1
, так далее.
Чтобы ответить на вопрос «Я мог бы записать макросы для имен 5 и 10, но я не видел, как это может быть выгодно», комментарий: использование именованных констант передает другим, в том числе и вам позже, взаимосвязь между множеством констант. и их индивидуальное значение.
Глобальные объекты
Как правило, гораздо лучше кодировать использование локальных объектов, чем глобальных.
Вместо
random_num_input(void)
Передайте указатель на массив и его размеры. Если VLA поддерживается:
random_num_input(int jn, int in, uint16_t a[j][i]) {
for (int j = 0; j < jn; j++) {
for (int i = 0; i < in; i++) {
a[j][i] = rand() % 256;
}
}
Индексирование массива
За большой массивы, рассмотрим size_t
вместо int
чтобы хорошо обрабатывать большие массивы. size_t
это Златовласка размер для определения размера и индексации массива: не слишком маленький, не слишком большой.
За большой массивы, вероятно, также необходимо переместить в выделенную память, а не в фиксированные размеры.
Комментарий / код отключен на 1.
rand() % 255
формирует ценности [0…254], нет [0…255].
// stores random numbers between 0-255 into big_array ...
big_array[j][i] = rand() % 255;
Учитывать
big_array[j][i] = rand() % 256;
// or
big_array[j][i] = (uint8_t) rand();
Копирование массивов
С массивами того же размера и типа, что и здесь, можно использовать memcpy()
.
// for (int j = 0; j < 10; j++) //
// for (int i = 0; i < 5; i++) {
// big_array_copy[j][i] = big_array[j][i];
// }
//}
// if known to be non-overlapping
memcpy(big_array_copy, big_array, sizeof big_array_copy);
// else
memmove(big_array_copy, big_array, sizeof big_array_copy);
Незначительный: более аккуратный принт
Подумайте о том, чтобы не печатать конечный ','
. Маленькая причина для глобального array_print[]
. Используйте правильный переносимый спецификатор
char *sep = "";
for (int i = 0; i < BIG_ARRAY_MAXI; i++) {
printf("%s%" PRI16u , sep, big_array_copy[j][i]);
sep = ",";
}
printf("n");
Спасибо за обзор. Хотя программисту проще писать memcpy, насколько он переносим или более эффективен, чем базовая реализация цикла for?
— ChrisD91
@ ChrisD91 Это портативный и более линейно эффективен для больших массивов. При рассмотрении эффективности лучше всего сосредоточить внимание на большой O и ясность кода, чем тратить слишком много усилий на линейные проблемы.
— chux — Восстановить Монику