How to modify multiple elements at a time in C? - c

Say I got an array
unsigned char digit[] = {0, 1, 2, 3, 4, 5, 6, 7};
Yet I want to modify part of the array, make the array become something like:
{0, 1, 2, 3, 0, 0, 0, 0}
Enumerate every element I want to modify and alter them might take some effort. Especially when there's a large amount of elements I want to change. I know in some languages like Python I may do something using a single line of code:
a = np.array([0, 1, 2, 3, 4, 5, 6, 7])
a[4:] = [0, 0, 0, 0]
//a: array([0, 1, 2, 3, 0, 0, 0, 0])
So I wonder, is there a similar way to do that in C?

There are fewer possibilities in C, but in case of an unsigned char and setting its values to zero you could use memset:
memset(&digit[4], 0, 4);
Demo.

One options is that you could write a subroutine that would implement the interface that other languages provide "under the cover". You'll probably want to educate yourself on 'VARARGS' to make it take a variable number of arguments.

Others have already mentioned setting the array elements to a single value using memset, as a part of your follow up question you asked if some elements can be set to certain values like {1, 2, 3, 4}.
You can use memcpy here to achieve that. Since your type here is unsigned char I will keep that, but in general this method can be used for any type.
memcpy(&digit[4], ((unsigned char[4]){1, 2, 3, 4}), 4 * sizeof(unsigned char));
You can see the demo here.

I think that maybe not the shortest but something you can easy do is just:
digit[] = {0, 1, 2, 3, 4, 5, 6, 7}; %Having this
a=the number in your vector you want to start making ceros;
n=the lenght of digit;
for(i=a;i=n;i++)
{
digit[n]=0;
}
Is just a way I think you could use.
If you want to change an specific one just
b=position;
digit[b]=c; %Where c is the number you want to put in there.
I hope it works for you, good luck.

Related

How do I add different size of new array to an old array using a for loop?

How do I use a for loop to add array 1 to array 2 and become the expected array like the example below?
What I expect is adding the first element in array 1 to array 2's second 1234 and continue adding up:
Array 1 = [4, 8]
Array 2 = [1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4]
Expected Array:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]
I am thinking of something like this, but just feel very strange.
N=4
for (int i=N; i<array.size; i++)
{
array2[i] = array1[...];
}
I guess your question is when
int array1[] = {4, 8};
int array2[] = {1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4};
int arrayAnswer[] = {array2[0],array2[1],array2[2],array2[3],
array2[0]+array1[1],array2[1]+array1[1],array2[2]+array1[1],array2[3]+array1[1],
array2[0]+array1[2],array2[1]+array1[2],array2[2]+array1[2],array2[3]+array1[2]}
is it right? if so, please leave the comment and I will edit more
First of all, the question you made is not a good question. Please try to give more detailed information about your problem next time.
Answer for your question is, skip fist four member of array and add array1[1] on from array2[4] to array [7], and add array1[2] on from array2[8] to array [11]. You are going to need two loop. such as
for (i = 0; i < 2; i++){
for (j = 0; j < 4; j++){
//your function
}
}
I am not going to give you direct answer for the problem so that you can design your own. However, if your first array is {0, 4, 8}, your coding is going to be much easier. ty

Can I realloc from a position of the array?

Say I declared an array[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}. Later I want it to be array[8] = {2, 3, 4, 5, 6, 7, 8, 9}.
Dismiss the first 2 elements. So it would start on array[2]. Reallocing array to array[2].
I tried:
int *array=(int*)malloc(10*sizeof(int));
...//do stuffs
array=(int*)realloc(array[2],8*sizeof(int));
It didn't work. Neither using &array[2], *array[2], nor creating an auxiliary array, reallocing Array to AuxArr than free(AuxArr).
Can I get a light?
You can only realloc a pointer to a memory block that has already been alloc'ed. So you can realloc(array), but not array[2] since that is a pointer to a location in the middle of a memory block.
You may want to try memmove instead.
Edit:In response to ThingyWotsit's comment, after memomving the data you want to the front of the array, then you can realloc to drop off the tail end.
Just use array += 2 or array = &array[2]. You can't realloc() it.

Incrementing in a list efficiently

I have a list:
foo = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Currently, I increment a known number of consecutive indices by a given value:
def increment(index, length, some_value, a_list):
for i in range(index, index+length):
a_list[i] += some_value
return a_list
foo = increment(2,3,4,foo)
# [0, 0, 4, 4, 4, 0, 0, 0, 0, 0]
However, the problem is that I would be doing this over a range of 50-100 "length" and would be doing this millions of times. So, my looping would pose a considerable problem to computational time (I believe). Is there a way to add a given value to all indices within a given range without having to loop through the given indices?
Simon Tatham wrote something about "Cumulative Frequency Tables": http://www.chiark.greenend.org.uk/~sgtatham/algorithms/cumulative.html
This would apparently get you log times:
def increment(index, length, some_value, a_frequency_table):
// increment "frequency" of (index) by some_value
// decrement "frequency" of (index+length-1) by some_value
He also links C-code on the bottom of the page. If I understood your question right, it should be possible to adopt.
Given your requirements, it looks to me as though you doing this correctly in regards to performance. The only thing I can see to improve performance is very miniscule... I wouldn't bother returning the array, as it is unnecessary. Beyond that, everything looks sound.
def increment(index, length, some_value, a_list):
for i in range(index, index+length):
a_list[i] += some_value
increment(2,3,4,foo)
# [0, 0, 4, 4, 4, 0, 0, 0, 0, 0]

How to initialize three dimensional char array without using pointers in c

How to initialize three dimensional char array without pointers in c and access it?
I tried the following:
char card[1][3][15]={
{"iron","man"},
{"contagious","heide"},
{"string","middle"}
};
but I am getting
**Error:too many initializers**
**Warning: Array is only partially initialized**
Lets take a simple example...You can use your own values instead of these integers:
declaration:
int arr[2][3][4] = { { {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4} },
{ {1, 2, 3, 4}, {1, 2, 3, 4}, {1, 2, 3, 4} } };
I hope, it is clear to you.
Considering your example itself:
I think it should be
char card[1][3][15]={ {"iron","man", "contagious"}};
What this means is that you can effectively create 3 char arrays each of length 15. Your first dimension of 1 doesn't have much effect.
So, you can make it like
char card[2][3][15]={ {"iron","man", "contagious"},
{"iron","man", "contagious"}};
So, for your simple understand, the number of rows indicate the first dimension, the number of columns in each row indicates the second dimension and the number of elements(in this case chars) in each column indicates the 3rd dimension.
So, now you can see that for the data in your question, you should declare the array as char char[3][2][15]
char card[1][3][15]={ { {"iron","man"},{"contagious","heide"},{"string","middle"}}
};
You should put another braces brackets inside. I think it will be helpful to you.

C: clever way to "shift" a matrix?

I have an integer matrix that should act like a buffer:
x = {{0, 0, 0, 0, 0}, {1, 1, 1, 1, 1}, {2, 2, 2, 2, 2}};
Now if I add a new row {3, 3, 3, 3, 3}, the new matrix should look like:
x = {{1, 1, 1, 1, 1}, {2, 2, 2, 2, 2}, {3, 3, 3, 3, 3}};
Is there a clever way of doing this without copying all elements around?
If your matrix is defined as an int ** and you separately allocate each row, then you would only have to swap the row pointers.
How about modulo operation?
If you access the elements as matrix[x + SZ * y] you could change it to:
matrix[x + SZ * ((y + FIRST_ROW) % SZ)] .
In this way to implement this shift you just put the new line {3, 3, 3..} where line {0, 0, 0} was, and increment the FIRST_ROW counter to point to the new starting row.
Use a linked list.
struct node
{
int row[5];
struct node *next;
};
Appending a row is as simple as walking the list to the end, then replacing the NULL next pointer with a new node (whose next pointer is NULL).
Can you increment x so that it points to the second row, then free the first row? Obviously, you would need to allocate a row at a time and this would not guarantee that the matrix is contiguous. If you require that, you could allocate one big block of memory to hold your matrix and then clobber the unused parts when you reach the end.
If you use an array of pointers to arrays (rather than an ordinary two-dimensional array), you can copy just the pointers to rows instead of copying all elements.
And if you're okay with overallocating the array of pointers, you could maybe add a new pointer to the end and advance the pointer to the "start" of the array. But this wouldn't be a good idea if you potentially want to do this sort of shift many times. And of course you'd want to make sure you have the original pointer somewhere so you can properly free() your resources.
Lazy to write code example - you can use modulo arithmetics to address the rows. When pushing a new row, simply increase a starting offset variable, add the matrix height and modulo the result by matrix height. This way you get a circular matrix with no need to copy the whole matrix and keeping the matrix array compact.

Resources