Parsing a fixed-length string with a delimiter - c#-3.0

...where the delimiter might also be in the body.
I am working with an LCD display that has a protocol that uses the format below:
STX(1byte) + IDT(1byte) + Type(1byte) + CMD(3bytes) + [Value/Reply(1byte)] + ETX(1byte)
STX is 0x07, and ETX is 0x08. The IDT coming from the display could also be 0x08, which is causing me problems when trying to parse the response from the display. I didn't write the parsing routine, but am now tasked with making things work.
The original programmer's solution can be seen at https://gyazo.com/1fc74133e7109e5aa213f3f5878cc001. The problem is that when IDT is 0x08, the code just grabs the first 2 bytes in the response because 0x08 is the ETX as well as the IDT. I thought about using LastIndexOf, but the possibility exists that there would be more than one response from the display in the buffer. Any help is appreciated.

If every response from the display will contain the 8 bytes you described, then there is no need to use IndexOf to find the ETX terminator. You could do something like this:
internal override void processRXBuffer()
{
for ( int index = 0; (index + 8) <= RXData.Length; index += 8 )
{
string pCmd= RXData.Substring(index, 8);
if ( (pCmd[0] == '\x07') && (pCmd[7] == '\x08') )
{
// Looks like we have a valid response so process it
}
}
}

Related

stm32f429, spi dr register not write data

code_1
code_2
register on debug
logic analyzer
void SPI_SendData(SPI_RegDef_t *pSPIx,uint8_t *pTxBuffer , uint32_t Len)
{
while(Len > 0)
{
// 1 . wait until TXE is set ,
while(SPI_GetFlagStatus(pSPIx, SPI_TXE_FLAG) == FLAG_RESET);
// 2. check the DFF bit in CR1
if( (pSPIx->CR1 & (1 << SPI_CR1_DFF) ) )
{
// 16 BIT DFF
pSPIx->DR = *((uint16_t*)pTxBuffer); // dereferencing(typecasting );
Len--;
Len--;
(uint16_t*)pTxBuffer++; // typecasting this pointer to uint16 type and incrementing by 2.
/* The buffer is a uint8_t pointer type. When using the 16-bit data frame,
* we pick up 16-bits of data, increment pointer by 2 bytes,*/
}else
{
// 8 BIT DFF
pSPIx->DR = *pTxBuffer;
Len--;
pTxBuffer++;
/*
*(( uint8_t*)&hspi->Instance->DR) = (*pData);
pData += sizeof(uint8_t);
hspi->TxXferCount--;
*/
}
}
}
i see, MOSI always send 255 on logic analyzer but wrong data.
(uint16_t*)pTxBuffer++; increments the pointer by 1 byte, not two that you say you hope it will in the comment.
If you want to do it by converting to halfword pointer and incrementing, then you need to do something like:
pTxBuffer = (uint8_t*)(((uint16_t*)pTxBuffer) + 1);
But that is just a silly way of saying pTxBuffer += 2;
Really it doesn't make sense to have the if inside the loop, because the value of the DFF bit doesn't change unless you write to it, and you don't. I suggest you write one loop over words and one loop over bytes and have the if at the top level.

How to pack/unpack a byte in q/kdb

What I'm trying to do here is pack a byte like I could in c# like this:
string symbol = "T" + "\0";
byte orderTypeEnum = (byte)OrderType.Limit;
int size = -10;
byte[] packed = new byte[symbol.Length + sizeof(byte) + sizeof(int)]; // byte = 1, int = 4
Encoding.UTF8.GetBytes(symbol, 0, symbol.Length, packed, 0); // add the symbol
packed[symbol.Length] = orderTypeEnum; // add order type
Array.ConstrainedCopy(BitConverter.GetBytes(size), 0, packed, symbol.Length + 1, sizeof(int)); // add size
client.Send(packed);
Is there any way to accomplish this in q?
As for the Unpacking in C# I can easily do this:
byte[] fillData = client.Receive();
long ticks = BitConverter.ToInt64(fillData, 0);
int fillSize = BitConverter.ToInt32(fillData, 8);
double fillPrice = BitConverter.ToDouble(fillData, 12);
new
{
Timestamp = ticks,
Size = fillSize,
Price = fillPrice
}.Dump("Received response");
Thanks!
One way to do it is
symbol:"T\000"
orderTypeEnum: 123 / (byte)OrderType.Limit
size: -10i;
packed: "x"$symbol,("c"$orderTypeEnum),reverse 0x0 vs size / *
UPDATE:
To do the reverse you can use 1: function:
(8 4 8; "jif")1:0x0000000000000400000008003ff3be76c8b43958 / server data is big-endian
("jif"; 8 4 8)1:0x0000000000000400000008003ff3be76c8b43958 / server data is little-endian
/ ticks=1024j, fillSize=2048i, fillPrice=1.234
*) When using BitConverter.GetBytes() you should also check the value of BitConverter.IsLittleEndian to make sure you send bytes over the wire in a proper order. Contrary to popular belief .NET is not always little-endian. Hovewer, an internal representation in kdb+ (a value returned by 0x0 vs ...) is always big-endian. Depending on your needs you may or may not want to use reverse above.

scanf hangs when copy and paste many line of inputs at a time

This may be a simple question, but I'm new to C, and yet couldn't find any answer. My program is simple, it takes 21 lines of string input in a for loop, and print them after that. The number could be less or greater.
int t = 21;
char *lines[t];
for (i = 0; i < t; i++) {
lines[i] = malloc(100);
scanf("%s", lines[i]);
}
for (int i = 0; i < t; i++) {
printf("%s\n", lines[i]);
free(lines[i]);
}
...
So when I copy & paste the inputs at a time, my program hangs, no error, no crash. It's fine if there's only 20 lines or below. And if I enter by hand line by line, it works normally regardless of number of inputs.
I'm using XCode 5 in Mac OS X 10.10, but I don't think this is the issue.
Update:
I tried to debug it when the program hangs, it stopped when i == 20 at the line below:
0x7fff9209430a: jae 0x7fff92094314 ; __read_nocancel + 20
The issue may be related to scanf, but it's so confused, why the number 20? May be I'm using it the wrong way, great thanks to any help.
Update:
I have tried to compile the program using the CLI gcc. It works just fine. So, it is the issue of XCode eventually. Somehow it prevents user from pasting multiple inputs.
Use fgets when you want to read a string in C , and see this documentation about that function:
[FGETS Function]
So you should use it like this :
fgets (lines[i],100,stdin);
So it'll get the string from the input of the user and you can have a look on these two posts as well about reading strings in C:
Post1
Post2
I hope that this'll help you with your problem.
Edit :
#include <stdio.h>
void main(){
int t = 21;
int i;
char *lines[t];
for (i = 0; i < t; i++) {
lines[i] = malloc(100);
fgets(lines[i],255,stdin);
}
for (i = 0; i < t; i++) {
printf("String %d : %s\n",i, lines[i]);
free(lines[i]);
}
}
This code gives :
As you can see , I got the 21 strings that I entered (From 0 to 20, that's why it stops when i==20).
I tried with your input ,here's the results :
I wrote the same code and ran. It works.
It might contain more than 99 characters (include line feed) per line...
Or it might contain spaces and tabs.
scanf(3)
When one or more whitespace characters (space, horizontal tab \t, vertical tab \v, form feed \f, carriage return \r, newline or linefeed \n) occur in the format string, input data up to the first non-whitespace character is read, or until no more data remains. If no whitespace characters are found in the input data, the scanning is complete, and the function returns.
To avoid this, try
scanf ("%[^\n]%*c", lines[i]);
The whole code is:
#include <stdio.h>
int main() {
const int T = 5;
char lines[T][100]; // length: 99 (null terminated string)
// if the length per line is fixed, you don't need to use malloc.
printf("input -------\n");
for (int i = 0; i < T; i++) {
scanf ("%[^\n]%*c", lines[i]);
}
printf("result -------\n");
for (int i = 0; i < T; i++) {
printf("%s\n", lines[i]);
}
return 0;
}
If you still continue to face the problem, show us the input data and more details. Best regards.

How do I change the name of Emacs auto-recovery file?

At the moment it saves the file with format:
.#main.c -> sara#sara.home.com.27017:1231918415
This makes it problematic since it ends with ".c".
I need it to be .#main.c#
Update: I have emacs 22.1
That's not the auto-recovery file, that's the link used as a locking token for the file.
update
If I tell you, will you introduce me to Summer Glau?
It's probably not going to be easy to change that; I just dug a bit and it looks like it's set in the C code. But let's ask the next question: why do you want to? I'm guessing you're hitting a regular expression for .c files that you don't want to match these. If so, note that all these lockfile links start with .# -- invariably, that's hardcoded -- so you could always exclude files with names that match "^.#" (depending on which regex syntax you use.)
If you really want to hack at it, it's in filelock.c at about line 320 in EMACS 22. Here's the code:
/* Write the name of the lock file for FN into LFNAME. Length will be
that of FN plus two more for the leading `.#' plus 1 for the
trailing period plus one for the digit after it plus one for the
null. */
#define MAKE_LOCK_NAME(lock, file) \
(lock = (char *) alloca (SBYTES (file) + 2 + 1 + 1 + 1), \
fill_in_lock_file_name (lock, (file)))
static void
fill_in_lock_file_name (lockfile, fn)
register char *lockfile;
register Lisp_Object fn;
{
register char *p;
struct stat st;
int count = 0;
strcpy (lockfile, SDATA (fn));
/* Shift the nondirectory part of the file name (including the null)
right two characters. Here is one of the places where we'd have to
do something to support 14-character-max file names. */
for (p = lockfile + strlen (lockfile); p != lockfile && *p != '/'; p--)
p[2] = *p;
/* Insert the `.#'. */
p[1] = '.';
p[2] = '#';
p = p + strlen (p);
while (lstat (lockfile, &st) == 0 && !S_ISLNK (st.st_mode))
{
if (count > 9)
{
*p = '\0';
return;
}
sprintf (p, ".%d", count++);
}
}
You can upgrade to emacs 24.3 and add to your .emacs file the following line:
(setq create-lockfiles nil)
That's strange, the default should have # at each end..
You can customize the name by redefining the auto-save-file-name-p and make-auto-save-file-name functions. In GNU emacs you would add the elisp to your .emacs file.

How to animate the command line?

I have always wondered how people update a previous line in a command line. a great example of this is when using the wget command in linux. It creates an ASCII loading bar of sorts that looks like this:
[======> ] 37%
and of course the loading bar moves and the percent changes, But it doesn't make a new line. I cannot figure out how to do this. Can someone point me in the right direction?
One way to do this is to repeatedly update the line of text with the current progress. For example:
def status(percent):
sys.stdout.write("%3d%%\r" % percent)
sys.stdout.flush()
Note that I used sys.stdout.write instead of print (this is Python) because print automatically prints "\r\n" (carriage-return new-line) at the end of each line. I just want the carriage-return which returns the cursor to the start of the line. Also, the flush() is necessary because by default, sys.stdout only flushes its output after a newline (or after its buffer gets full).
There are two ways I know of to do this:
Use the backspace escape character ('\b') to erase your line
Use the curses package, if your programming language of choice has bindings for it.
And a Google revealed ANSI Escape Codes, which appear to be a good way. For reference, here is a function in C++ to do this:
void DrawProgressBar(int len, double percent) {
cout << "\x1B[2K"; // Erase the entire current line.
cout << "\x1B[0E"; // Move to the beginning of the current line.
string progress;
for (int i = 0; i < len; ++i) {
if (i < static_cast<int>(len * percent)) {
progress += "=";
} else {
progress += " ";
}
}
cout << "[" << progress << "] " << (static_cast<int>(100 * percent)) << "%";
flush(cout); // Required.
}
The secret is to print only \r instead of \n or \r\n at the and of the line.
\r is called carriage return and it moves the cursor at the start of the line
\n is called line feed and it moves the cursor on the next line
In the console. If you only use \r you overwrite the previously written line.
So first write a line like the following:
[ ]
then add a sign for each tick
\r[= ]
\r[== ]
...
\r[==========]
and so on.
You can use 10 chars, each representing a 10%.
Also, if you want to display a message when finished, don't forget to also add enough white chars so that you overwrite the previously written equal signs like so:
\r[done ]
below is my answer,use the windows APIConsoles(Windows), coding of C.
/*
* file: ProgressBarConsole.cpp
* description: a console progress bar Demo
* author: lijian <hustlijian#gmail.com>
* version: 1.0
* date: 2012-12-06
*/
#include <stdio.h>
#include <windows.h>
HANDLE hOut;
CONSOLE_SCREEN_BUFFER_INFO bInfo;
char charProgress[80] =
{"================================================================"};
char spaceProgress = ' ';
/*
* show a progress in the [row] line
* row start from 0 to the end
*/
int ProgressBar(char *task, int row, int progress)
{
char str[100];
int len, barLen,progressLen;
COORD crStart, crCurr;
GetConsoleScreenBufferInfo(hOut, &bInfo);
crCurr = bInfo.dwCursorPosition; //the old position
len = bInfo.dwMaximumWindowSize.X;
barLen = len - 17;//minus the extra char
progressLen = (int)((progress/100.0)*barLen);
crStart.X = 0;
crStart.Y = row;
sprintf(str,"%-10s[%-.*s>%*c]%3d%%", task,progressLen,charProgress, barLen-progressLen,spaceProgress,50);
#if 0 //use stdand libary
SetConsoleCursorPosition(hOut, crStart);
printf("%s\n", str);
#else
WriteConsoleOutputCharacter(hOut, str, len,crStart,NULL);
#endif
SetConsoleCursorPosition(hOut, crCurr);
return 0;
}
int main(int argc, char* argv[])
{
int i;
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hOut, &bInfo);
for (i=0;i<100;i++)
{
ProgressBar("test", 0, i);
Sleep(50);
}
return 0;
}
PowerShell has a Write-Progress cmdlet that creates an in-console progress bar that you can update and modify as your script runs.
Here is the answer for your question... (python)
def disp_status(timelapse, timeout):
if timelapse and timeout:
percent = 100 * (float(timelapse)/float(timeout))
sys.stdout.write("progress : ["+"*"*int(percent)+" "*(100-int(percent-1))+"]"+str(percent)+" %")
sys.stdout.flush()
stdout.write("\r \r")
As a follow up to Greg's answer, here is an extended version of his function that allows you to display multi-line messages; just pass in a list or tuple of the strings you want to display/refresh.
def status(msgs):
assert isinstance(msgs, (list, tuple))
sys.stdout.write(''.join(msg + '\n' for msg in msgs[:-1]) + msgs[-1] + ('\x1b[A' * (len(msgs) - 1)) + '\r')
sys.stdout.flush()
Note: I have only tested this using a linux terminal, so your mileage may vary on Windows-based systems.
If your using a scripting language you could use the "tput cup" command to get this done...
P.S. This is a Linux/Unix thing only as far as I know...