Test for first empty value of array - c

Is there anyway to test for the first empty value of a 2 dimensional int array in c?
In my current program, I used 2 for loops before the main program(while loop) to set all the values of my 2 dimensional array to -9999. Then inside my main while loop, I test for the first -9999 value and set it to a value, and then use break to exit from it.
Using this I managed to do my assignment, but I'm not very satisfied, as I think there might be a better solution.
Is there one?
EDIT: Code since you asked for it.
For loop outside while loop:
for(int x=0;x<ctr-1;x++)
{
for(int y=0;y<maxtrips;y++)
{
EmployeeKilos[x][y] = -9999; // Set all the kilos to -9999 to signify emptiness.
}
}
Inside my main while loop:
for(int x=0;x<ctr-1;x++) // and set it to the log kilometers
{
if(employeenames[x].EmployeeNumber == log.Record)
{
for(int y=0;y<maxtrips;y++)
{
if(EmployeeKilos[x][y] == -9999)
{
EmployeeKilos[x][y] = log.Kilometers;
break;
}
}
}
}
All my code: http://pastebin.com/Zb60mym8

As Dave said, checking for empty values cannot be made more efficient than linear time (O(n)), but my answer focuses on a solution that can prevent having to look for it in the first place.
In general you could iterate the matrix in row-major or column-major mode.
Effectively, you can use a single index that translates to a matrix cell like so
for (size_t i=0; i<ROWS*COLS; ++i)
{
int row = i / ROWS;
int col = i % ROWS;
// work with matrix[row][col]
}
This way you could just store and remember the value of i where you last found the first empty cell, so you don't have to restart from the beginning.
If you're not actually interested in row/col addressing, you could forget about those and just use an output iterator to track your current output location.
Here's a demo using 'iterator' style (borrowing from c++ but perfectly C99)
typedef int data;
typedef data* output;
output add_next(data matrix[ROWS][COLS], output startpoint, data somevalue)
{
if (output < (matrix + ROWS*COLS))
*(output++) = somevalue;
return output;
}
Now you can just say:
add_next(matrix, 42);
add_next(matrix, 9);
NOTE the output iterator thing assumes contiguous storage and therefore cannot be used with so-called jagged arrays
HTH

You can use memset to initialise arrays to a fixed value - it's a bit more efficient and cleaner looking than iterating over the array.
Checking for your 'empty' value can't be done much faster than you are doing it, though. :)

This sounds like you should think about your datatype. Since you are already using structs. why don't you add another int for the last unassigned value so you just loop to it. something like
e.g:
struct t_EmployeeKilos{
int kilos[maxtrips];
int nlast;
} EmployeeKilos[N];
and set nlast whenever you assign a new element in kilos. This way it is O(1).
for(int x=0;x<ctr-1;x++) //
{
if(employeenames[x].EmployeeNumber == log.Record)
{
EmployeeKilos[x].kilos[EmployeeKilos[x].nlast] = log.Kilometers;
EmployeeKilos[x].nlast++;
}
}

Related

How to print 2D array of strings in reverse order

I'm trying to create a function in C that will swap the indexes of my 2D array by replacing the last row index with the first row index on each iteration until the whole array is completely reversed. For example, the given sample of strings:
I am human
hello world
et is real
i am the knight
should output:
i am the knight
et is real
hello world
I am human
using my swap function. Instead the output I get (last string gets cut off) is this:
Ih am human
eello world
it is real
The function I've whipped up, looks like this:
void swap(char array[][COLS], int start, int end)
{
for(int i = 0; i >= ROWS; i++)
{
int temp = array[start][i];
array[start][i] = array[end][i];
array[end][i] = temp;
end--;
}
}
I've defined ROWS and COLS to be of size 100. What am I doing wrong and how do I rectify this?
To get the desired output, you do not want to use any sort of assignment. Assignment, as you may already know, refers to setting one piece of memory to be equal to another. In other words, copying. These three lines in your code are all assignment and cause copies to be made:
int temp = array[start][i];
array[start][i] = array[end][i];
array[end][i] = temp;
The following method will require that your string array be defined as follows:
char** array = {
"I am human",
"hello world",
"et is real",
"i am the knight"
};
Since all you want to do is print the contents in reverse order, you simply need to start at the end row, and work your way back to the beginning row. If this is your printing function
void printStrings(char** array, int start, int end)
{
while(start!=end)
{
printf("%s\n",array[start]);
++start;
}
}
You would call it like this to print the strings in normal order:
printStrings(array,0,3);
Or
printStrings(array,0,sizeof(array)-1);
And to print it in reverse order, you would need a different function:
void printStringsReverse(char** array, int end, int start)
{
while(end!=start)
{
printf("%s\n",array[end]);
--end;
}
}
And you would call this function like this:
printStringsReverse(array,3,0);
Or
printStringsReverse(array,sizeof(array)-1,0);
No assignment is needed. No copies are made. No malloc is used. You are simply printing what is already there so there is no need to move anything around. There are, of course, many ways that you could write these functions. In fact there is a way that you could write both functions to just be one function. But this is a simple method that will have very little overhead.

Getting data in rows from a 2D array in C/Objective C

It's quite a simple question, yet I cannot find an answer that works.
Take the following 2D array: int grid[4][4]. I could fill it with integers, so that visually, it could look something like:
1,0,0,5,0 0,0,0,6,7 3,0,0,0,7 2,0,0,0,9 4,0,0,2,0 (each segment a new row)
Now, what if I only wanted the data of one row, to be given as a standard array? The way I would of thought to do this would be: grid[0], which would give me 1,0,0,5,0.
However, this does not seem to work. Can anyone tell me how I can extract rows of data? Here is a code example
int grid[4][4];
//Add in some numbers, e.g.
grid[0][3] = 5;
//Get the first row
int* row1 = grid[0]; //I'm not sure about this
For instance, this example should set "row1" to "0,0,0,5,0"
I have the feeling I'm doing something awfully wrong here...
There is no error message, but it just gives "row1" a random string of integers instead, which are definitely not correct.
Remember, in an array declared int grid[4][4], you can only store four lots of four elements (sixteen total).
Your array, { 1,0,0,5,0 }, { 0,0,0,6,7 }, { 3,0,0,0,7 }, { 2,0,0,0,9 }, { 4,0,0,2,0 } is actually an int [5][5].
What you're doing is not wrong; row1 will be a pointer to the first item of grid[0]. If you wanted to print each element, that's a good start...
In a moment of clarity, you'll likely realise when I mention the word "loop"... You then need a "loop" to loop through each element of the row!
int *row = grid[0];
for (size_t x = 0; x < sizeof grid[0] / sizeof grid[0][0]; x++) {
printf("%d, ", row[x]);
}
putchar('\n');

C - How can I sort and print an array in a method but have the prior unsorted array not be affected

This is for a Deal or No Deal game.
So in my main function I'm calling my casesort method as such:
casesort(cases);
My method looks like this, I already realize it's not the most efficient sort but I'm going with what I know:
void casesort(float cases[10])
{
int i;
int j;
float tmp;
float zero = 0.00;
for (i = 0; i < 10; i++)
{
for (j = 0; j < 10; j++)
{
if (cases[i] < cases[j])
{
tmp = cases[i];
cases[i] = cases[j];
cases[j] = tmp;
}
}
}
//Print out box money amounts
printf("\n\nHidden Amounts: ");
for (i = 0; i < 10; i++)
{
if (cases[i] != zero)
printf("[$%.2f] ", cases[i]);
}
}
So when I get back to my main it turns out the array is sorted. I thought void would prevent the method returning a sorted array. I need to print out actual case numbers, I do this by just skipping over any case that is populated with a 0.00. But after the first round of case picks I get "5, 6, 7, 8, 9, 10" printing out back in my MAIN. I need it to print the cases according to what has been picked. I feel like it's a simple fix, its just that my knowledge of the specifics of C is still growing. Any ideas?
Return type void has nothing to do with prevention of array from being sorted. It just says that function does not return anything.
You see that the passed array itself is affected because an array decays to a pointer when passed to a function. Make a copy of the array and then pass it. That way you have the original list.
In C, arrays are passed by reference. i.e. they're passed as pointer to the first element. So when you pass cases into your function, you're actually giving it the original array to modify. Try creating a copy and sorting the copy rather than the actual array. Creating a copy wouldn't be bad as you have only 10 floats.
Instead of rolling your own sort, consider using qsort() or std::sort() if you are actually using c++
There are 2 obvious solutions. 1) Make a copy of the array and sort the copy (easy, waste some memory, likely not a problem these days). 2) Create a parallel array of integers and perform an index sort, i.e., instead of sorting thing original, you sort the index and then dereference the array using the index when you want the sorted version, otherwise by the raw unsorted array.
Well, make a local copy of you input and sort it. Something like this:
void casesort(float cases[10])
{
float localCases[10];
memcopy(localCases, cases, sizeof(cases));
...
Then use localCases to do your sorting.
If you don't want the array contents to be affected, then you'll have to create a copy of the array and pass that to your sorting routine (or create the copy within the routine itself).
Arrays Are Differentâ„¢ in C; see my answer here for a more detailed explanation.

Copying a subset of an array into another array / array slicing in C

In C, is there any built-in array slicing mechanism?
Like in Matlab for example,
A(1:4)
would produce =
1 1 1 1
How can I achieve this in C?
I tried looking, but the closest I could find is this: http://cboard.cprogramming.com/c-programming/95772-how-do-array-subsets.html
subsetArray = &bigArray[someIndex]
But this does not exactly return the sliced array, instead pointer to the first element of the sliced array...
Many thanks
Doing that in std C is not possible. You have to do it yourself.
If you have a string, you can use string.h library who takes care of that, but for integers there's no library that I know.
Besides that, after having what you have, the point from where you want to start your subset, is actually easy to implement.
Assuming you know the size of your 'main' array and that is an integer array, you can do this:
subset = malloc((arraySize-i)*sizeof(int)); //Where i is the place you want to start your subset.
for(j=i;j<arraySize;j++)
subset[j] = originalArray[j];
Hope this helps.
Thanks everyone for pointing out that there is no such built-in mechanism in C.
I tried using what #Afonso Tsukamoto suggested but I realized I needed a solution for multi-dimensional array. So I ended up writing my own function. I will put it in here in case anyone else is looking for similar answer:
void GetSlicedMultiArray4Col(int A[][4], int mrow, int mcol, int B[1][4], int sliced_mrow)
{
int row, col;
sliced_mrow = sliced_mrow - 1; //cause in C, index starts from 0
for(row=0; row < mrow; row++)
{
for (col=0; col < mcol; col++)
{
if (row==sliced_mrow) B[0][col]=A[row][col];
}
}
}
So A is my input (original array) and B is my output (the sliced array).
I call the function like this:
GetSlicedMultiArray4Col(A, A_rows, A_cols, B, target_row);
For example:
int A[][4] = {{1,2,3,4},{1,1,1,1},{3,3,3,3}};
int A_rows = 3;
int A_cols = 4;
int B[1][4]; //my subset
int target_row = 1;
GetSlicedMultiArray4Col(A, A_rows, A_cols, B, target_row);
This will produce a result (multidimensional array B[1][4]) that in Matlab is equal to the result of A(target_row,1:4).
I am new to C so please correct me if I'm wrong or if this code can be made better... thanks again :)
In C,as far as I know, array name is just regarded as a const pointer. So you never know the size of the subset. And also you can assign a arrary to a new address. So you can simply use a pointer instead. But you should manage the size of the subset yourself.

Grid containing apples

I found this question on a programming forum:
A table composed of N*M cells,each having a certain quantity of apples, is given. you start from the upper-left corner. At each step you can go down or right one cell.Design an algorithm to find the maximum number of apples you can collect ,if you are moving from upper-left corner to bottom-right corner.
I have thought of three different complexities[in terms of time & space]:
Approach 1[quickest]:
for(j=1,i=0;j<column;j++)
apple[i][j]=apple[i][j-1]+apple[i][j];
for(i=1,j=0;i<row;i++)
apple[i][j]=apple[i-1][j]+apple[i][j];
for(i=1;i<row;i++)
{
for(j=1;j<column;j++)
{
if(apple[i][j-1]>=apple[i-1][j])
apple[i][j]=apple[i][j]+apple[i][j-1];
else
apple[i][j]=apple[i][j]+apple[i-1][j];
}
}
printf("\n maximum apple u can pick=%d",apple[row-1][column-1]);
Approach 2:
result is the temporary array having all slots initially 0.
int getMax(int i, int j)
{
if( (i<ROW) && (j<COL) )
{
if( result[i][j] != 0 )
return result[i][j];
else
{
int right = getMax(i, j+1);
int down = getMax(i+1, j);
result[i][j] = ( (right>down) ? right : down )+apples[i][j];
return result[i][j];
}
}
else
return 0;
}
Approach 3[least space used]:
It doesn't use any temporary array.
int getMax(int i, int j)
{
if( (i<M) && (j<N) )
{
int right = getMax(i, j+1);
int down = getMax(i+1, j);
return apples[i][j]+(right>down?right:down);
}
else
return 0;
}
I want to know which is the best way to solve this problem?
There's little difference between approaches 1 and 2, approach 1 is probably a wee bit better since it doesn't need the stack for the recursion that approach 2 uses since that goes backwards.
Approach 3 has exponential time complexity, thus it is much worse than the other two which have complexitx O(rows*columns).
You can make a variant of approach 1 that proceeds along a diagonal to use only O(max{rows,columns}) additional space.
in term of time the solution 1 is the best because there is no recursie function.
the call of recursive function takes time
Improvement to First Approach
Do you really need the temporary array to be N by M?
No.
If the initial 2-d array has N columns, and M rows, we can solve this with a 1-d array of length M.
Method
In your first approach you save all of the subtotals as you go, but you really only need to know the apple-value of the cell to the left and above when you move to the next column. Once you have determined that, you don't look at those previous cells ever again.
The solution then is to write-over the old values when you start on the next column over.
The code will look like the following (I'm not actually a C programmer, so bear with me):
The Code
int getMax()
{
//apple[][] is the original apple array
//N is # of columns of apple[][]
//M is # of rows of apple[][]
//temp[] is initialized to zeroes, and has length M
for (int currentCol = 0; currentCol < N; currentCol++)
{
temp[0] += apple[currentCol][0]; //Nothing above top row
for (int i = 1; i < M; i++)
{
int applesToLeft = temp[i];
int applesAbove = temp[i-1];
if (applesToLeft > applesAbove)
{
temp[i] = applesToLeft + apple[currentCol][i];
}
else
{
temp[i] = applesAbove + apple[currentCol][i];
}
}
}
return temp[M - 1];
}
Note: there isn't any reason to actually store the values of applesToLeft and applesAbove into local variables, and feel free to use the ? : syntax for the assignment.
Also, if there are less columns than rows, you should rotate this so the 1-d array is the shorter length.
Doing it this way is a direct improvement over your first approach, as it saves memory, and plus iterating over the same 1-d array really helps with caching.
I can only think of one reason to use a different approach:
Multi-Threading
To gain the benefits of multi-threading for this problem, your 2nd approach is just about right.
In your second approach you use a memo to store the intermediate results.
If you make your memo thread-safe (by locking or using a lock-free hash-set) , then you can start multiple threads all trying to get the answer for the bottom-right corner.
[// Edit: actually since assigning ints into an array is an atomic operation, I don't think you would need to lock at all ].
Make each call to getMax choose randomly whether to do the left getMax or above getMax first.
This means that each thread works on a different part of the problem and since there is the memo, it won't repeat work a different thread has already done.

Resources