My code below is working perfect when I write number or only len inside of it. However, I want to write(len-3) but it again return as if I write len inside of it. How can I solve it??
I get the length of the array by using:
int len = sizeof(tmp)/sizeof(tmp[0]);
The message variable is a String and received is:
char received = Serial.read();
if (Index<(len-3)){
message=tmp[Index++]=received;
Serial.print(message);
}
My aim is when I write dv35!1234567890*asdfqwertyuiopmnbvcx#asdas the code should return the part of it that is between '!' and '#' then during the if else part the code should get some parts of it. However, the last part should return until 3 chars before the array ends. but it did not work properly. it returns all the parts remaining.(As if I write only len inside of it). the length of the input is not stable so the message part changes depending on the length of the whole array. It should return 3 chars before the end.
Here is my whole code:
char tmp[200] = {0};
String pack;
String command;
String Size;
String messum;
String message;
String checksum;
int len = sizeof(tmp)/sizeof(tmp[0]);
int Index = 0;
bool Seen = false;
void setup(){
Serial.begin(9600);
}
void loop(){
while (Serial.available() > 0){
char received = Serial.read();
if (received == '!'){
Seen = true;
}
else if (received == '#'){
return strdup(tmp);
}
else if (Seen == true){
if(Index<2){
//Serial.print("P");
pack=tmp[Index++] = received;
Serial.print(pack);
}
else if(Index<4){
//Serial.print("C");
command=tmp[Index++] = received;
Serial.print(command);
}
else if(Index<6){
//Serial.print("S");
Size=tmp[Index++] = received;
Serial.print(Size);
}
else if (Index<(len-3)){
Serial.print("M");
message=tmp[Index++]=received;
Serial.print(message);
}
}
}
return NULL;
//input: dv35!1234567890*asdfqwertyuiopmnbvcx#asdas
}
there is no need of most of it.
You define the variable tmp in the global and it has constant length. You do not need to calculate the length of it.
For the char array sizeof(char_array) gives you the length of the array as sizeof(char) is by definition 1
Use the correct types. for the sizes use size_t not int
Related
The task of this function is to check, whether it contains any symbols but digits, spaces, or minuses.
bool MainWindow::inputExcp()
{
QString inputStr = ui->input->toPlainText();;
QByteArray ba = inputStr.toLocal8Bit();
char *myString = ba.data();
QString warn;
char space = ' ';
size_t size = sizeof(myString);
try{
for(unsigned long long i = 0; i < size; i++)
{
if (isdigit(*(myString+i)))
continue;
else if (*(myString+i) == space)
continue;
else if(*(myString+i) == '-')
continue;
else
throw *(myString+i);
}
}
catch (char x)
{
warn += ("Enter digits, spaces or minuses");
QMessageBox::warning(this, "Uncorrect input",warn);
return false;
}
return true;
}
I can't understand why this function returns true only for arrays that contain 8 and more elements. What is the solution to this problem?
Because the sizeof() function doesnt return the number of elements of a list, it returns the the size of the memory allocated for it.
I have asked a question here and now the code below makes the work that I expected (the work that I mentioned previously). Now I have another issue: if I write tmp[20] and if the size of the input is 20 chars, the code works. However the size of the input is not known. Therefore, there can be a maxsize, but the actual size depends on the input. How can I make this code work with every length? (yes, the code works when I write 200 inside of tmp but the size of 'message' depends on the whole array. It should be 3 chars before end and 6 chars after start).Therefore when I write 200 inside of tmp[] and the input is shorter than 200 chars, the message returns incorrectly. I think I should use dynamic memory allocation but I could not implement it to my code.
Here is my complete code:
char tmp[20] = { 0 };
int len = sizeof(tmp) / sizeof(tmp[0]);
String pack;
String command;
String Size;
String messum;
String message;
String checksum;
int Index = 0;
bool Seen = false;
void setup() {
Serial.begin(9600);
}
void loop() {
while (Serial.available() > 0) {
char received = Serial.read();
if (received == '!') {
Seen = true;
} else
if (received == '#') {
return strdup(tmp);
} else
if (Seen == true) {
if (Index < 2) {
//Serial.print("P");
pack = tmp[Index++] = received;
Serial.print(pack);
} else
if (Index < 4) {
//Serial.print("C");
command = tmp[Index++] = received;
Serial.print(command);
} else
if (Index < 6) {
//Serial.print("S");
Size = tmp[Index++] = received;
Serial.print(Size);
} else
if (Index < (len - 3)) {
//Serial.print("M");
message = tmp[Index++] = received;
Serial.print(message);
} else
if (Index < len) {
//Serial.print("C");
checksum = tmp[Index++] = received;
Serial.print(checksum);
}
}
}
return NULL;
//input: asdeyh134!123456789abcdefghtry#8647dfn
}
Anywhere you are adding characters to your array like this:
if (Seen == true) {
if (Index < 2) {
//Serial.print("P");
pack = tmp[Index++] = received;
Serial.print(pack);
You should also null terminate your string like so:
if (Seen == true) {
if (Index < 2) {
//Serial.print("P");
pack = tmp[Index++] = received;
tmp[Index] = 0;
Serial.print(pack);
That way you can use strlen to get the length of the string in the array. It will count the number of characters up to that null character.
int length = strlen(tmp);
On the next pass of the loop when you write in another character you will write it over that null and then write a new null right after that new character.
I have a function definition like this in an Arduino library:
bool RHReliableDatagram::sendtoWait(uint8_t * buf, uint8_t len, uint8_t address)
When I use:
uint8_t timePacket[] = "time\n";
sendtoWait(timePacket, sizeof(timePacket), SERVER_ADDRESS)
I get a perfectly fine string with "time" at the other end (SERVER_ADDRESS) in pyserial's readline() function which is decoded perfectly using utf-8 encoding.
Now I need to send some bytes using the same sendtoWait() function. I first define a char array of 60 bytes
char packetBuff[60] = "";
Then I get every byte and cast it as a char
char value = (char)flash.readByte(dumpCounter++);
Then put each value in the char array like this:
packetBuff[charNo] = value;
After I find a new line character I try to send the char array again using the sendtoWait() function:
if (value == '\n') {
Serial.println(packetBuff);
uint8_t buff[charNo];
for (int i = 0; i < charNo; i++) {
buff[i] = packetBuff[i];
}
sendtoWait(buff, charNo, SERVER_ADDRESS))
charNo++;
But although Serial.println(packetBuff) shows the proper characters e.g. something like "1559105487\n" (unix timestamp), buff array is just not working correctly and shows random characters something like a semi-colon, random single digit numbers etc.
How do I properly cast the char array and send it properly using the sendtoWait() function like "time\n" was sent?
EDIT:
Full code:
int charNo = 0;
char packetBuff[60] = "";
if (dumpCounter != 0) {
dumpCounter--;
}
while(dumpCounter < currentFlashLoc) {
char value = (char)flash.readByte(dumpCounter++);
packetBuff[charNo] = value;
if (value == '\n') {
Serial.println(packetBuff);
uint8_t buff[charNo];
for (int i = 0; i < charNo; i++) {
buff[i] = packetBuff[i];
}
if (manager.sendtoWait(buff, charNo, SERVER_ADDRESS)) {
// packet sent successfully
}
charNo = -1;
}
charNo++;
}
Casting the char array like this:
sendtoWait((uint8_t*)packetBuff, sizeof(packetBuff), SERVER_ADDRESS)
works correctly. buff is not required.
I'm having a little bit of trouble with this bit of code here for my Arduino.
Basically, I'm trying to send in a series of characters, turn it into an character array, and use that to run the rest of the program. I'm close because I know everything is working perfectly internally, but when I boot from the serial port, the message isn't getting in.
I assume that at this point it probably is how I am constructing the array... or some oddity. It is probably just a simple error in how I put the code together, but I'm completely struck. (I was previously using a string, but because of how the Arduino works with them, it pretty much makes using them for memory purposes impossible.)
I'm using a Java program (Ardulink) to send the information into the program with a customized version I've edited. So simply put, the input has to be a series of characters, and I need it stored in an array.
void serialEvent()
{
int arrayPostion = 0;
int i;
int maxArraySize = 20;
char CharArrayInLocal[20];
while (Serial.available() && !stringComplete)
{
char inChar = (char)Serial.read();
CharArrayInLocal[arrayPostion] = inChar;
arrayPostion++;
if (inChar == '\n')
{
stringComplete = true;
}
}
for (int i = 0; i<=19; i++)
{
CharArrayIn[i] = CharArrayInLocal[i];
}
}
This worked for me,
String CharArrayInLocal[20];
String inputString = "";
boolean stringComplete = false;
int i = 0;
void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read();
if (inChar == '\n') {
CharArrayInLocal[i] = inputString;
i++;
stringComplete = true;
inputString = "";
}
else {
inputString += inChar;
}
}
}
I want to create a function that can read a file char by char continuously until some specific char encountered.
This is my method in a class FileHandler.
char* tysort::FileHandler::readUntilCharFound(size_t start, char seek)
{
char* text = new char;
if(this->inputFileStream != nullptr)
{
bool goOn = true;
size_t seekPos = start;
while (goOn)
{
this->inputFileStream->seekg(seekPos);
char* buffer = new char;
this->inputFileStream->read(buffer, 1);
if(strcmp(buffer, &seek) != 0)
{
strcat(text, buffer); // Execution stops here
seekPos++;
}
else
{
goOn = false;
}
}
}
//printf("%s\n", text);
return text;
}
I test this function and it actually works. This is an example to read a file content until new line character '\n' found.
size_t startPosition = 0;
char* text = this->fileHandler->readUntilCharFound(startPosition, '\n');
However, I am sure that something not right is exists somewhere in the code because if I use those method in a loop block, the app will just hangs. I guess the 'not right' things are about pointer but I don't know exactly where. Could you please point out for me?
C++ provides some easy-to-use solutions. For instance:
istream& getline (istream& is, string& str, char delim);
In your case, the parameter would be the equivalent of your text variable and delim would be the equivalent of your seek parameter. Also, the return value of getline would in some way be the equivalent of your goOn flag (there are good FAQs regarding the right patterns to check for EOF and IO errors using the return value of getline)
The lines
if(strcmp(buffer, &seek) != 0)
and
strcat(text, buffer); // Execution stops here
are causes for undefined behavior. strcmp and strcat expect null terminated strings.
Here's an updated version, with appropriate comments.
char* tysort::FileHandler::readUntilCharFound(size_t start, char seek)
{
// If you want to return a string containing
// one character, you have to allocate at least two characters.
// The first one contains the character you want to return.
// The second one contains the null character - '\0'
char* text = new char[2];
// Make it a null terminated string.
text[1] = '\0';
if(this->inputFileStream != nullptr)
{
bool goOn = true;
size_t seekPos = start;
while (goOn)
{
this->inputFileStream->seekg(seekPos);
// No need to allocate memory form the heap.
char buffer[2];
this->inputFileStream->read(buffer, 1);
if( buffer[0] == seek )
{
buffer[1] = '\0';
strcat(text, buffer);
seekPos++;
}
else
{
goOn = false;
}
}
}
return text;
}
You can further simplify the function to:
char* tysort::FileHandler::readUntilCharFound(size_t start, char seek)
{
// If you want to return a string containing
// one character, you have to allocate at least two characters.
// The first one contains the character you want to return.
// The second one contains the null character - '\0'
char* text = new char[2];
text[1] = '\0';
if(this->inputFileStream != nullptr)
{
this->inputFileStream->seekg(start);
// Keep reading from the stream until we find the character
// we are looking for or EOF is reached.
int c;
while ( (c = this->inputFileStream->get()) != EOF && c != seek )
{
}
if ( c != EOF )
{
text[0] = c;
}
}
return text;
}
this->inputFileStream->read(buffer, 1);
No error checking.
if(strcmp(buffer, &seek) != 0)
The strcmp function is used to compare strings. Here you just want to compare two characters.