I want to define a table where the size depends on an input information.
The limitation is that I must not use dynamic allocation functions such as malloc.
Input information:
Linked List
Each item of this linked list has one field: length:
struct node {
unsigned int length;
struct node *next;
};
How to calculate the size of table:
It should be equal to the number of items if only the length value of each item is less than 255,
If the length is greater than 255, then the size should be:
(Nbr of Items where size < 255)+ (Nbr Item where size >= 255).
(Nbr Item where size >= 255) is:
Sum for each item( 0x00U == (Len % 255) ? (Len / 255) :(Len / 255)+1)
Note that it's an integer division
Example:
List of 4 items:
Length field of Item1 =245,
Length field of Item2 =165,
Length field of Item3 =101,
Length field of Item4 =16,
So the table size is 4
List of 4 items:
Length field of Item1 =500,
Length field of Item2 =510,
Length field of Item3 =1000,
Length field of Item4 =16,
So the table size is ((500/255)+1) + (510/255) +((1000/255)+1)+ (1) = 9
The problem is when I define a table with variable size:
unsigned int MyTable[size];
It generates an error. Because it needs a fixed size.
How to define this table without using dynamic allocation (malloc)?
Related
So I'm prompting the user for a number, stored as a long int, then I want to do a for loop and iterate that long int, getting all the odd position numbers in a odd array and all the even position numbers in a even array. I'm trying to resolve the credit problem set from CS50
#include <stdio.h>
#include <cs50.h>
int main(void)
{
long even[] = {}, odd[] = {};
long cc = get_long("Number: ");
}
Basically I'm trying to get this:
If long cc = 12345678912345, then even should be even[7] = {1, 3, 5, 7, 9, 2, 4} and odd should be odd[7] = {2, 4, 6, 8, 1, 3, 5}
I don't really know how I would be able to iterate over long cc to then add the specific number I need into the array
The main problem you have is that arrays in C have a fixed size, set when they are created, and that size cannot be changed. So there's no way to "append" to an array.
The usual way to deal with that is to create an array with a maximum size (or capacity) and track the "in use" part of the array with a separate variable (often called 'size'). At any given time, the array elements from 0 to size-1 are "in use" and valid, while those from size to capacity-1 are "free" and might contain garbage values that will be ignored.
Since the array and the size variable are so intimately connected, it is common to combine them into a struct to make things easier to manage:
#define MAX_ARRAY_SIZE 100
struct long_array {
size_t size;
long data[MAX_ARRAY_SIZE];
};
Now you can initialize an empty array with struct long_array odd = { 0 }; and you could then append to this array with
if (odd.size == MAX_ARRAY_SIZE) {
/* always check for errors or unexpected situations! */
fprintf(stderr, "array overflow\n");
exit(1); }
odd.data[odd.size++] = new_value;
of course, this will end up allocating the maximum amount for every array, so the limit needs to be fairly small. You can make this more flexible by allocating the array on the heap and storing the capacity in the array as well as the size:
struct long_array {
size_t size, capacity;
long *data;
};
but this requires more management to track when the array needs to be resized or freed.
that's fairly easy, just allocate two array with how many numbers are in cc using something like
int temp = cc, i = 0;
while (temp > 0) {i++; cc /= 10;}
Then calculate ur stuff like this:
while (cc > 0)
{
newNumber = cc/10;
newDigit = CC % 10
if (newNumber % 2 == 0) /*newDigit is even*/
else /*newDigit is odd*/
cc = newNumber;
}
You can use the modulo operator % to get each digit. The modulo operator basically gives you the remainder so if you do % 10 then it will give you the last digit. So 123 % 10 = 3. Then you divide the credit card number by 10 and repeat the process to get the next digit. Ex 123/10 = 12, then 12 % 10 is 2. If you make a counter variable to count how many times you've done the loop, that will give you the position. If you do position % 2, that will tell you if it is odd or even.
while (CC > 0)
digit = CC % 10
if (position % 2 == 1) //it's odd
else //its even
CC = CC/10 //to prepare for next iteration of the loop
position = position + 1 //position starts at right side of CC number
One of the other proposed answers here determines if the digit's value is odd or even, but you're trying to determine if the digit is in an even or odd position. The other proposed answer uses an array, which is something you learn about later in the course and isn't what the class is trying to teach you now.
The solution I've suggested is in line with what has been covered by your class so far. Later you will learn about arrays and you can approach this problem differently. Later in the course, you need to do this same problem in Python and that time I took in the value as a string because you can treat the full credit card number as an array and then each digit is just an element in that array. creditcardnumberarray[0] would be the first digit for example. You would need to change each digit from a Char to a Int before doing your checksum. You can do this conversion by subtracting the digit char from the char '0'. So int digitAsInt = digitAsChar - '0'
Let's say I have a sorted array of values:
int n=4; // always lower or equal than number of unique values in array
int i[256] = {};
int v = {1 1 2 4 5 5 5 5 5 7 7 9 9 11 11 13}
// EX 1 ^ ^ ^ ^
// EX 2 ^ ^ ^ ^
// EX 3 ^ ^ ^ ^
I would like to generate n random index values i[0] ... i[n-1], so that:
v[i[0]] ... v[i[n-1]] points to a unique number (ie. must not point to 5 twice)
Each number to must be the rightmost of its kind (ie. must point to the last 5)
An index to the final number (13 in this case) should always be included.
What I've tried so far:
Getting the indexes to the last of the unique values
Shuffling the indexes
Pick out the n first indexes
I'm implementing this in C, so the more standard C functions I can rely on and the shorter code, the better. (For example, shuffle is not a standard C function, but if I must, I must.)
Create an array of the last index values
int last[] = { 1, 2, 3, 8, 10, 12, 14 };
Fisher-Yates shuffle the array.
Take the first n-1 elements from the shuffled array.
Add the index to the final number.
Sort the resulting array, if desired.
This algorithm is called reservoir sampling, and can be used whenever you know how big a sample you need but not how many elements you're sampling from. (The name comes from the idea that you always maintain a reservoir of the correct number of samples. When a new value comes in, you mix it into the reservoir, remove a random element, and continue.)
Create the return value array sample of size n.
Start scanning the input array. Each time you find a new value, add its index to the end of sample, until you have n sampled elements.
Continue scanning the array, but now when you find a new value:
a. Choose a random number r in the range [0, i) where i is the number of unique values seen so far.
b. If r is less than n, overwrite element r with the new element.
When you get to the end, sort sample, assuming you need it to be sorted.
To make sure you always have the last element in the sample, run the above algorithm to select a sample of size n-1. Only consider a new element when you have found a bigger one.
The algorithm is linear in the size of v (plus an n log n term for the sort in the last step.) If you already have the list of last indices of each value, there are faster algorithms (but then you would know the size of the universe before you started sampling; reservoir sampling is primarily useful if you don't know that.)
In fact, it is not conceptually different from collecting all the indices and then finding the prefix of a Fisher-Yates shuffle. But it uses O(n) temporary memory instead of enough to store the entire index list, which may be considered a plus.
Here's an untested sample C implementation (which requires you to write the function randrange()):
/* Produces (in `out`) a uniformly distributed sample of maximum size
* `outlen` of the indices of the last occurrences of each unique
* element in `in` with the requirement that the last element must
* be in the sample.
* Requires: `in` must be sorted.
* Returns: the size of the generated sample, while will be `outlen`
* unless there were not enough unique elements.
* Note: `out` is not sorted, except that the last element in the
* generated sample is the last valid index in `in`
*/
size_t sample(int* in, size_t inlen, size_t* out, size_t outlen) {
size_t found = 0;
if (inlen && outlen) {
// The last output is fixed so we need outlen-1 random indices
--outlen;
int prev = in[0];
for (size_t curr = 1; curr < inlen; ++curr) {
if (in[curr] == prev) continue;
// Add curr - 1 to the output
size_t r = randrange(0, ++found);
if (r < outlen) out[r] = curr - 1;
prev = in[curr];
}
// Add the last index to the output
if (found > outlen) found = outlen;
out[found] = inlen - 1;
}
return found;
}
I am trying to calculate the union of two arrays containing double floating point values (they are timestamps in milliseconds), but I need to allow a tolerance of +/- one microsecond.
For example:
consider the two values from the two different lists (or arrays) below:
[ref 0 : 1114974059.841] [dut 0 : 1114974059.840]
there is a small delta between the above two numbers of .001 microseconds. So when I make my new union list, they shouldn't both appear as unique, but should be counted as ONE item, and should only have the item from the first list (in this example, ref one, ending in 059.841).
More examples of the above type:
[ref 21 : 1114974794.562] [dut 18 : 1114974794.560]
[ref 22 : 1114974827.840] [dut 19 : 1114974827.840]
[ref 23 : 1114974861.121] [dut 20 : 1114974861.120]
All the above should be considered as ONE, and hence the union list should ONLY have the ONE item of the first list: the union list would have all three from the ref array, and NONE from the dut array.
Now consider the example :
[ref 8 : 1114974328.641] [dut 8 : 1114974361.921]
Here, the delta between the two values in the list above is quite significant with respect to microseconds, and it comes under .01 micro-seconds, and hence should be considered as TWO unique items in the new union list.
Here is another example like the above one :
[ref 13 : 1114974495.041] [dut 12 : 1114974528.321]
[ref 26 : 1114974960.960] [dut 23 : 1114975027.520]
[ref 27 : 1114974994.240] [dut 23 : 1114975027.780]
They all should be considered unique in the new union list.
Can you help me?
I made a subroutine that allows me to detect the tolerance like this:
unsigned int AlmostEqualRelative(double A, double B, double maxRelDiff){
double diff = fabs(A - B); // Calculate the difference.
//
if (diff < maxRelDiff) {
//printf("\n page hit [ref: %10.3f] [dut: %10.3f]",A,B);
return 1;
}
//printf("\n page miss [ref: %10.3f] [dut: %10.3f]",A,B);
return 0;
}
I give maxRelDiff as .02.
Assuming that the two lists are of same size:
unsigned int // size of output array
union_list(const double *list1, // first list
const double *list2, // second list
double* ulist, // output list
unsigned int size) // size of input list
{
unsigned int i = 0u, j = 0u ;
for(; i < size; ++i, ++j)
{
result = is_near(list1[i], list[2]);
if (result == 1)
{
ulist[j] = list1[i] ;
}
else
{
ulist[j] = list1[i] ;
j += 1 ;
ulist[j] = list2[i];
}
}
return j ;
}
Now ulist is the output array. The maximum value it can contain is size*2 and minimum is size. Allocate max number of elements. The returned value is the size of the output array.
int is_near(double a, double b)
{
int result = 1 ;
if (fabs(a - b) >= relative_error)
result = 2 ;
return result ;
}
You can do it like this:
First, make a copy foo of the ref array. foo must be large enough to store both ref and dut arrays' elements as they may be mutually exclusive.
len=0;
for(i=0;i<length_ref;i++)
foo[len++]=ref[i];
Then, add to foo only those elements of dut which are not in ref.
for(i=0;i<length_dut;i++)
{
flag=1;
for(j=0;j<length_ref;j++)
if(AlmostEqualRelative(dut[i],ref[j],MAXRELDIFF))
{
flag=0;
break;
}
if(flag)
foo[len++]=dut[i];
}
One way to approach this is to rewrite your AlmostEqualRelative function as a function which conforms to the prototype int (*compar)(const void *, const void *) (ie, return negative, zero or positive depending on the relative ordering of the arguments). That makes it suitable for passing to the qsort(3) function.
That done, you could concatenate your two starting arrays, qsort the concatenation, and then work through the resulting array copying to a final result only a single exemplar of a sequence of elements which mutually compar to zero.
That would require a little bit of bookkeeping, and a bit of extra space, but it uses existing code (ie, qsort), and unless your arrays are so big that the extra space is a problem, it's probably the most straightforward route to a solution.
That is, this is the moral equivalent of getting the set-union of two files by doing cat f1 f2 | sort | uniq, but with some fuzziness on the uniq comparison.
How do I make a 2d dynamic array (in C) with specific row number and different column size in each row?
For example:
This is an array (3=rows)
|1 | 4 | 5 |
|3 |
|6 | 2 |
1st row - 3 columns
2nd row - 1 column
3rd row - 2 columns
I want my program while running to ask the user for every row to give the number of cols.
How do I make an array like this?
If you want something dynamic and don't care about constant access time, you can create an array of linked list, otherwise you have no choice but to allocate some space with sufficient memory and keep it updated with realloc.
What you will probably want to is to use a pointer pointer and allocate sufficient memory for each row then. Example:
int ** array = calloc(sizeof(*array), NUMROWS);
array[0] = calloc(sizeof(**array), 3); // 3 fields
array[1] = calloc(sizeof(**array), 1); // 1 field
array[2] = calloc(sizeof(**array), 2); // 2 fields
You need an array of pointers:
int *ptr_array[3];
Then for each row, you need to allocation memory:
int map_array[3] = {3,1,2}
int i;
for(i = 0; i < 3; i++){
ptr_array[i] = malloc(sizeof(int)*map_array[i]);
}
If you need the number of row to be dynamic, you should do the first part as:
int **ptr_ptr_array;
(*ptr_ptr_array) = malloc(sizeof(int *)*3);
Good luck with recycling the memory.
In a program, I have to scan from the input
scanf("%s",currWord);
a non-defined number of words, which come in a non-defined number of lines.
I want to put the words in a 2 dimensional array of strings.
Length of the strings is fixed [MAX_WORD_LEN+1]
My idea is:
int row=10 //10 lines for starting
int col=5 //5 words in each line for starting
int i;
typedef char word[MAX_WORD_LEN+1]; //new type of 11char lenght string
word** matrix; //2 dimensional array (pointers) with no memory
matrix = malloc(row*sizeof(word*)); //allocate row number of word* (word pointer) size
for(i=0;i<row;i++)
{
matrix[i] = malloc(col*sizeof(word)); //allocate col number of words to each row
}
So, I have no idea if that is right.
I'll be happy for some help and tips..
EDIT:
When receiving the words from input I have to increase memory ( number of rows and words in each row) if needed, How do I do that? (realloc ?)
I need to do the following:
Without going into details, the easiest way is to use a Matrix as a Linked-List of Linked-Lists ..
struct matrix_field
{
char data [11];
matrix_field * next_field;
};
struct matrix_row
{
matrix_field * first_field;
matrix_row * next_row;
};
struct matrix
{
matrix_node * first_row;
};
Your data will look like this in memory ..
[+]
|
v
[x]-->[a]-->[b]-->[c]-->
|
v
[y]-->[d]-->[e]-->[f]-->
|
v
[z]-->[g]-->[h]-->[i]-->
|
v
---------------
[+] matrix
[x] .. [z] matrix_row
[a] .. [i] matrix_field