我目前有发射器阵列存储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;
}
答案 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),即:0
,01111110
,1
,11
,{{1} },111
,1111
和111110
。如果接受了一个标志,你还必须检查位数是否是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,B
和0
(无限制)它会在适当的位置插入1
。要解码,只需输入一系列位,它会将标志转换为0
,BREAK转换为F
并消除编码器插入的空间B
。 (在0
位之后插入1
,以确保透明度
我已经手动编译了自动机,所以可能它在状态数量上并不是最优的,但是18个状态并不是太多。
状态名称代表前缀0
,后跟已读取太多而尚未输出的内容,因为我们无法确定它是标志,中断还是简单的数据位序列。锚定到流开头的状态以ST
为前缀。
另外,DFA只识别标志之间的8位模式中的多个,这远远超出了这个答案的范围。您可以计算标志之间的位,看看它们是否是标志识别中的8位的倍数,因为DFA应该具有N1xN2状态(大约80个状态),这使得它没有值得实现。