删除存储在数组中的标志位

时间:2018-02-04 23:35:51

标签: c arrays loops

我目前有发射器阵列存储01111110 0110111 01111110 我希望接收器阵列存储0110111.我想消除所有01111110位。

但是我收到了0110111 01111110.为什么我的代码只删除了发送器阵列中的第一个01111110位?

我尝试的代码如下:

#define nosbits 23
#include<stdio.h>
#include <stdlib.h>
#include<stdbool.h> 

int main()
{

   unsigned transmitter[nosbits] = { 0,1,1,1,1,1,1,0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,0 };
   unsigned receiver[nosbits];
   int count = 0;
   int outputreceivercount = 0;
   bool flag = false;

   for (int i = 0; i < nosbits; i++)
   {

       if (transmitter[i] == 1)
       {
          count++;
       }
       else
       {
          count = 0;
       }

       receiver[outputreceivercount++] = transmitter[i];

       //After 5 consecutive 1s, if the next two bits are '10', then the flag is detected. 
       if ((transmitter[i + 1] == 1) && (transmitter[i + 2] == 0) && count == 5)
       {
           if (!(flag))
           {
              flag = true;
              i = i + 2;
              outputreceivercount = 0;
              count = 0;
           }  
        }
   }


   printf("Bitstream before removing flag bits:\n");
   for (int i = 0; i < nosbits; i++)
   {
      printf("%d", transmitter[i]);
   }
   printf("\n\n");


   printf("Bitstream after removing flag bits:\n");
   for (int i = 0; i < outputreceivercount; i++)
   {
      printf("%d", receiver[i]);
   }
   printf("\n");

   system("pause");
   return 0; 

}

3 个答案:

答案 0 :(得分:1)

实际上你并不需要&#34;标志&#34;变量来检测标志。 替换以下代码,看看它是否有帮助。

//After 5 consecutive 1s, if the next two bits are '10', then the flag is detected. 
   if ((transmitter[i + 1] == 1) && (transmitter[i + 2] == 0) && count == 5)
   {                        
        i = i + 2;      
        outputreceivercount -= (count+1);
        count = 0;      
    }

如果需要,可以进一步优化。

答案 1 :(得分:0)

要回答您的具体问题,请在执行“删除”部分之前检查flag的状态 - 在“删除”位之前,您需要flag为false。第一次检测到这样的标志时,您将flag设置为true。然后它对所有后续循环都保持为真,因此你的“删除”部分永远不会再执行。

更笼统地说,我对你的“删除”部分感到困惑 - 每次检测到“标志”时,你都会从第0个元素开始覆盖receiver?字符串中会发生什么,例如“0111111001101110111111010101010” - 您对输出的期望是什么?

答案 2 :(得分:0)

1)如果你需要检测多个8bit的标志,你最好使用字符,所以当你检测到字节0x7e时,就消除它。当您在异步线路中使用扁平字符时,这适用于仅传输8位字节的字符。 (您的示例数据在标志之间只有七位数据,因此我认为情况并非如此。)

2)如果你需要逐位检测标志,那么你面临HDLC成帧问题,它有两个部分:a)当你检测到6个联合1位时检测到标志,并且b)如果顺序超过5 0位,则发送器插入1位(以确保透明度)。对于第二部分,您还需要删除5 0位序列后的第6个1位。我不知道你是否想要这个,但你的标志似乎与HDLC标志非常相似,假设你没有真正研究这个协议。

这个问题可以面对有限的自动机。 NFA等效,检测到这一点是:

 0,1 
,--. 
|  / 
| /  
|v  1       1       1       1       1      0 
(0)--->(1P)--->(2P)--->(3P)--->(4P)--->(5)--->(6D)
 |                                      |      _
 .                                      .     / \ 1
  \                                      \ 1  | V
   \0                                     `-->(7B)
    \
     \   1      1       1       1       1       0      
     (8)--->(9)--->(10)--->(11)--->(12)--->(13)--->(14F)

其中

  • ([1-4]P)接受状态,打印状态编号中显示的1个字符数(例如,状态(3P)打印111。)
  • (6D)接受状态,请打印11111
  • (7B)接受状态。检测到BREAK状况。
  • (14F)接受状态。检测到标记。
  • 所有其他人都不接受国家。自动机必须继续 匹配状态直到不再能够达到接受状态,输出 作为输出访问的最后一个接受状态的字符串(例如,如果最后一个接受状态是6D,那么它必须输出'11111'。如果访问的最后一个状态包括几个接受状态,则优先级顺序为:

    14F, 7B, 6D, 4P, 3P, 2P, 1P
    

此NFA识别8种字符串(我将其表示为regexps),即:001111110111,{{1} },1111111111110。如果接受了一个标志,你还必须检查位数是否是8的倍数,因为你可以使用这个协议的任意位序列。可能你没有,因为你发布的样本数据只包含7位。它可以用以下11111111*模式表示:

lex(1)

下面是一个完整的DFA,它将输入位转换为以下内容 字母表(对于您的问题,它只需要将%% 0 ECHO; 01111110 putchar('F'); 1111111* putchar('B'); 1 | 11 | 111 | 1111 ECHO; 111110 fputs("11111", stdout); . ; %% "F"字符串替换为空字符"B"):

""

要编译,请使用以下命令:

/*
 * DFA to implement.
 */

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

#define F(x) __FILE__":%d:%s: " x, __LINE__, __func__
#ifndef DEBUG
#define DEBUG 0
#endif

#if DEBUG
#define D(...) fprintf(stderr, __VA_ARGS__)
#else
#define D(...)
#endif

#define E(...) fprintf(stderr, __VA_ARGS__)

char *names[] = {
        "START"    , "ST0"      , "ST_1"     , "ST01"     ,
        "ST_11"    , "ST011"    , "ST_111"   , "ST0111"   ,
        "ST_1111"  , "ST01111"  , "ST_11111" , "ST011111" ,
        "ST1111111", "ST"       , "ST0111111", "ST1"      ,
        "ST11"     , "ST111"    , "ST1111"   , "ST11111"  ,
};
static enum st {
        START    , ST0      , ST_1     , ST01     , ST_11    ,
        ST011    , ST_111   , ST0111   , ST_1111  , ST01111  ,
        ST_11111 , ST011111 , ST1111111, ST       , ST0111111,
        ST1      , ST11     , ST111    , ST1111   , ST11111  ,
} state = START;

char flag[] = "F";
char brk[] = "B";


struct tab_entry {
    enum st t_next;
    char *t_insert;
} tab[][2] = {
        /* INPUT                                          */
        /* STATE            0/OUTPUT   | 1/OUTPUT         */
        /* ========================+================      */
        /* START     */     ST0, 0,         ST_1,      0,       
        /* ST0       */     ST0, "0",       ST01,      0,     
        /* ST_1      */     ST0, 0,         ST_11,     0,     
        /* ST01      */     ST0, "01",      ST011,     0,    
        /* ST_11     */     ST0, 0,         ST_111,    0,    
        /* ST011     */     ST0, "011",     ST0111,    0,   
        /* ST_111    */     ST0, 0,         ST_1111,   0,    
        /* ST0111    */     ST0, "0111",    ST01111,   0,
        /* ST_1111   */     ST0, 0,         ST_11111,  0,
        /* ST01111   */     ST0, "01111",   ST011111,  0,
        /* ST_11111  */     ST0, 0,         ST1111111, 0, /* break */
        /* ST011111  */     ST, "011111",   ST0111111, 0,
        /* ST1111111 */     ST0, brk,       ST1111111, 0,
        /* ST        */     ST0, 0,         ST1,       0,
        /* ST0111111 */     ST , flag,      ST1111111, 0, /* break */
        /* ST1       */     ST0, "1",       ST11,      0,
        /* ST11      */     ST0, "11",      ST111,     0,
        /* ST111     */     ST0, "111",     ST1111,    0,
        /* ST1111    */     ST0, "1111",    ST11111,   0,
        /* ST11111   */     ST,  "11111",   ST1111111, 0, /* break */
};

void hdlc_rst()
{
    state = START;
}

char *hdlc_dec(char *out, int outsz, char *in)
{
    char *res = out;
    int c;

    while ((c = *in++) != 0) {
        switch(c) {
        case '0': case '1':;
            struct tab_entry *entry = &tab[state][c - '0'];
            if (state != START) fputs("", stderr);
            D(F("State: %s(%d), Input: '%c'\n"),
                    names[state], state, c);
            if (entry->t_insert) {
                int n = snprintf(out, outsz,
                        "%s", entry->t_insert);
                D(F("Append \"%s\"\n"), entry->t_insert);
                out += n;
                outsz -= n;
            }
            D(F("State %s(%d) -> %s(%d)\n"),
                    names[state], state,
                    names[entry->t_next], entry->t_next);
            state = entry->t_next;
            break;
        default:
            E(F("Invalid character '%c' in input string\n"), c);
            break;
        } /* switch */
    } /* while */
    char *p = tab[state][0].t_insert;
    snprintf(out, outsz, "%s", p ? p : "");
    return res;
} /* hdlc_dec */

char *hdlc_enc(char *out, int outsz, char *in)
{
    char *res = out;
    char c;
    int n_ones = 0;

    while ((c = *in++) != 0) {
        int n = 0;
        switch(c) {
        case 'F': case 'f':
            n = snprintf(out, outsz, "01111110");
            n_ones = 0;
            break;
        case 'B': case 'b':
            n = snprintf(out, outsz, "1111111");
            n_ones = 0;
            break;
        case '0':
            n = snprintf(out, outsz, "0");
            n_ones = 0;
            break;
        case '1':
            n = snprintf(out, outsz, "1");
            n_ones++;
            if (n_ones == 5) {
                n += snprintf(out+1, outsz-1, "0");
                n_ones = 0;
            }
            break;
        default:
            D(F("Invalid character '%c' in input string\n"), c);
            break;
        } /* switch */
        outsz -= n;
        out += n;
    } /* while */
    return res;
} /* hdlc_enc */

int main(int argc, char **argv)
{
    static char linea[10240], out[10240];
    char *(*hdlc)(char *out, int outsz, char *in) = hdlc_dec;

    if (strcmp(argv[0], "hdlc_dec") == 0)
        hdlc = hdlc_dec;
    else if (strcmp(argv[0], "hdlc_enc") == 0)
        hdlc = hdlc_enc;

    while(fgets(linea, sizeof linea, stdin)) {
        int l = strlen(linea);
        if (linea[l-1] == '\n') linea[--l] = '\0';
        hdlc(out, sizeof out, linea);
        D(F("%s ==> %s\n"), linea, out);
        printf("%s\n", out);
    } /* while */

} /* main */

或者,如果您想了解自动机如何工作的调试痕迹,请使用

cc -o hdlc_enc hdlc.c
ln hdlc_enc hdlc_dec

并且您将使用两个命令cc -o hdlc_enc -DDEBUG=1 hdlc.c ln hdlc_enc hdlc_dec 来编码标准输入,并使用hdlc_enc来解码它。要进行编码,请使用hdlc_dec作为标记,F表示BREAK,B0(无限制)它会在适当的位置插入1。要解码,只需输入一系列位,它会将标志转换为0,BREAK转换为F并消除编码器插入的空间B。 (在0位之后插入1,以确保透明度

我已经手动编译了自动机,所以可能它在状态数量上并不是最优的,但是18个状态并不是太多。

状态名称代表前缀0,后跟已读取太多而尚未输出的内容,因为我们无法确定它是标志,中断还是简单的数据位序列。锚定到流开头的状态以ST为前缀。

注2

另外,DFA只识别标志之间的8位模式中的多个,这远远超出了这个答案的范围。您可以计算标志之间的位,看看它们是否是标志识别中的8位的倍数,因为DFA应该具有N1xN2状态(大约80个状态),这使得它没有值得实现。