动态char数组大小

时间:2010-02-05 11:08:29

标签: c arrays embedded

在我的应用程序中,我定义了一个char数组,它可以采用以下三个选项之一:“okay”,“high”,“low”,然后从串行端口发送到远程设备。我目前的数组大小可以取4个字符加上回车和换行,但是当我必须发送“低”时,我在字符串中得到一个空字符,我担心这会混淆主机终端。

数组定义

char mod1_status_char[6] = {'0','0','0','0','0','0'};     
char mod2_status_char[6] = {'0','0','0','0','0','0'};     
char mod3_status_char[6] = {'0','0','0','0','0','0'};     

switch case语句示例:

void DCOKStatus(uint8_t *ptr_status)
{
    uint8_t status = *ptr_status;

    switch (status) 
    {
        case 0x00:
            strcpy(mod1_status_char, "okay");
            strcpy(mod2_status_char, "okay");
            strcpy(mod3_status_char, "okay");
            break; 
        case 0x10:
            strcpy(mod1_status_char, "okay");
            strcpy(mod2_status_char, "okay");
            strcpy(mod3_status_char, "low");
            break;
     }

这是使消息字符串发送的结构

    strcpy(MsgStatus_on.descriptor_msg, "$psu_");
    MsgStatus_on.address01 = hex_addr[0];
    MsgStatus_on.address02 = hex_addr[1];
    MsgStatus_on.space01 = 0x20;
    strcpy(MsgStatus_on.cmdmsg01, "op_en op1_");
    strcpy(MsgStatus_on.statusmsg01, mod1_status_char);
    MsgStatus_on.space02 = 0x20;
    strcpy(MsgStatus_on.cmdmsg02, "op2_");
    strcpy(MsgStatus_on.statusmsg02, mod2_status_char);
    MsgStatus_on.space03 = 0x20;
    strcpy(MsgStatus_on.cmdmsg03, "op3_");
    strcpy(MsgStatus_on.statusmsg03, mod3_status_char);
    MsgStatus_on.CR = 0x0D;
    MsgStatus_on.LF = 0x0A;

并发送消息

void USARTWrite(char *object, uint32_t size)
{    
    GPIO_SetBits(GPIOB, GPIO_Pin_1);

    char *byte;
    for (byte = object; size--; ++byte)                                                                       
    {                                       
          USART_SendData(USART1,*byte);                                 

    }

当我需要发送“低”时,是否有人能够建议一个好的方法来将数组动态调整为一个字符?

由于

6 个答案:

答案 0 :(得分:5)

我认为不需要调用动态大小的数组。 C语言中有两种方法可以动态调整数组大小:使用malloc或类似方法分配它;或使用C99 VLA。但是在这种情况下,你有不同长度的字符串,当然重要的是按正确的顺序写正确的字节?就个人而言,我更喜欢这样的事情,或许:

char * strings[] = {"okay\r\n", "high\r\n", "low\r\n"};

serial_send(strings[msg_number], strlen(strings[msg_number]));

您不必调用strlen,必须将长度存储在另一个数组中。但即使在最小的嵌入式设备上,与发送串行数据相比,数到6只需要很少的时间。

当然我假设你调用的任何函数实际发送数据,需要一个指针和一个长度。但如果没有,我不会看到动态大小的数组如何帮助。

我认为这里难以回答这个问题的一般问题是你没有真正说出数组的“大小”是什么,或者为什么它与实际写入的字节数有关到串口。

编辑:通过你的额外解释,关键的事情似乎是这个结构,三个单独的字符串被“传入”。不确定将字符串传递给struct意味着什么。如果它目前看起来像这样:

struct serialmessage {
    char first[6];
    char second[6];
    char third[6];
};

serialmessage msg;
memcpy(msg.first, mod1_status_char, 6); // etc.

那么也许最好这样做:

char *char mod1_status_char; // etc.

switch(status) {
    case 0x00:
        mod1_status_char = strings[0]; // or #define STATUS_OK 0
        mod2_status_char = strings[0];
        mod3_status_char = strings[0];
        break;
    case 0x10:
        mod1_status_char = strings[0];
        mod2_status_char = strings[0];
        mod3_status_char = strings[2]; // STATUS_LOW
};

serialmessage msg[3*MAX_STRING_LENGTH+1];
strcpy(msg, mod1_status_char); // or use stpcpy if you have it
strcat(msg, mod2_status_char);
strcat(msg, mod3_status_char);

然后使用strlen(msg)发送结构。 msg在这里并不完全是“动态的”,但它中字符串的长度根据数据而变化,这可能是你想要的。或许我仍然误解了这三个char数组的作用。

在我看来,复制字符串不仅仅是为了引入并发症。通过指针引用它们,直到最后可能的时刻,组装消息,并最小化代码中必须正确获取缓冲区大小的位置数。

答案 1 :(得分:3)

“然后将status_char数组传递给结构,然后使用发送例程发送该结构。”

要非常小心这样做,根据你编码的方式,你可以在那里获得各种垃圾。记住在C中编译器可以填充结构但是它很高兴。

作为旁注,您的字符串缓冲区太短而无法正确保存字符串。使用4个字符+ CR + LF时,您需要一个7个字符的缓冲区,因为您需要存储空终止符'\ 0'。如果你不这样做,不要使用任何'str'函数,因为你没有处理正确的C字符串,所有你要做的就是当有人去读这个/做出改变并发现时,你将要做的更多问题在你的黑客终止之后复制一个str(strcopy正在将“low \ 0”复制到你的缓冲区中,你出于某种原因显然在其他地方抛出/ r / n)使用memcpy。

解决方案:

为什么要复制这些字符串呢?为什么不直接向send函数发送一个指示,告诉它应该发送什么,只是静态分配字符串?

您可以使用(E_LOW,E_OKAY,E_HIGH)的值创建枚举,只需将3个枚举发送到发送函数,并将实际的字符串存储为本地静态变量。如果空间有问题,您可以使用位标志而不是枚举。

你的send函数只需要将字符串值一次一个字节地复制到发送缓冲区并发送strlen()字节。

答案 2 :(得分:1)

我在这里遗漏了什么吗? send例程应该只对字符串使用strlen(),因此它只在缓冲区中发送数据。

serWrite( mod1_status, strlen( mod1_status));
serWrite( "\r\n", 2);

答案 3 :(得分:0)

您可以选择的选项很少:

  1. 如果选项是预定义的,为什么要发送文本?
    你可以只发送身份证。
  2. 通常情况下,除少数情况外,协议消息不是固定长度的 长度第一,消息第二, CRC第三。
  3. 用空格填充空的char数组空间并修剪另一侧的字符串 不是一种选择,我没有写过这个。

答案 4 :(得分:0)

截断数组的“head”。

假设您有char words[5](或6 - 持有“\ r \ n”)。

因此,如果是“okay”和“high”,则从第一个元素 - words开始发送words的内容,如果是低,则从第二个元素开始发送内容:{{ 1}}。

编辑:当然,在这种情况下,您应该从words + 1开始写“低”,而不是words[1]

答案 5 :(得分:0)

我想看看你对MsgStatus_on的定义。

我打赌你有这样的事情:

tyepdef struct {
   char descriptor_msg[6];
   char address01;
   char address02;
   char space01;
   char cmdmsg01[11];
   char statusmsg01[6];
   char space02;
   char cmdmsg02[5];
   char statusmsg02[6];
   char space03;
   char cmdmsg03[5];
   char statusmsg03[6];
   char CR;
   char LF;
} MsgStatus;

MsgStatus MsgStatus_on;

然后我猜你在调用USARTWrite时会做一个直字节指针,如下所示:

USARTWrite ((char *)&MsgStatus_on, sizeof(MsgStatus_on));

如果是这种情况,那么它会复制缓冲区中的额外字节。实际上它应该在你的所有char数组上添加额外的\ 0。除非你声明所有这些比我做的少,并且当你执行strcpy()时,你实际上是在超越你的数组。它不会导致您出现问题,因为您在下一个语句中设置了超限内存。

另一种选择可能是使用sprintf:

char *message[100] //or some size big enough to hold the whole message.

sprintf (message, "$psu_%d%d op_en op1_%s op2_%s op3_%s\r\n",
   address01, address02, mod1_status_char, mod2_status_char, mod3_status_char);

然后致电:

USARTWrite (message, strlen(message));
编辑:哎呀我想这个问题很老了。哦,好吧,我会留下答案,以防它对你有用。