433 MHz receiver
Arduino environment
The transmitter sends Y, N or M which works just fine. The problem lies in the receivers code. The goal is, after the receiver has value message equal N, its suppose to trigger an if statement which would do a thing. I simply need to have a system that can determine if the receiver takes in a specific value.
void loop()
{
if (vw_get_message(message, &messageLength)) // Non-blocking
{
Serial.print("Received: ");
for (int i = 0; i < messageLength; i++)
{
Serial.write(message[i]);
const char *p = reinterpret_cast<const char*>(message);
if(p == "N")
{
Serial.print("if statement works when = N");
}
}
}
}
The problem, is it simply does not do the job, and after 2 weeks of struggle, I am completely at a loss. This code will compile and run, but the if statement is completely ignored.
if (p=="N") compares two pointers. While the contents they point to can be identical, that does not mean the pointers themselves are equal.
You may want strcmp (C style) or std::string::operator== (canonical C++)
Thankfully I was able to find a solution.
The working code:
void loop()
{
if (vw_get_message(message, &messageLength))
{
for (int i = 0; i < messageLength; i++)
{
const char *p = reinterpret_cast<const char*>(message);
if(p[0] == 'Y')
{
Serial.print(" - Yes");
break;
}
else if(p[0] == 'N')
{
Serial.print(" - No");
break;
}
}
Serial.println();
}
}
The point of const char *p = reinterpret_cast<const char*>(message); was to turn message, which is a byte, into a char. Yes p is a pointer, but it's pointing to a char, so with that, I can get the data in the char that p is pointing to by simply doing p[#]. A simple if statement can now be made
if(p[0] == 'M')
{
...
}
What type is message? Anyway, right now you are comparing value stored in p (so the address in memory, not what there is) to a string (notice double quotes). Why don't you just do
if(message[i] == 'N')
Single quotes here mean char literal.
Related
Here is the code:
void Reader::read(short& in) {
char* str = new char[6];
char* strbeg = str;
cin.getline(str, 6);
in = 0;
int value = 0;
short sign = 1;
if (*str == '+' || *str == '-') {
if (*str == '-' ) sign = -1;
str++;
}
while (isdigit(*str)) {
value *= 10;
value += (int) (*str - '0');
str++;
if (value > 32767) {
cout.write("Error, value can't fit short. Try again.\n", 41);
delete[] strbeg;
read(in);
return;
}
}
if (sign == -1) { value *= -1; }
in = (short) value;
delete[] strbeg;
return;
}
What happens is that if I type 999999999, it calls itself but on fourth line it's not gonna ask for input again. Debugger couldn't give much info as it is more language-specific question. Thank you in advance. Have a nice day!
Yes, the goal is to parse input as short. I know about losing 1 from min negative, wip :)
=== edit ===
I've tried goto... No, same thing. So it's not about visible variables or addresses, I guess.
=== edit ===
I can't use operator >> as it is forbidden by the task.
999999999 will cause an overflow, thus failbit is set for cin. Then your program reach read(in), then the cin.getline(). Here, beacause of failbit, cin will not ask any input again.
If you tried to figure out why in my code cin do ask for more input, you might find out all this by yourself.
I write you an example.
#include <iostream>
#include <climits>
using namespace std;
int main() {
char str[6];
short x = 0;
bool flag = false;
while (flag == false) {
cin.getline(str, 6);
flag = cin.good();
if (flag) { // if read successfully
char *p = str;
if (*p=='-') // special case for the first character
++p;
while (*p && *p>='0' && *p<='9')
++p;
if (*p) // there is a non digit non '\0' character
flag = false;
}
if (flag == false) {
cout << "An error occurred, try try again." << endl;
if (!cin.eof()) {
cin.unget(); // put back the possibly read '\n'
cin.ignore(INT_MAX, '\n');
}
cin.clear();
} else {
// str is now ready for parsing
// TODO: do your parsing work here
// for exemple x = atoi(str);
}
}
std::cout << x << std::endl;
return 0;
}
As we have discussed, you don't need new.
Check whether the string read is clean before parsing. If you mix checking and parsing, things will be complicated.
And you don't need recursion.
Read characters from stream by istream::getline seems to be the only option we have here. And when an error occurred, this function really doesn't tell us much, we have to deal with overflow and other problem separately.
im busy writing a line of code for my study.
I already have gotten quite far on the assignment but i keep running into the same problem.
On the swap function i keep running into a segmentation fault when a character is inputted(word & word2) that is not in the main 'dictionary' string.
Could someone explain to me what is causing the problem and how i can solve it? Sorry if anything isnt clear, i've just started learning c++.
code where segmentation fault occures:
void swapWords(char **dict, char *word, char *word2)
{
int i;
int d;
int x;
int y;
char *tmp;
while (1){
for(i = 0; i < MAX_NUMBER_OF_WORDS; i++)
{
if(strcmp(word, dict[i]) != 0)
{
if(i == MAX_NUMBER_OF_WORDS -1)
{
printf("Cannot swap words. Atleast one word missing in the dictionary.\n");
goto error;
}
}
else
{
x = i;
break;
}
}
for(d = 0; d < MAX_NUMBER_OF_WORDS; d++)
{
if(strcmp(word2, dict[d]) != 0)
{
if(d == MAX_NUMBER_OF_WORDS -1)
{
printf("Cannot swap words. Atleast one word missing in the dictionary.\n");
goto error;
}
}
else
{
y = d;
break;
}
}
tmp = dict[x];
dict[x] = dict[y];
dict[y] = tmp;
error: break;
}
}
The entire code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#define MAX_NUMBER_OF_WORDS 10
void swapWords(char **dict, char *word, char *word2)
{
int i;
int d;
int x;
int y;
char *tmp;
while (1){
for(i = 0; i < MAX_NUMBER_OF_WORDS; i++)
{
if(strcmp(word, dict[i]) != 0)
{
if(i == MAX_NUMBER_OF_WORDS -1)
{
printf("Cannot swap words. Atleast one word missing in the dictionary.\n");
goto error;
}
}
else
{
x = i;
break;
}
}
for(d = 0; d < MAX_NUMBER_OF_WORDS; d++)
{
if(strcmp(word2, dict[d]) != 0)
{
if(d == MAX_NUMBER_OF_WORDS -1)
{
printf("Cannot swap words. Atleast one word missing in the dictionary.\n");
goto error;
}
}
else
{
y = d;
break;
}
}
tmp = dict[x];
dict[x] = dict[y];
dict[y] = tmp;
error: break;
}
}
void removeWord(char **dict, char *word)
{
int i;
int d;
for(i = 0; i < MAX_NUMBER_OF_WORDS; i++)
{
if(strcmp(dict[i], word) == 0)
{ dict[i] = NULL;
for(d = i+1; d < MAX_NUMBER_OF_WORDS; d++)
{ if(dict[d] == NULL)
{ dict[i] = dict[d-1];
dict[d-1] = NULL;
break;
}
}
break;
}
}
}
void printDict(char **dict)
{
int i = 0;
if(dict[0] == NULL)
{
printf("The dictionary is empty.\n");
}
else{
while (dict[i] != NULL)
{
printf("- %s\n", dict[i]);
i++;
}
}
}
void addWord(char **dict, char *word)
{
int d;
char *word1;
for(d = 0; d < MAX_NUMBER_OF_WORDS; d++)
{
if (dict[d] == NULL)
{
word1 = (char*) malloc(sizeof(char)*(strlen(word) + 1));
strcpy(word1, word);
dict[d] = word1;
break;
}
}
}
int numberOfWordsInDict(char **dict)
{
int i = 0;
int d;
for (d = 0; d < MAX_NUMBER_OF_WORDS; d++){
if(dict[d] != NULL)
{
i++;
}
}
return i;
}
int main()
{
char *dict[MAX_NUMBER_OF_WORDS] = {};
char word[36];
char word2[36];
char c;
int i;
while(printf("Command (a/p/r/s/q): "))
{
scanf(" %c", &c);
switch (c){
case 'p': printDict(dict);
break;
case 'a': printf("Enter a word: ");
scanf("%s", word);
addWord(dict, word);
break;
case 'n': i = numberOfWordsInDict(dict);
printf("%d\n", i);
break;
case 'r': printf("Remove a word: ");
scanf("%s", word);
removeWord(dict, word);
break;
case 's': printf("Swap two words:\n");
printf("Enter first word: ");
scanf("%s", word);
printf("Enter second word: ");
scanf("%s", word2);
swapWords(dict, word, word2);
break;
case 'q': return 0;
}
}
}
It will be most helpful to your studies as a student if you find the actual error yourself, though Marco and πάντα ῥεῖ may be right. However, here are a few things to think about, as this will definitely not be your last segfault problem as a programmer (I had at least 20 this month alone).
A segmentation fault is almost always caused by the code trying to modify or read memory that it doesn't have permission to read or modify. When the program starts, it is given a chunk of memory (RAM) to work with. For security reasons, no program is allowed to work with memory outside of that chunk. There are other limitations at play too.
As a general rule, if you try to read memory past the end of an array, you have a high risk of getting a segfault, or in other cases, garbled data. The official word on this actually comes from C, C++'s parent language, in that accessing past the end of an array causes "undefined behavior". Or, as it was once said on USENET, "it is legal for the compiler to make demons fly out of your nose". The behavior is totally unpredictable. Thankfully, that undefined behavior usually IS a segfault.
By the way, if you try to access an uninitialized array, similar weirdness can happen.
NOW, since you are accessing the elements of your array via a loop, another possible cause is that your loop is continuing beyond where you think it is. Sometimes it is helpful to modify your code so that the loop's iterator (i in your case) is printed out each iteration. This can help you catch if the loop is going beyond where it should.
In short, check...
Did I initialize all of my arrays before I tried to read or write
them?
Are my loops starting and stopping where I expected? Check for
"off-by-one" errors (i.e. starting at 1 instead of 0), infinite
loops (forgot to increment the iterator or the stop condition is
never true), and other logical errors.
Am I trying to read/write past the end of the array?
If I'm working with a C-string, did I forget the NULL terminator?
In addition to your debugger, which you should learn how to use well, tools like valgrind are instrumental in finding the cause of memory errors. Oftentimes, it can point you to the exact line of code where the segfault is occuring.
I had figured out myself the problem was in the strcmp. I know that figuring out a problem by myself is the best way to learn and I tried, but I just couldn't figure out why it was returning a seg fault. As this is my fifth assignment I'm only just getting to know how array's and pointers work. I assumed that the array was already initialized as 'NULL', as seen I was already comparing the pointer to 'NULL' in the addWord function. To assume this is ofcourse very stupid of me. I might not have figured the problem out by myself, yet it is still something I will not be forgetting anymore.
Most probably the segmentation fault happens here:
if(strcmp(word, dict[i]) != 0)
Infact it is quite likely that that i > becomes bigger than the size of your dict and if your dict has 3 elements and you try to access the 4th you are accessing an unknown area or ram and that causes a segmentation fault.
The solution is to make sure your for loop stops at the last element of the dictionary with the solution πάντα ῥεῖ has proposed in the above comment.
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;
}
}
}
This is not homework, but study for a midterm.
I cannot use any type of array indexing such as str[i] or *(str+i)
I have to take the c-string "EECS280ISAWESOME" and substitute the 'E' with the c-string "XY". I also have to allow for multiple length of the "XY" variable.
The following main is given:
int main () {
const char* S = "EECS280ISAWESOME";
const char* P = "XY";
char result[256];
subsituteChar(S,P,'E', result);
cout << result << endl;
}
My solution seems complex/bad practice/and ugly. I could do it better with the use of deferencing and adding *(R+1) but I dont think it's allowed.
void subsituteChar(const char* S, const char* P, char c, char* R) {
while(*S != '\0') {
if(*S == c) {
const char* PP = P;
while (*P != '\0') {
*R = *P;
R++;
P++;
}
P = PP;
} else {
*R = *S;
R++;
}
S++;
}
}
This works but I am left with XYXYCS280ISAWXYSOMXY2. I have no idea where the weird 2 has came from.
Since this is a study problem, here's a hint to get you started. Try initializing your result array. I did this:
char result[256];
for (int i = 0; i < 250; ++i)
result[i] = 'a';
result[250] = 0;
Now run your code again, and you'll see that you've got lots of 'a' characters at the end of your output, up to the point where you get to character 250. That is, you'll see:
"XYXYCS280ISAWXYSOMXYaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
If you want to figure out the rest for yourself, STOP READING NOW.
The problem is that you're not explicitly null terminating your string.
Note that it's not a problem with your last character of S being replaced, but rather with your while loop's terminal condition. Since you aren't manually copying over the '\0' character from S, you're left hoping that the result array is full of '\0' characters, which C and C++ don't guarantee.
Simply adding the following line to the end of your substituteChar function will solve the problem:
*R = '\0';
Does this fit?
#include<stdio.h>
int main () {
const char* S = "EECS280ISAWESOME";
const char* P = "XY";
char result[256];
while(*S)
{
if(*S=='E')
printf("XY");
else
printf("%c", *S);
S++;
}
}
Your code is perfectly correct along with small error. There is a fact of string , everry
string should be terminate with null character. so just add the *R ='\0'; at the end of
while function and this algorithm works perfectely.
For a homework assignment, I need to implement a function which takes a char *s and a char c and return the index of c if found, and -1 otherwise.
Here's my first try:
int IndexOf(const char *s, char c) {
for (int i = 0; *s != '\0'; ++i, ++s) {
if (*s == c) {
return i;
}
}
return -1;
}
Is that an okay implementation, or are there things to improve?
EDIT Sry, didn't mention that I only should use pointer-arithmetic/dereferencing, not something like s[i]. Besides, no use of the Standard Library is allowed.
Yes, it's fine, but you could increment only one variable:
int IndexOf(const char *s, char c) {
for (int i = 0; s[i] != '\0'; ++i) {
if (s[i] == c) {
return i;
}
}
return -1;
}
Won't make any serious difference though, mostly a matter of taste.
Looks fine to me, at least given the signature. Just to add to the "many slightly different ways to do it" roadshow:
int IndexOf(const char *s, const char c) {
for (const char *p = s; *p != 0; ++p) {
if (*p == c) return p - s;
}
return -1;
}
Slight issue - p-s isn't guaranteed to work if the result is sufficiently big, and certainly goes wrong here if the correct result is bigger than INT_MAX. To fix this:
size_t IndexOf(const char *s, const char c) {
for (size_t idx = 0; s[idx] != 0; ++idx) {
if (s[idx] == c) return idx;
}
return SIZE_MAX;
}
As sharptooth says, if for some didactic reason you're not supposed to use the s[i] syntax, then *(s+i) is the same.
Note the slightly subtle point that because the input is required to be nul-terminated, the first occurrence of c cannot be at index SIZE_MAX unless c is 0 (and even then we're talking about a rather unusual C implementation). So it's OK to use SIZE_MAX as a magic value.
All the size issues can be avoided by returning a pointer to the found character (or null) instead of an index (or -1):
char *findchr(const char *s, const char c) {
while (*s) {
if (*s == c) return (char *)s;
++s;
}
return 0;
}
Instead you get an issue with const-safety, the same as the issue that the standard function strchr has with const-safety, and that can be fixed by providing const and non-const overloads.
Here's a way to do it without keeping track of the index:
int IndexOf(const char *s, char c) {
const char *p = s;
while (*p != '\0') {
if (*p == c) {
return p - s;
}
++p;
}
return -1;
}
This is not necessarily better than your solution. Just demonstrating another way to use pointer arithmetic.
FWIW, I would define the function to return size_t rather than int. Also, for real-world usage (not homework), you would probably want to consider what the proper behavior should be if s is a NULL pointer.
Yours is perfectly fine, as far as it goes. You should also write a simple test program that tests for the first char, last char, and a missing char.
Piling on to the 'other ways to do it' group, here is one with no break, a single return, and showing off pointer arithmetic. But, beware: if I were grading your homework, I would grade yours higher than mine. Yours is clear and maintainable, mine needlessly uses ?: and pointer subtraction.
#include <stdio.h>
int IndexOf(const char *s, const char c)
{
const char * const p = s;
while(*s && *s != c) s++;
return (*s) ? s-p : -1;
}
#ifdef TEST
int main()
{
printf("hello, h: %d\n", IndexOf("hello", 'h'));
printf("hello, g: %d\n", IndexOf("hello", 'g'));
printf("hello, o: %d\n", IndexOf("hello", 'o'));
printf("hello, 0: %d\n", IndexOf("hello", 0));
}
#endif
The output of this program is:
hello, h: 0
hello, g: -1
hello, o: 4
hello, 0: -1
There's a typo (index instead of i), but otherwise it looks fine. I doubt you'd be able to do much better than this (both in terms of efficiency and code clarity.)
yes, you shoule return i;
not index.
I think it's just a typo.
Another variant, as an old school C programmer may write it:
int IndexOf(const char *s, char c) {
int i = 0;
while (s[i] && (s[i] != c)) ++i;
return (s[i] == c)?i:-1;
}
Benefices : short, only one variable, only one return point, not break (considered harmful by some people).
For clarity I would probably go for the one below:
int IndexOf(const char *s, char c) {
int result = -1;
for (int i = 0; s[i] != 0; ++i) {
if (s[i] == c) {
result = i;
break;
}
}
return result;
}
It uses a break, but has only one return point, and is still short.
You can also notice I used plain 0 instead of '\0', just to remind that char is a numeric type and that simple quotes are just a shorthand to convert letters to their values. Obviously comparing to 0 can also be replaced by ! in C.
EDIT:
If only pointer arithmetic is allowed, this does not change much... really s[i] is pointer arithmetic... but you can rewrite it *(s+i) if you prefer (or even i[s] if you like obfuscation)
int IndexOf(const char *s, char c) {
int result = -1;
for (int i = 0; *(s+i) != 0; ++i) {
if (*(s+i) == c) {
result = i;
break;
}
}
return result;
}
For a version that works for most cases on x86 systems, one can use:
int IndexOf(char *s, char sr)
{
uint_t *x = (uint_t*)s;
uint_t msk[] = { 0xff, 0xff00, 0xff0000, 0xff000000 };
uint_t f[4] = { (uint_t)sr, (uint_t)sr << 8, (uint_t)sr << 16, (uint_t)sr << 24 };
uint_t c[4], m;
for (;;) {
m = *x;
c[0] = m & msk[0]; if (!c[0]) break; if (c[0] == f[0]) return (char*)x - s;
c[1] = m & msk[1]; if (!c[1]) break; if (c[1] == f[1]) return (char*)x - s + 1;
c[2] = m & msk[2]; if (!c[2]) break; if (c[2] == f[2]) return (char*)x - s + 2;
c[3] = m & msk[3]; if (!c[3]) break; if (c[3] == f[3]) return (char*)x - s + 3;
x++;
}
return -1;
}
Limitations:
It breaks if the string is shorter than four bytes and its address is closer to the end of a MMU page than four bytes.
Also, the mask pattern is little endian, for big endian systems the order for the msk[] and f[] arrays has to be reversed.
In addition, if the hardware can't do misaligned multi-byte accesses (x86 can) then if the string doesn't start at an address that's a multiple of four it'll also fail.
All of these are solveable with more elaborate versions, if you wish...
Why would you ever want to do weird things like that - what's the purpose ?
One does so for optimization. A char-by-char check is simple to code and understand but optimal performance, at least for strings above a certain length, tends to require operations on larger blocks of data. Your standard library code will contain some such "funny" things for that reason. If you compare larger blocks in a single operation (and with e.g. SSE2 instructions, one can extend this to 16 bytes at a time) more work gets done in the same time.