我目前正试图为基于AVR的步进电机控制器构建一个字符串解析器.这个 idea 是观察一个输入字符串在MIDI上,然后将这个字符串分解成几个子缓冲区,最终将找到他们的方式进入一组运动控制行为.考虑以下分隔符:

'<' - START
'%' - CHANGE BUFFER
'>' - STOP
'A' - Clockwise
'B' - Counterclockwise

我会取一个有点任意宽的字符串,看起来像1234A%7743B,然后把它变成"马达1顺时针方向1234步,马达B逆时针方向7743步".<>

到目前为止,我已经提出了以下解决方案

#include <stdio.h>
#include <stdint.h>

#define TARGET 12

typedef struct 
{
    uint8_t STRING_SEL;

    char  X    [32]; // buffer X
    char  Y    [32]; // buffer Y
    uint8_t  iX; // buffer X iterator
    uint8_t  iY; // buffer Y iterator
    uint8_t  PTR_CTR;

    char* Xptr; // pointer to buffer X
    char* Yptr; // pointer to buffer Y

    uint8_t * iXptr; // pointer to buffer X iterator
    uint8_t * iYptr; // pointer to buffer Y iterator

    char ** PTR_ARR [2];   //pointer to array of buffer initial value pointers
    uint8_t ** CTR_ARR[2]; //pointer to array of buffer iterator pointers

} parser_manager;

static parser_manager mgr =  {
                              .STRING_SEL = 0,
                              .X          = {[0 ... 31] = 0},
                              .Y          = {[0 ... 31] = 0},
                              .iX         = 0,
                              .iY         = 0,
                              .PTR_CTR    = 0,
                              .Xptr       = &mgr.X[0],
                              .Yptr       = &mgr.Y[0],
                              .iXptr      = &mgr.iX,
                              .iYptr      = &mgr.iY,
                              .PTR_ARR    = {&mgr.Xptr, &mgr.Yptr},
                              .CTR_ARR    = {&mgr.iXptr, &mgr.iYptr}
                             };

这让我陷入了三星级的编程地狱,并为讨厌的成员访问提供了自己,比如:

char EXPECT_CHAR = *(*(*(mgr.PTR_ARR + mgr.PTR_CTR)) + (***(mgr.CTR_ARR + mgr.PTR_CTR)));
(mgr.Y[TARGET] == EXPECT_CHAR) ? printf("1\n") : printf("0\n");

为什么要做这么丑的事?我的基本原理是,在解析传入的字符时,我会 for each '%'字符递增PTR_CTR,从而干净地切换迭代器和缓冲区.然后,我可以通过添加缓冲区和指针到 struct 体,然后扩大PTR和CTR数组,将其扩展到N个电机.

我可以看到,我可以用计数器数组为自己节省一个间接级别,因为它不需要是双指针array.

这感觉像是解决这个问题的一种非常不雅观的方式.我如何让这个过程变得更干净?到目前为止,我唯一的 idea 是转向固定宽度的包装,消除了这种虚假的活力的必要性.

推荐答案

你有XY作为 struct parser_manager的成员:

    char  X    [32]; // buffer X
    char  Y    [32]; // buffer Y

你还提到了

I could then extend this out for some N number of motors by adding the buffers and pointers to the struct, then widening the PTR and CTR arrays.

你打算怎么做?(通过在parser_manager struct 中添加更多的成员,如XY!)

最好创建具有构件XY的不同 struct .获取parser_manager struct 中 struct 的指针,以便您可以通过重新分配内存来扩展它.有了这一点,您可以在访问XY缓冲区时消除多级别的间接访问.

示范代码示例:

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

typedef struct {
    char X[32];
    char Y[32];
} buffers;

typedef struct {
    buffers * ptr_x_y;
    int numele;   // to keep track of number of elements
} parser_manager;

int main (void)
{
    parser_manager mgr = {NULL, 0};

    mgr.numele = 1;
    mgr.ptr_x_y = malloc (sizeof (buffers) * mgr.numele);
    if (!mgr.ptr_x_y) {
        exit (EXIT_FAILURE);
    }

    strcpy (mgr.ptr_x_y[0].X, "DUMMY_X1");
    strcpy (mgr.ptr_x_y[0].Y, "DUMMY_Y1");
    printf ("%s, %s\n", mgr.ptr_x_y[0].X, mgr.ptr_x_y[0].Y);
    
    mgr.numele = 2;
    buffers * temp;
    mgr.ptr_x_y = realloc (temp = mgr.ptr_x_y, mgr.numele * sizeof (buffers));
    if (!mgr.ptr_x_y) {
        free (temp);
        exit (EXIT_FAILURE);
    }

    strcpy (mgr.ptr_x_y[1].X, "DUMMY_X2");
    strcpy (mgr.ptr_x_y[1].Y, "DUMMY_Y2");
    printf ("%s, %s\n", mgr.ptr_x_y[0].X, mgr.ptr_x_y[0].Y);
    printf ("%s, %s\n", mgr.ptr_x_y[1].X, mgr.ptr_x_y[1].Y);
    
    // free dynamically allocted memory
    
    return 0;
}

输出:

DUMMY_X1, DUMMY_Y1
DUMMY_X1, DUMMY_Y1
DUMMY_X2, DUMMY_Y2

iXiY是缓冲区XY的迭代器,因此你可以让它们也成为buffers struct 的成员.

如果出于某种原因,您不能使用动态内存分配函数mallocrealloc,则可以执行以下操作:

#include <stdio.h>

#define MAX_BUFFERS 10

typedef struct {
    char X[32];
    char Y[32];
} buffers;

typedef struct {
    buffers * ptr_x_y[MAX_BUFFERS];
    int numele;   // to keep track of number of elements
} parser_manager;

int main (void)
{
    parser_manager mgr = {{NULL}, 0};
    
    buffers buf1 = {.X = "DUMMY_X1", .Y = "DUMMY_Y1"};
    
    mgr.numele = 1;
    mgr.ptr_x_y[0] = &buf1;
    
    printf ("%s, %s\n", mgr.ptr_x_y[0]->X, mgr.ptr_x_y[0]->Y);    

    buffers buf2 = {.X = "DUMMY_X2", .Y = "DUMMY_Y2"};
    
    mgr.numele = 2;
    mgr.ptr_x_y[1] = &buf2;
    
    printf ("%s, %s\n", mgr.ptr_x_y[1]->X, mgr.ptr_x_y[1]->Y);
   
    return 0;
}

输出:

DUMMY_X1, DUMMY_Y1
DUMMY_X2, DUMMY_Y2

C++相关问答推荐

漏洞仅出现在FreeBSD上,但在Windows、Linux和MacOS上运行得非常好

数组元素的编号索引

当包含头文件时,gcc会发出隐式函数声明警告

segfault在C中使用getline()函数

如何判断宏参数是否为C语言中的整型文字

GCC预处理宏和#杂注GCC展开

C语言中的strstr问题

从纯C中访问通用项对话框

C是否用0填充多维数组的其余部分?

我的程序在收到SIGUSR1信号以从PAUSE()继续程序时总是崩溃()

如何使用C for Linux和Windows的标准输入与gdb/mi进行通信?

在Apple Silicon上编译x86的Fortran/C程序

CGO:如何防止在使用CGO在包中包含C头文件时出现多个定义...&q;错误?

Fscanf打印除退出C代码为1的程序外的所有内容

c程序,让用户输入两类数字,并给出输出用户输入多少个数字

C中的数组下标和指针算法给出了不同的结果

在git补丁中自动添加C的宏

`%%的sscanf无法按预期工作

指向返回 struct 成员的指针,安全吗?

定义 int a = 0, b = a++, c = a++;在 C 中定义了行为吗?