Arduino function interfering with loop() code - arrays

I have, among others, the following lines in the loop function:
item = String(buffer);
Serial.println(item);
Where item is a String and buffer a char array. This works perfectly until I add a function at the end of the file (outside of the loop function):
void storeData(String item){
Serial.println("StoreData");
for (int k=0; k<11; k++){
Serial.print("*");
if(item == products[k]){
items[index] = names[k];
index++;
Serial.print("\n");
Serial.print(item);
Serial.print("\t");
Serial.print(names[k]);
}
}
}
Which compares the string item to a list of values and stores the corresponding name if the value is found.
When I add this code at the end, even if I DON'T call on the function, the output of the conversion becomes:
978973103 Á
9789731030418
Where the first value is the incorrect conversion and the second one is the value of buffer.
What could possibly be happening? I've restarted and rewired and redone everything from scratch over and over again.

It may be possible you are running out of the 2K SRAM. Arrays of Strings can quickly use it up.
Additionally I recommend using the F() function as not use use RAM for constanst. e.g. Serial.println(F("StoreData");
The latest IDE's show the expected RAM usage. but this is a guess. If it is even close then there is likely an issue. I use the following MemoryFree library at specific points in the code to reveal the highwater.

Since item is string. I think you can try using
Serial.println(item);
instead of
Serial.print(item);
in you storeData function. Also similarly for other strings

Related

How to recursively return string value in C?

Trying to learn something here more than solve the specific problem. Please help me towards some best practices to apply in this situation, and if possible some clarification of why. Thanks in advance for your assistance.
Basically I'm brute-force breaking a very simple hash algorithm, within known limits. Function tests possibilities of a string (within a length limit) against the hash, until it matches the hash passed. Then recursion should stop all iterations and return the string that matched. The iteration works, but when the answer is found, it seems that each run of the function doesn't get the value returned by its call of the same function.
Here's the code of the function, with extra comments for clarity:
//'hash' is the hash to be replicated
//'leading' is for recursive iteration (1st call should have leading=="")
//'limit' is the maximum string length to be tested
string crack(string hash, string leading, int limit)
{
string cracked=NULL, force=NULL, test=NULL;
//as per definition of C's crypt function - validated
char salt[3] = {hash[0], hash[1], '\0'};
// iterate letters of the alphabet - validated
for(char c='A'; c<='z'; c++)
{
// append c at the end of string 'leading' - validated
test = append(leading,c);
// apply hash function to tested string - validated
force = crypt(test,salt);
// if hash replicated, store answer in 'cracked' - validated
if(strcmp(hash,force)==0)
{
cracked = test;
}
else
{
// if within length limit, iterate next character - validated
if(strlen(test)<=limit+1)
{
// THIS IS WHERE THE PROBLEM OCCURS
// value received when solution found
// is always empty string ("", not NULL)
// tried replacing this with strcpy, same result
cracked = crack_des(hash,test,limit);
}
}
// if answer found, break out of loop - validated
if(cracked){break;}
// test only alphabetic characters - validated
if(c=='Z'){c='a' - 1;}
}
free(test);
// return NULL if not cracked to continue iteration on level below
// this has something to do with the problem
return cracked;
} // end of function
From the little bit I recall of pointers, I'd guess it is something with passing references instead of values, but I don't have enough knowledge to solve it. I have read this thread, but this suggestion doesn't seem to solve the issue - I tried using strcpy and got the same results.
Disclaimer: this is an exercise in 2018's CS50 by Harvard at EDX. It won't affect my grading (have already submitted two perfect exercises for the week, which is what is required) but as stated above I'm looking to learn.
Edit: edited the tag back to C (as clarified in comments, string is from string.h, and append was coded by me and validated several times over - I'll get to TDD in a while). Thanks all for your comments; problem solved and lessons learned!
I found a bug in the code, but I am not sure whether it is the root cause of your problem.
When the code hit the line:
strcmp(hash,force)==0
then you will assign the string pointed by 'test' to 'cracked':
cracked = test;
then this line is hit:
if(cracked){break;}
then the loop is breaked, and the next line:
free(test);
this line will free the string pointed by test, and remember that it is the same string pointed by 'cracked', thus you returned a string which is already freed.
What will happened to the string is dependent on your compiler and libc. You can try to fix this problem by allocating memory for 'cracked':
cracked = strdup(test);
Also, there are memory leaks caused by the 'test' and 'force' string, but they should be irrelevant to your problem.

Why am I getting this huge numbers in C?

I'm trying to teach myself C using Kernighan's book and I'm supposed to make a graph that indicates how many letters there are in each word. I haven't got to the "plotting" part as I'm getting really weird and enormous numbers at the output. Right now I'm just trying to have the value of the first and second elements of the array "arreglo" printed.
The code is the following:
#include <stdio.h>
#define ARRAY_SIZE 100
/*#define AUX 0
#define AUX2 0*/
main()
{
int s,j,noletra,i,arreglo[ARRAY_SIZE],otros, nopalabra, c;
int a;
nopalabra=1;
while((c=getchar())!=EOF)
{
if(c==' '||c=='\t'||c=='\n')
++nopalabra;
else
++arreglo[nopalabra];
}
printf("%d",arreglo[1],arreglo[2]);
}
The reason I'm trying to know the value in the second element in the array is that the first element has the correct value. The code is supposed to add 1 to the array index which is the number of words each time a space, tab or \n is typed and to add 1 to the array element whenever something different than the previously mentioned characters is typed (Letters). Right now it´s supposed to print correctly the number of the letters of two words, the first element is correctly printed but the second is a huge number, the output is:
alan amaury
^Z
4 8257542
--------------------------------
Process exited after 7.773 seconds with return value 9
Press any key to continue . . .
The output is supposed to be 4 7. I'm using a compiler in windows so EOF should be Ctrl+Z
Any help that I could get from you will be appreciated :)
At least these problems.
int arreglo[ARRAY_SIZE]; is not initialized before its elements are incremented. This is the mostly likely cause of "Why am I getting this huge numbers" #ikegami
// int arreglo[ARRAY_SIZE];
// replace with
int arreglo[ARRAY_SIZE] = { 0 };
Code can access out of array bounds as nopalabra is not confined to 0 to 99.
#define ARRAY_SIZE 100
int arreglo[ARRAY_SIZE];
++arreglo[nopalabra]; // No access protection
printf("%d",arreglo[1],arreglo[2]); only prints arreglo[1]
Logic flow is incorrect to "make a graph that indicates how many letters there are in each word."
main() return type not coded.
Some pseudo-code as an alternative
int main(void) {
set all arreglo[] to 0
int nopalabra = 0;
part_of_word = false; // Keep track of word state
loop forever {
get a character into c
if c is a separator or EOF
if (part_of_word) {
arreglo[nopalabra]++;
part_of_word = false;
nopalabra = 0;
if (c == EOF) break loop
} else {
nopalabra++;
part_of_word = true;
}
}
print out results
}
First, try the solution answered before, changing the printf() call.
If there is still a problem try:
printf("%d %d \n",arreglo[1],arreglo[2]);
Just before the while loop, to see if the "arreglo" array is initialize to 0's or just random values.
On the side:
Your call to printf() has more parameters than covered by the format string.
So you should clean up your code to something similar to
printf("%d %d\n", arreglo[1], arreglo[2]);
Concerning the strange output:
A way of getting surprising values is using non-initialised variables.
In your case the lack of initialisation affects the array arreglo.
Make sure to initialise it, so that all counting starts on a meaningful value.
Another way of getting seemingly very high values is printing several numbers next to each other, without separating white space in between.
So the " " and the "\n" in the format string I proposed are quite relevant.
the question is: "Why am I getting this huge numbers in C?"
the answer is: you have not assigned anything to arreglo array, and since you have not initialized it, you got some random values that have been there in memory. Trust me on this, I have run your code in debugger, which I also highly recommend a a standard practice while lerning to program.
Also, this is a common mistake where the format specifier is not written:
printf("%d",arreglo[1],arreglo[2]);
See if using printf("%d","%d",arreglo[1],arreglo[2]) solves your problem.
By the way, K&R book is very old, and written at the time where there have been no other C books. There are better ways to learn C.

I have a for loop that refuses to stay within the defined limits. The limits have been verified (by printing) during runtime

I am inserting the snippet of code that is causing the problem. Please focus on the uncommented code, as that is the actual code. The commented out code was there to help me debug. Apologies for poor readability, but I decided to let the comments stay, in case anyone had a doubt as to how I arrived at my diagnosis of the problem.
void backProp(double back_prop_err, double x[])// x is the complete output of input layer neurons.
{
//j++;
//printf("\nA"); printf("\nj=%d",j);
error = out*(1-out)*back_prop_err;
printf("\nB:%20.18f",error);
//if(j==8)
//{
// printf("\nstart= %d, stop= %d",start, stop);
// temp=1;
//}
for(int i=start; i<= stop; i++)
{
// if(i==24)
// break;
// if(temp==1)
// {
// printf("\nstart= %d and stop= %d", start, stop); //temp=0;
// }
//j++;
//printf("\nC");
del_w[i] = c*error*x[i];
printf("\ndel_w[%d]=%20.18f",i,del_w[i]);
}
}
Please ignore the commented out sections. They were there to display stuff on the screen, so I could debug the code.
The Problem:
There are 3 classes, let's call them A, B and C. A has 24 objects, stored as an array. B has 10 objects, again in an array and C has only 1 object.
The above code is from the B class.
for class B's object[7], the value of start and stop (see above code) is 0 and 23, respectively. I have verified the same during runtime using the commented out pieces of code that you see above.
Yet, when the backProp function is called, at that particular for loop, an infinite loop is entered. The value of i keeps increasing without bound till DevC++ crashes. The commented out if(i==24) was put there to prevent that.
This only happens with class B's object[7]... Not with the previous 7 objects (object[0]...object[6]). For them, that particular loop starts and stops as per the set "start" and "stop" variables. Is it important that for those objects, "stop" is a small number (like 6 or 12 max)?
Class B's object[8] and object[9] also have stop = 23, which leads me to suspect that they too would face the same problem.
The Question: Why is this happening? start and stop variables are set. Why isn't the loop staying within those limits?
I have tried to keep this as concise as possible. Thank you for your efforts at reading this wall of a question.
EDIT: start and stop are private variables of class B (of which, the above function is a public function). They are set to their respective values using another public function, which I call from main.
j is somewhat embarrassing. It's a global static integer, initially set to 0. The reason I did this is so that I could count when class B's object[7] was accessing the backProp function. j gets incremented each time backProp is called, and as it's a static global, it acts as a counter so I can count till the object[7].
As per Oak's suggestion, I am putting up the link for the code here: http://pastebin.com/ftxBGs2y
Yeah, efforts are on to learn the DevC++ debugger. :P
I am pretty sure I don't have any problems with the dimensions of x. I will look into the matter again though.
My bet is that you are modifying i unintentionally when writing elements to del_w[]: perhaps the number of elements in the array is not large enough for what you are doing.
I say this because i and del_w could be close to each other on the stack but don't know for sure because I don't know how you allocated the memory for del_w.
Check the bounds of your arrays carefully, remembering that they are zero based.
It will not be anything funny in the for loop; you can trust the compiler!
But use a good debugger though or you'll waste so much time.

printf() changing treatment of variable in C

I have a pretty simple function in my program using the secant method to find a root of a function. It works fine with the printf() that's indicated below. But if I comment it out, the loop endlessly repeats. I have no idea why...
I've read about printf changing a variable, but I don't see anything on it changing the storage of the variable. Am I missing something? It's not a great solution to have it print, since the iterates are not important and the function is called millions of times.
double guess1=500.;
double y1=estimater(r,volume,guess1,adm,tm,rr[r]);
double guess2=adm/30.;
double y2=estimater(r,volume,guess2,adm,tm,rr[r]);
int i;
double guess3=0.;
double y3;
double tol =heightTOL;
int secmax=SECANTMAX;
for(i=1;i<=secmax;i++){
guess3=guess2-y2*(guess2-guess1)/(y2-y1);
if(guess3>adm/2.){
guess3=adm/2.;
}
if(guess3<=0.){
guess3=0.;
}
y3=estimater(r,volume,guess3,adm,tm,rr[r]);
y1=y2;
y2=y3;
guess1=guess2;
guess2=guess3;
if(fabs(guess2-guess1)<tol){
break;
}
if(i==secmax){
printf("\nRan out of iterations in height finder\n");
}
printf("%d %f",i,guess3); //THIS ONE HERE!!!!!!!!
}
return guess3;
printf is not changing your data at all. The only way the printf family of functions can have any effect on your data is if you use the %n format specifier (which writes into the variable whose address you pass) or if you're doing something which invokes undefined behavior, like passing the wrong format arguments. You're not doing either of those things here (your format strings are correct), so your bug lies elsewhere.
Check that all your array accesses are in bounds. Try running your code in Valgrind or other validators to try to find memory errors.

Lower cpu usage on searching a big char array

I'm searching for few bytes in a char array. The problem is that on slower machines the process gets up to 90%+ cpu usage. How to prevent that? My code is:
for(long i = 0; i < size - 5; ) {
if (buff[++i] == 'f' && buff[++i] == 'i' && buff[++i] == 'l' && buff[++i] == 'e') {
printf("found at: %d\n", i);
}
}
EDIT:
The string "file" is not null-terminated.
This looks like an attempt at very naive string search, I'd suggest you use either the standard functions provided for this purpose (like strstr) and/or research string search algorithms like Boyer-Moore.
The linked Wikipedia article on Boyer-Moore shows quite well why moving along one character at a time on a mismatch (like you do) is not necessary - it's an interesting read.
EDIT: also look at this page, it has a nice animated presentation that shows how BM does its job.
EDIT2: regarding the string not being nullterminated: either you
buff[size] = 0;
terminate it yourself, and use strstr, or you have a look at the BM code from the page I linked, that works with lengths, ie it will work with strings without terminating 0.
There is nothing wrong with getting 90% utilisation, since the algorithm is CPU-bound. But...
Unless you expect the search term to be on a 32-bit word boundary, the code is broken. If the word 'file' begins on the second character of the buffer, you will simply skip over it. (EDIT: Short-circuit eval means the code is correct as it stands. My mistake.)
Don't roll your own code for this; use strstr.
Try just storing a list of values where 'file' is found and print them out after the loop. It will prevent context switches and will enable the CPU to use the cache better. Also put i in a register.

Resources