Array not printing

Hi,

The array I created contains sales of 5 employees, for a 2x5 array

Row 1 = sales
Row 2 = bonus (bonus = sales * 0.09)

I can get Row 1 populated by entering data. What I'm stuck on is populating Row 2 of bonus data from Row 1.

This codes works

void data_entry(int metrics, int employees, int employees_data[][employees_num])
{
  //enter data for each employee
  for (int i = 0; i < employees; i++)
  {
    Serial.print("Enter gross sales for employee ");
    Serial.print(i+1);
    Serial.print(": $");
    while (Serial.available() == 0) {}  // waits until data is entered into serial monitor
    employees_data[0][i] = Serial.parseInt();    //takes incoming characters and converts it to a number. This is read into the buffer altogether. Row 1 is contstand, updates column num each pass
    Serial.println(employees_data[0][i]);    // test for printing value entered from array
            
    // flush input buffer, do before asking for new input.  Notes: https://forum.arduino.cc/t/serial-input-basics-updated/382007
    while (Serial.available() > 0) {Serial.read();}      
  }
}

This code doesn't work. It doesn't even print the array data from Row 1, which I was able to print in the above code. What could be going wrong?

// calculate bonus and fill these into employee data array
void pay_calculations(int metrics, int employees, int employees_data[][employees_num])
{ 
  //Bonus 
    // multiply each employee data element by bonus %
    // store values in Row 2 of array for each element

    for (int i = 0; i < employees; i++)
    { 
          employees_data[1][i] = employees_data[0][i] * 0.09;  // multiplies an employees gross weekly pay by 9% for bonus, and stores in Row 2 of employee_data array
          Serial.println(employees_data[0][i]);    // test for printing Row 1, column 'n'
          Serial.println(employees_data[1][i]);    // test for printing Row 2, column 'n'          
    }
}

Full code

/**********Libraries**********/
#include <Arduino.h>



/**********Global Variables**********/
const int metrics = 3;      // # of financial data metric for employees to track, array row
  const int metrics_count_num = metrics; // don't touch
  // may have to make seperate var for passing into array, copy this value
const int employees = 5;  // # of employees, array column
  const int employees_num = employees; // don't touch
  // may have to make seperate var for passing into array, copy this value
const int employees_data[metrics][employees];  // mxn array
const int bonus[9];  // # of employee bonus pay ranges


/**********Function Prototypes**********/
void data_entry(int metrics, int employees, int employees_data[][employees_num]);
void pay_calculations(int metrics, int employees, int employese_data[][employees_num]);
void print_bonus(int metrics, int employees, int employees_data[][employees_num], int bonus[]);

/**********Setup**********/
void setup() 
{
  Serial.begin(9600);
  data_entry(metrics, employees, employees_data);
  pay_calculations(metrics, employees, employees_data);
}

/**********Main Loop**********/
void loop() 
{

}

/**********Function Definition**********/
void data_entry(int metrics, int employees, int employees_data[][employees_num])
{
  //enter data for each employee
  for (int i = 0; i < employees; i++)
  {
    Serial.print("Enter gross sales for employee ");
    Serial.print(i+1);
    Serial.print(": $");
    while (Serial.available() == 0) {}  // waits until data is entered into serial monitor
    employees_data[0][i] = Serial.parseInt();    //takes incoming characters and converts it to a number. This is read into the buffer altogether. Row 1 is contstand, updates column num each pass
    Serial.println(employees_data[0][i]);    // test for printing value entered from array
            
    // flush input buffer, do before asking for new input.  Notes: https://forum.arduino.cc/t/serial-input-basics-updated/382007
    while (Serial.available() > 0) {Serial.read();}      
  }
}


// calculate bonus and fill these into employee data array
void pay_calculations(int metrics, int employees, int employees_data[][employees_num])
{ 
  //Bonus 
    // multiply each employee data element by bonus %
    // store values in Row 2 of array for each element

    for (int i = 0; i < employees; i++)
    { 
          employees_data[1][i] = employees_data[0][i] * 0.09;  // multiplies an employees gross weekly pay by 9% for bonus, and stores in Row 2 of employee_data array
          Serial.println(employees_data[0][i]);    // test for printing Row 1, column 'n'
          Serial.println(employees_data[1][i]);    // test for printing Row 2, column 'n'          
    }
}

const int employees_data[metrics][employees];  // mxn array
const int bonus[9];  // # of employee bonus pay ranges

You have made the arrays const.

There are a number of improvements that can be made. It is more than what you might expect. If you walk through it step by step, you should make better code in the future.

  1. Don't #include <Arduino.h>. You may remove that.
  2. Use the same style for the text of the code everywhere, use the indents consistent. In Arduino IDE 2.0, right-click and select "Format Document".
  3. Follow the KISS rule. I don't understand why you have two variables for the number of employees and two variables for the number of metrics.
  4. Go to the preferences in the Arduino IDE, set "Compiler warnings" to "All". You will notice that the compiler warns you that a 'const' variable can not be changed (as david_2018 already wrote). The warnings for a unused parameter may be ignored.
  5. You don't need function prototyping. The Arduino pre-processor does that for you. Sometimes the Arduino pre-processor gets confused, then you have to add it after all.
  6. Please don't use the same name for global variables and for function parameters. Although it is valid code (the compiler will use the most local variable), but you will get confused easily.
  7. I don't like multiplying an integer with 0.09. If you need do to that, then use casting to show what is going on. Or make the 'employees_data' an array of floats.
  8. How wide is your screen ? Wall to wall ? Some comments are very long on the same line. I have to keep on scrolling sideways a long time to read it.
  9. If you present the result to the Serial Monitor in a nicer way, then that will be helpful for yourself when developing code.
  10. There is a bug in the code. If the gross sale is larger than a integer can hold, then it will convert to a negative number or a smaller number. The Serial.parseInt() returns a long value that is converted to a integer. See the reference: Serial.parseInt() - Arduino Reference

The resulting sketch is this:

// For: https://forum.arduino.cc/t/array-not-printing/1066914
// December 18, 2022

/**********Global Variables**********/
const int metrics_num = 3;             // # of financial data metric for employees to track, array row
const int employees_num = 5;           // # of employees, array column
int employees_data[metrics_num][employees_num]; // mxn array
int bonus[9];                        // # of employee bonus pay ranges

/**********Setup**********/
void setup()
{
  Serial.begin(9600);
  data_entry(employees_num, employees_data);
  pay_calculations(metrics_num, employees_num, employees_data);
}

/**********Main Loop**********/
void loop()
{
}

/**********Function Definition**********/
void data_entry(int n, int data[][employees_num])
{
  //enter data for each employee
  for (int i = 0; i < n; i++)
  {
    Serial.print("Enter gross sales for employee ");
    Serial.print(i + 1);
    Serial.print(": $");
    // waits until data is entered into serial monitor
    while (Serial.available() == 0) {} 
    // takes incoming characters and converts it to a number. 
    // This is read into the buffer altogether. 
    // Row 1 is contstand, updates column num each pass
    data[0][i] = Serial.parseInt();
    Serial.println(data[0][i]);        // test for printing value entered from array

    // flush input buffer, do before asking for new input.  
    // Notes: https://forum.arduino.cc/t/serial-input-basics-updated/382007
    while (Serial.available() > 0) {
      Serial.read();
    }
  }
}

// calculate bonus and fill these into employee data array
void pay_calculations(int m, int n, int data[][employees_num])
{
  // Bonus
  // multiply each employee data element by bonus %
  // store values in Row 2 of array for each element

  for (int i = 0; i < n; i++)
  {
    // Multiplies an employees gross weekly pay by 9% for bonus, 
    // and stores in Row 2 of employee_data array.
    //
    // Use a 'float' calculation and then convert it to integer.
    // The conversion to integers takes the integer part (rounding down).
    float b = (float) data[0][i] * 0.09;
    data[1][i] = (int) b;

    Serial.print("Empoyee ");
    Serial.print(i+1);
    Serial.print(", pay: ");
    Serial.print(data[0][i]);   // test for printing Row 1, column 'n'
    Serial.print(", bonus: ");
    Serial.println(data[1][i]); // test for printing Row 2, column 'n'
  }
}

You can test the sketch in Wokwi:

Thanks both for your help! I've made significant progress, and got my code working. Koepel I've reviewed your suggestions and much thanks. I've tackled some to get is start working.

Question on your list #10.

I fixed this, making to allow for Serial.parseInt() to be saved in

long employees_data[metrics][employees];  // mxn array

I want to check for garbage values before saving to ensure that number entered is within long range (I'm not using unsigned long). Below code logically I thought would work, but messes up, and doesn't save properly to the array, etc. Any ideas?

    if ((0 <= Serial.parseInt() ) && (Serial.parseInt() < 2147483647) )
    {
      employees_data[0][i] = Serial.parseInt();  //takes incoming characters and converts it to a number. This is read into the buffer altogether. Row 1 is contstant, updates column num each pass
      Serial.println(employees_data[0][i]);      // test for printing value entered from array
      while (Serial.available() > 0) { Serial.read(); }
    }
      else
      {
        Serial.println("---Invalid entry---");
        while (Serial.available() > 0) { Serial.read(); }
      }  

Below code works, but doesn't filter for the incoming data range.

/**********Global Variables**********/
const int metrics = 3;                  // # of financial data metric for employees to track, array row
const int metrics_count_num = metrics;  // don't touch
// may have to make seperate var for passing into array, copy this value
const int employees = 5;              // # of employees, array column
const int employees_num = employees;  // don't touch
// may have to make seperate var for passing into array, copy this value


//Arrays
long employees_data[metrics][employees];  // mxn array
int bonus[9] = {0}; //initialize all array elements to 0. Element bins contain frequency of employee bonus pay ranges


/**********Setup**********/
void setup() 
{
  Serial.begin(9600);
  data_entry(employees, employees_data);
  pay_calculations(employees, employees_data);
  histogram(employees_data, bonus);
}


/**********Main Loop**********/
void loop() {
}


/**********Function Definition**********/
void data_entry(int employees, long employees_data[][employees_num]) 
{
  //enter data for each employee
  for (int i = 0; i < employees; i++) 
  {
    Serial.print("Enter gross sales for employee ");
    Serial.print(i + 1);
    Serial.print(" (0 - 2,147,483,647): $");
    while (Serial.available() == 0) {}         // waits until data is entered into serial monitor
    
    employees_data[0][i] = Serial.parseInt();  //takes incoming characters and converts it to a number. This is read into the buffer altogether. Row 1 is contstant, updates column num each pass
    Serial.println(employees_data[0][i]);      // test for printing value entered from array
    

    /*
    if ((0 <= Serial.parseInt() ) && (Serial.parseInt() < 2147483647) )
    {
      employees_data[0][i] = Serial.parseInt();  //takes incoming characters and converts it to a number. This is read into the buffer altogether. Row 1 is contstant, updates column num each pass
      Serial.println(employees_data[0][i]);      // test for printing value entered from array
      while (Serial.available() > 0) { Serial.read(); }
    }
      else
      {
        Serial.println("---Invalid entry---");
        while (Serial.available() > 0) { Serial.read(); }
      }      

    */
    
    // flush input buffer, do before asking for new input.  Notes: https://forum.arduino.cc/t/serial-input-basics-updated/382007
    while (Serial.available() > 0) { Serial.read(); }
  }
}


// calculate bonus and fill these into employee data array
void pay_calculations(int employees, long employees_data[][employees_num]) 
{
  //Bonus
  // multiply each employee data element by bonus %
  // store values in Row 2 of array for each element

  for (int i = 0; i < employees; i++) 
  {
    employees_data[1][i] = employees_data[0][i] * 0.09;  // multiplies an employees gross weekly pay by 9% for bonus, and stores in Row 2 of employee_data array
    Serial.print(employees_data[0][i]);                // test for printing Row 1, column 'n'
    Serial.print(" | ");
    Serial.println(employees_data[1][i]);                // test for printing Row 2, column 'n'
    //Serial.println();                                    // skip line
  }
}

// create histogram for employee bonus pay bins
void histogram(long employees_data[][employees_num], int bonus[]) 
{
  Serial.println(bonus[0]); // test 
  
  for (int i = 0; i < employees; i++) 
  {    
    // test each of the 9 bins
    for (int j = 0; j < 9; j++)    {
      
      if ( ( (200 + (j*100)) <= (employees_data[1][i] + 200) ) &&  ( (employees_data[1][i] + 200) < (299 + (j*100))  ) ) 
      {
        bonus[j] = bonus[j] + 1;        
      }

        // test for if the salary is $1000+
        else if (999 < (employees_data[1][i] + 200) )
        {
          // print value
          Serial.print("High value = ");
          Serial.println(employees_data[1][i] + 200);
          bonus[8] = bonus[8] + 1;  //highest bin is $1000+
          break;          
        }
    }
    
  }


   /*print the specific bin, e.g. $200-$299, with the value in each for a freqency (using '*') for data plot
     create loop for each bin to bring out bin value store translating into # of '*' to print
   */
    for (int j = 0; j < 9; j++)
   {
        //print bin range
        Serial.print("$");
        Serial.print(200 + (j*100)); // bin_lower range
        //Serial.print(" - $");

          if (j>7) // checks for last bin range of $1000+
          {
                  Serial.print("+     "); // bin_upper range
          }
            else // default case for all prior bin ranges
            {
              Serial.print(" - $");
              Serial.print((200 + 99) + (j*100)); // bin_upper range
            }
        
        Serial.print(": ");
        
        //loop to print '*' for each bin
        int star_count = bonus[j];
        for (int a = 0; a < star_count; a++)
        {
           Serial.print("*");
        }
        Serial.println(); // skip line
    }
}

There are two ways to look at code:

  1. See how the code does things, do this, do that, and so on.
  2. See how the data flows through the code.

If a button turns on and off a led, then the data stream starts at the button, it flows through the sketch and ends up at the led.

Your input stream is the Serial monitor, you have to get that into your sketch. You use Serial.parseInt() for that. That is where the stream of data enters your sketch.

But now you have created three input streams, because you call the Serial.parseInt() three times, while there is only a single stream of data. This is calling it three times:

    if ((0 <= Serial.parseInt() ) && (Serial.parseInt() < 2147483647) )
    {
      employees_data[0][i] = Serial.parseInt();

Which stream of data are you going to use and what will you do with the other streams of data. Those are impossible questions, so you need only one place where the data stream enters your sketch.

long unfilteredInput = Serial.parseInt();
if (unfilteredInput >= 0 && unfilteredInput < 2147483647)
{
  employees_data[0][i] = unfilteredInput;
}
else
{
  Serial.println("No valid data entered");
}

If a very long number is entered, will the Serial.parseInt() return the maximum long value ? I don't know, have you tried it ?
If nothing is entered, then the Serial.parseInt() times out and returns zero. But you might also want to enter zero. There is no way to distinguish both situations. That is one of the reasons that I don't use Serial.parseInt().

You made an excellent catch there. I was trying to avoid using a variable, but I see your point, and it works.

I tried the max long, 2147483646, and it works (2147483647 when including 0). No other problems I've identified with the code, except an extra '0' printing after the final input. Perhaps that's the '0' you're mentioning.

I was ok with truncating the data, so figured Serial.parseInt() was fine from the Arduino Serial Reference. Do you have another suggestion?

No, only a few little things.

In the Arduino IDE 2.0, right-click and select "Format Document" or use menu: Tools / Auto Format.
If you use the same text layout for your code, it will help to read and understand your own code.

I prefer to tell the compiler what it should do, instead hoping for the best.
This line has a floating point number and long integer variables.

employees_data[1][i] = employees_data[0][i] * 0.09;

You should tell the compiler what it should do.

You have to make clear that a floating point calculation is used, but the result is a long integer anyway. The clearer that is for the reader, the better. A few lines of comment to make it extra clear is also good.

// Use a 'float' calculation and then convert it to integer.
// The conversion to integers takes the integer part (rounding down).
float b = float( employees_data[0][i] ) * 0.09;
employees_data[1][i] = (long) b;

You might prefer this:

employees_data[1][i] = (long) ( float( employees_data[0][i] ) * 0.09 );

but that is not clear enough in my opinion.

In my opinion, code should show what it does. Writing code is not about using less variables or less text lines or less code.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.