1

I've started learning functions in C.

I have a task to convert numbers from imperial to metric, which are contained in the 2d Array.

Array:

{1300, 0}  [0][0] [0][1]

{2198, 0}  [1][0] [1][1]

{4199, 1}  [2][0] [2][1]

{2103, 0}  [3][0] [3][1]

{3104, 1}  [4][0] [4][1]

{1093, 1}  [5][0] [5][1]

{3204, 0}  [6][0] [6][1] 

So I am calling function with double return SortedArray[DATA_ROWS] = find_function(MixedData);

find_function logic:

0 is an indicator of the metric system value and 1 is an indicator of imperial system value, i is a row indexer and j is a column indexer.

So when for cycles find out that column value is 0 or 1 they save [j-1](an actual value that we need) into SortedArray.

It also converts value if finds out that column value is 1 SortedArray[i] = MixedData[i][j-1]*CONSTANT;

Just for a check, I did printf to see if values are correct and correctly converted if needed. I got this output:

1300.00
2198.00
1301.69
2103.00
962.24
338.83
3204.00

So, seems like correct, but in Task I have another task - use 2 functions to solve this task. I've decided to make another function, which will sum all values in SortedArray[DATA_ROWS] and then calculate avg - average. Then print them out. And here comes the problem.

Calling function with no return total_AVG(SortedArray); with copied array SortedArray[DATA_ROWS]

Just to check made a printf and got this:

-1.#R
0.00
0.00
0.00
0.00
0.00
0.00

It seems like my SortedArray[DATA_ROWS] did not copy into the second function total_AVG

Pointers are coming in the next task, so according to task's timeline I can't use them * (and even if I could, I have no idea how to use them still)*

Can you please tell me, what I am doing wrong.

NB: Some comments and variables, which are not used just old ones, when I tried to correct my code. And also I only need to understand why SortedArray[DATA_ROWS] did not copy into second function total_AVG. All further logic will be corrected after solving this problem.

Thank you! And sorry for broken English!

CODE:

#include <stdio.h>
#define DATA_ROWS 7
#define DATA_COLS 2
#define CONSTANT 0.31
#define MAX 3


double find_function(int MixedData[DATA_ROWS][DATA_COLS]);
void total_AVG(double SortedArray[DATA_ROWS]);


int main(void)
{
    int i;
    double SortedArray[DATA_ROWS];


    int MixedData[DATA_ROWS][DATA_COLS] = {
        {1300, 0},//[0][0] [0][1]
        {2198, 0},//[1][0] [1][1]
        {4199, 1},//[2][0] [2][1]
        {2103, 0},//[3][0] [3][1]
        {3104, 1},//[4][0] [4][1]
        {1093, 1},//[5][0] [5][1]
        {3204, 0}};//[6][0] [6][1]

    SortedArray[DATA_ROWS] = find_function(MixedData);
    total_AVG(SortedArray);


    return 0;
}

double find_function(int MixedData[DATA_ROWS][DATA_COLS])
{
    // imperial numbers from source array "mixedData" are 4199,3104,1093;

    int i,j; // indexers
    double SortedArray[DATA_ROWS]; 




    // 7 rows, each row suppose to contain only metric values
    // That means, if second for cycle with j indexer finds 0, it will contain j-1 value for example 1300 in SortedArray
    // If it finds in second for cycle with j indexer 1, it will converte the value from imperial to metric for example 4199*0.31
        /*  {1300, 0}  [0][0] [0][1]
            {2198, 0}  [1][0] [1][1]
            {4199, 1}  [2][0] [2][1]
            {2103, 0}  [3][0] [3][1]
            {3104, 1}  [4][0] [4][1]
            {1093, 1}  [5][0] [5][1]
            {3204, 0}  [6][0] [6][1] */


    // Probably problem in "double SortedArray and int MixedData"
    for(i=0;i<DATA_ROWS;i++)
    {
        for(j=0;j<DATA_COLS;j++)
        {
            if(MixedData[i][j]==0)                                               
            {
                SortedArray[i] = MixedData[i][j-1];
            }
            else if(MixedData[i][j]==1)
            {
                SortedArray[i] = MixedData[i][j-1]*CONSTANT;

            }
        }
    }
    for(i=0;i<DATA_ROWS;i++)
    {
        //total += SortedArray[i];
        printf("%.2lf\n", SortedArray[i]);
    }

    return SortedArray[DATA_ROWS];
}

void total_AVG(double SortedArray[DATA_ROWS])
{
    double avg,total;
    int i;

    for(i=0;i<DATA_ROWS;i++)
    {
        printf("%.2lf\n", SortedArray[i]);
    }
    //avg = total/DATA_ROWS;
    //printf("Total by every worker: %.2lf\n",total);
    //printf("In average by every worker: %.2lf", avg);

    return;
}

6
  • SortedArray[i] = MixedData[i][j-1]; you access invalid location when j=0. Commented Feb 14, 2020 at 9:22
  • And SortedArray[DATA_ROWS] = find_function(MixedData); here too. Commented Feb 14, 2020 at 9:23
  • Again return SortedArray[DATA_ROWS]; here too. Commented Feb 14, 2020 at 9:24
  • SortedArray[DATA_ROWS] = find_function(MixedData); -> double result = find_function(MixedData);. Your find function should return a single double. Most of your confusion comes from your attempt to "return arrays". You can't do that in C. You need to pass arrays by pointers. I'd advise stepping back from 2D arrays and study how arrays decay to pointers, and how that happens when you pass an array as function parameter. Commented Feb 14, 2020 at 9:25
  • SortedArray[i] = MixedData[i][j-1]; you access invalid location when j=0 * I have if else cycle for chechking for imperial numbers marked as 1, when j=1 So if I am not mistaken when j = 0 I have for example 1300 value. And when j=1, it's either 0 or 1. if it's a 0, just save previous value j-1 = j = 0, which is 1300 into array else if it's a 1, just save previous value j-1 = j = 0, which is 1300 into array, but first multiply by CONSTANT Commented Feb 14, 2020 at 10:54

3 Answers 3

1

Arrays are NOT assignable in C. C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) ..."an expression that has type *"array of type"* is converted to an expression with type *"pointer to type"* that points to the initial element of the array object and is not an lvalue." An array is NOT an lvalue;

In order to fill an array you have to iterate over the elements and assign values to the individual elements, or copy a block of memory to your array containing the values for your elements with memcpy, etc..

Further, with double SortedArray[DATA_ROWS]; you cannot return a locally declared array from a function. When the function returns, the function stack (containing your array) is destroyed (released for re-used). You must either pass your SortedArray as a parameter to find_function and fill the values of the array passed from main() there, or you must allocate storage for the values and return a Pointer to the allocated block of memory holding your values to main(). Those are your two-options.


Rearranging Your Code

Looking at your code and what you are attempting to do, it appears you need to:

  • declare double total = 0; in main()
  • you need to change the declaration for the find function so it takes SortedArray as a parameter, e.g.

    double find_function(int (*MixedData)[DATA_COLS], double *SortedArray)

  • you need to declare another double total; (or any other name you choose) in find_function() and that total is what you want to return from find_function() to assign to the total declared in main() thereby providing its value, e.g.

    total = find_function (MixedData, SortedArray);
    
  • You need to change the declaration for total_AVG() so it takes the SortedArray passed to find_function() and filled there to the total_AVG() function as a parameter, along with the total returned from the find_function() e.g.

    void total_AVG (double *SortedArray, double total);

With that, and uncommenting the calculations and getting rid of the unused variables in your code, you could do:

#include <stdio.h>

#define DATA_ROWS 7
#define DATA_COLS 2
#define CONSTANT 0.31
#define MAX 3

double find_function (int (*MixedData)[DATA_COLS], double *SortedArray);
void total_AVG (double *SortedArray, double total);

int main(void)
{
    double total = 0;
    double SortedArray[DATA_ROWS] = {0};    /* good idea to initialize arrays zero */


    int MixedData[DATA_ROWS][DATA_COLS] = { {1300, 0},      //[0][0] [0][1]
                                            {2198, 0},      //[1][0] [1][1]
                                            {4199, 1},      //[2][0] [2][1]
                                            {2103, 0},      //[3][0] [3][1]
                                            {3104, 1},      //[4][0] [4][1]
                                            {1093, 1},      //[5][0] [5][1]
                                            {3204, 0} };    //[6][0] [6][1]

    total = find_function (MixedData, SortedArray);
    total_AVG (SortedArray, total);
}

double find_function(int (*MixedData)[DATA_COLS], double *SortedArray)
{
    // imperial numbers from source array "mixedData" are 4199,3104,1093;

    int i,j;    // indexers
    double total = 0;

    // Probably problem in "double SortedArray and int MixedData"
    for (i=0;i<DATA_ROWS;i++)
        for (j=0;j<DATA_COLS;j++)
            if (MixedData[i][j]==0)
                SortedArray[i] = MixedData[i][j-1];
            else if (MixedData[i][j]==1)
                SortedArray[i] = MixedData[i][j-1]*CONSTANT;

    for (i=0;i<DATA_ROWS;i++) {
        total += SortedArray[i];
        printf("%.2lf\n", SortedArray[i]);
    }

    return total;
}

void total_AVG (double *SortedArray, double total)
{
    double avg;
    int i;

    for (i=0;i<DATA_ROWS;i++)
        printf("%.2lf\n", SortedArray[i]);

    avg = total/DATA_ROWS;

    printf("Total by every worker: %.2lf\n",total);
    printf("In average by every worker: %.2lf\n", avg);
}

Example Use/Output

Running the compiled program yields the following:

$ ./bin/sorteddata
1300.00
2198.00
1301.69
2103.00
962.24
338.83
3204.00
1300.00
2198.00
1301.69
2103.00
962.24
338.83
3204.00
Total by every worker: 11407.76
In average by every worker: 1629.68

(note: I have not validated this output for correctness -- that I leave to you, but at a quick glance -- it looks reasonable based on what your code does)

Let me know if you have any questions about the changes made.

Sign up to request clarification or add additional context in comments.

3 Comments

Thank you for the fast response. Pointers are in the next lecture and next Tasks, so theoretically I can't use them right now. But this part helped me a lot: Further, with double SortedArray[DATA_ROWS]; you cannot return a locally declared array from a function. When the function returns, the function stack (containing your array) is destroyed (released for re-used). So I can use only a variable not array, to save data(SortedArray) from find function?
You can just stick the array notation back in as parameters instead of the pointer notation I used. They are the same C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3) I have now confirmed the output -- it is correct. Remove the (duplicate) printing of numbers from find_function also make your j loop for (j=1;j<DATA_COLS;j++) and you are done. Now if you just use qsort on SortedArray after you call find_function -- you would really have a SortedArray.
Thanks! Yea, the main problem was only to receive this SortedArray.
0

You cant use arrays like this

return SortedArray[DATA_ROWS];
SortedArray[DATA_ROWS] = find_function(MixedData);

You can pass it as parameter to function. like below.

find_function(MixedData, SortedArray);

void find_function(int MixedData[DATA_ROWS][DATA_COLS], double SortedArray[DATA_ROWS])
{
// Dont define, use itt from parameter
// double SortedArray[DATA_ROWS];

// ...

// Dont need to return.
// return SortedArray[DATA_ROWS];
}

1 Comment

Thank you! Like from the previous answer I should give SortedArray[DATA_ROWS] from main function as a parameter to find_function because I can't contain data from it in array. And also I can't return locally declared array from function.
0

The function you've defined is:

double find_function(int MixedData[DATA_ROWS][DATA_COLS]) { }

It's return type is double whereas you're trying to return an array, assays can't be returned liked nor can be assigned.

return SortedArray[DATA_ROWS]; 

Here you're trying to access the element which is equal to length, it's wrong. What you can do is, pass array as function parameter (or as a pointer) and return void. i.e:

void find_function(int MixedData[DATA_ROWS][DATA_COLS], double* SortedArray) { /*...*/ }

or you may use dynamic memory allocations.. in case you want to return the base address from the function.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.