Strange values being initialized into array - c

int letters[] = {['A'] = 4, ['B'] = 8, ['E'] = 3, ['I'] = 1, ['O'] = 0, ['S'] = 5};
When I initialize the array letters above, my assumption is that at the index of each capital letter, the value will be the number i.e. if ['A'] = 4, then at index 'A' the value will be 4 and the rest of the values not initialized will be 0 by default.
But when I print all the values of the array letters, I am getting this output:
00000000000000000000000000000000000000000000000000000000000000000480030001000000000514303876720941309621-1392458268143038767232767-197939865932767-1979398659327670010143038792832767
I have no idea where the negative numbers are coming from.

'S' is the highest index you gave a value for and, as your encoding's apparently ASCII, the length of your array is 83 (= 0x53). Everything with smaller indexes (without an initializer) is initialized to 0.
When you print your array, you are accessing the array out-of-bounds, which is undefined behavior.
What your program probably outputs are the values which happen to be on the stack after your array. However, as said above, there is no guarantee about what will happen.
HTH

My guess is that the code you wrote to print the array is wrong. Just tested with this:
#include <stdio.h>
int main()
{
int letters[] = {['A'] = 4, ['B'] = 8, ['E'] = 3, ['I'] = 1, ['O'] = 0, ['S'] = 5};
int i;
for (i = 0; i <= 'S'; i++) {
printf("%d\n", letters[i]);
}
return 0;
}
And it works fine and prints everything up to and including 5.

You most probably are using a for loop that is structured as follows:
for ( int i = 0; i < sizeof letters; i++ ) {
// ...
}
And the problem lies within the sizeof letters part, which gives you the size of... letters, which is not how many elements the array has. It rather is, the size of letters, that is, size of a single element times amount of elements:
sizeof letters == sizeof * letters * amountofelements;
// evaluates to 1
// assuming that amountofelements is the amount of elements that
// the array letters points to
// more: sizeof * letters is equivalent to sizeof( letters[0] )
// and the equation above is equivalent to
// sizeof( letters ) == sizeof( letters[0] ) * amountofelements;
// just in case...
So, change your for condition into the following:
for ( int i = 0; i < sizeof letters / sizeof * letters; i++ ) {
// whatever
}
Thanks for giving me the opportunity to use my psychic powers, kek.

Related

Is this syntax array inside array?

Below code snippet from Leetcode. the given exercise is to find the longest substring without repeating characters. I am trying to understand the logic from someone has posted the solution
I have below question is
I have cnt and s are array. is this array inside array cnt[s[j]] and cnt[s[j]]++? how it works, please help to explain. I have tried to visualize the code execution using this
I have tried to understand below line . I tried to visualize the code execution using
#include <stdio.h>
int lengthOfLongestSubstring(char * s)
{
if (s[0] == '\0')
return 0;
if (s[1] == '\0')
return 1;
int i, j, len, max = 0;
int cnt[255] = {0}; // array of counter
//memset(cnt,0,sizeof(cnt));
for (i=0; s[i]!=0; i++)
{
len = 0;
for (j=i; s[j]!=0; j++)
{
if (cnt[s[j]] == 0) /* What does this mean since cnt and s both are array? is this called array inside array ? */
{
printf("iteration %d %c\n",j,s[j]);
cnt[s[j]]++;
len++;
}
else
{ /* if character are not equal */
break;
}
}
if (len > max)
max = len;
}
return max;
}
int main()
{
char string1[] = "abcabcbb";
printf("%d",lengthOfLongestSubstring(string1));
return 0;
}
The syntax a[b[i]] means the value in b[i] references the index from a to read.
So if you have int a[] = { 10, 100, 1000, 10000, 100000}; int b[] = { 3, 2, 1, 0}; then a[b[0]] resolves to a[3] which has the value 10000.
Note that this requires b to only have values that are valid indexes into a.
It's not an array inside an array, it's using one array to get the subscript into another array.
When you see a complex expression you don't understand, split it up into simpler expressions.
cnt[s[j]]++;
is roughly equivalent to
int charcode = s[j];
cnt[charcode]++;
s is a string, so s[j] contains a character code. So this increments the element of cnt corresponding to that character code, and the final result is frequency counts of each character.

Arrange one array and other array do the same

sorry if English no good, but I have questions please:
I have this array[quantity] that I will sort:
int main() {
int numberOfFruits[] = {3, 5, 2, 4, 1};
//I do sorting algorithm
}
but I also want other array do same thing and match.
char fruits[] = {"apple", "orange", "bannana", "peach", "watermelon"};
So after algrithm it will be:
int numberOfFruits[] = {1, 2, 3, 4, 5};
char fruits[] = {"watermelon", "banana", "apple", "peach", "orange"};
How I do this? Thank you.
First, a variable of type char is not able to hold a string (unless it holds the value 0, then it is an empty string). A string is a sequence of char, where the last char has the value 0. Typically a string is stored in an array, or you use a pointer char * to point to a string that is stored somewhere else. In your case, the name of the fruits are stored in a string literal, so you can use a char * to that. An since you want an array of strings, you should declare an array of char *:
char *fruits[] = {.....};
Now to your actual question:
When you have multiple things that belongs together, you can aggregate them together by declaring a struct:
struct fruit
{
int number;
char *name;
};
And you can define an array of struct fruit like this:
struct fruit fruits[] =
{
{1, "watermelon"},
{2, "banana"},
{3, "apple"},
{4, "peach"},
{5, "orange"}
}
When you now swap two element of fruits, you swap both number and name together:
/* Swap the i-th and j-th element in fruits */
struct fruit tmp = fruits[i];
fruits[i] = fruits[j];
fruits[j] = tmp;
I upvoted HAL9000’s answer because it suggests a better data structure than parallel arrays, but it doesn’t actually answer the title question: How do I sort parallel arrays?
Parallel Arrays
OP has presented an example of parallel arrays. I will add my favorite fruits to his:
int fruit_IDs [] = { 3, 5, 2, 4, 1 10, -7 };
char * fruit_names[] = { "apple", "orange", "banana", "peach", "watermellon", "grapefruit", "strawberry" };
Notice how the ID has no relation to any ordering or indexing of the list. It is just another piece of information. Here is another parallel array structure:
char * first_names[] = { "Harry", "Ron", "Hermione", "Severus" };
char * last_names [] = { "Potter", "Weasley", "Granger", "Snape" };
int year_born [] = { 1980, 1980, 1979, 1960 };
So, how do we sort them without breaking their index association?
Index Array
The simplest would be to use an additional array which is simply used as indices into the parallel arrays. Sticking with the fruits:
int fruit_indexes[NUM_FRUITS] = { 0, 1, 2, 3, 4, 5, 6 };
Now we have a layer of indirection into our parallel arrays. To print the arrays, we might write:
for (int n = 0; n < NUM_FRUITS; n++)
printf( "%d %s\n", fruit_IDs[fruit_indexes[n]], fruit_names[fruit_indexes[n]] );
As you can imagine, if we reorder the elements of the index array, we also reorder how we view the parallel arrays. For example, to see the fruits in reverse order:
int fruit_indexes[NUM_FRUITS] = { 6, 5, 4, 3, 2, 1, 0 };
You should notice right away that this additional array has consequences:
On the plus side, we no longer have to move stuff around in the parallel arrays to reorder them.
On the minus side, we have an additional array to deal with.
Let’s qsort() with the index array!
First, we need a comparitor for the fruit IDs, accessed via indirection through the index array:
int compare_indexed_fruits_by_ID( const void * a, const void * b )
{
// A and b are pointers to elements of the fruit_indices[] array
int ai = *(const int *)a;
int bi = *(const int *)b;
// We use those indices to compare fruit IDs
if (fruit_IDs[ai] < fruit_IDs[bi]) return -1;
if (fruit_IDs[ai] > fruit_IDs[bi]) return 1;
return 0;
}
Comparing by fruit name works the same way, except now we compare names instead of IDs:
int compare_indexed_fruits_by_name( const void * a, const void * b )
{
// A and b are pointers to elements of the fruit_indices[] array
int ai = *(const int *)a;
int bi = *(const int *)b;
// Use those indices to compare fruit names
return strcmp( fruit_names[ai], fruit_names[bi] );
}
The call to QSort is thereafter very simple — pass the correct comparison function and sort the index array:
qsort( fruit_indexes, NUM_FRUITS, sizeof(*fruit_indexes), &compare_indexed_fruits_by_ID );
Printing our fruits will give you:
-7 strawberry
1 watermellon
2 banana
3 apple
4 peach
5 orange
10 grapefruit
We can sort by name just as easily:
qsort( fruit_indexes, NUM_FRUITS, sizeof(*fruit_indexes), &compare_indexed_fruits_by_name );
Producing:
3 apple
2 banana
10 grapefruit
5 orange
4 peach
-7 strawberry
1 watermellon
Dynamic data, static arrays
One of the nice things about the index array is that you can still use it when adding and removing data from other arrays. Remember, to set up static arrays you need a data structure something like this:
#define MAX_NUM_PEOPLE 1000
char * first_names[MAX_NUM_PEOPLE];
char * last_names [MAX_NUM_PEOPLE];
int indices [MAX_NUM_PEOPLE];
int num_people = 0;
To add new data, just push it onto the back of your existing arrays as usual, checking of course that you have room:
if (num_people < MAX_NUM_PEOPLE)
{
first_names[num_people] = new first name;
last_names [num_people] = new last name;
indices [num_people] = num_people;
num_people += 1;
The new element will naturally be out of order, so you will have to sort the index array again.
qsort( indices, ... );
}
To delete an element you need only swap it off the end before sorting the index array again. Don’t forget to check your array bounds!
if (index_to_delete > 0 && index_to_delete < num_people)
{
first_names[indices[index_to_delete]] = first_names[num_people-1];
last_names [indices[index_to_delete]] = last_names [num_people-1];
indices[index_to_delete] = indices[num_people-1];
num_people -= 1;
qsort( indices, ... );
}
Dynamic data, dynamic arrays
This works very much like the static array version, only your arrays are dynamically-allocated.
char ** first_names = NULL;
char ** last_names = NULL;
int * indices = NULL;
int num_people = 0;
...
first_names = malloc( new_num_people * sizeof(*first_names) );
last_names = malloc( new_num_people * sizeof(*last_names) );
indices = malloc( num_num_people * sizeof(*indices) );
if (!first_names || !last_names || !indices)
{
free( indices );
free( last_names );
free( first_names );
fooey();
}
num_people = new_num_people;
Using realloc() to increase the size of your arrays works as usual as well, with the added complexity that you must check that every array was reallocated successfully.
Eliminating the index array
That index array can be kind of obnoxious. It would be nice to get rid of it after sorting. And, of course, you can!
Create it dynamically before sorting, initializing it to 0, 1, 2, ... as always, sort using the array intermediary, and then take the time to rearrange the other arrays with the new order.
void sort_fruits_by( void (*comparitor)(const void *, const void *) )
{
int indices[num_fruits];
for (int n = 0; n < num_fruits; n += 1)
indices[n] = n;
qsort( indices, num_fruits, sizeof(*indices), comparitor );
reorder_people_by_index( indices );
}
This rearrange bit is what takes some time and space:
void reorder_people_by_index( int * indices )
{
char * temp_names[num_people];
memcpy( temp_names, first_names, num_people*sizeof(char*) );
for (int n = 0; n < num_people; n += 1)
first_names[indices[n]] = temp_names[n];
memcpy( temp_names, last_names, num_people*sizeof(char*) );
for (int n = 0; n < num_people; n += 1)
last_names[indices[n]] = temp_names[n];
}
For the people we could reuse the char * temporary, but for fruits we would need both an int temporary and a char * — one for each type of parallel array.
Now the parallel arrays themselves are sorted differently. But you lose the sorting-an-array-of-integers-only advantage.
Conclusions
You can see that it really isn’t too difficult to maintain parallel arrays. The grief is in the details — you are maintaining multiple arrays!
This is why having a single array of structured data is ever so much more convenient.
But, if you have to do it with parallel arrays, it can be done.

How to return a matrix of all occurrences of given word/pattern?

I am trying to implement a function that's called Sniffer which gets two inputs and returns the correspond matrix.
First input is an integer binary array values (just zeros or ones)
second input is your searched word ( the word you choose it as argument to your function )
The functionally of the function :
Searching for occurrence of the given word within your given binary array.
At each occurrence of your word there's always follows 8 bits following it, assume that always the input is correct (it means that there's no possibility two occurrence occur one after the other without at least there's space 8bits (8 binary values)!).
Then the function must return a matrix(integer matrix) of those followed 8bit for each occurrence of the word sorted corresponded by every row of the matrix. (the functions returns just the first 8bit followed each occurrence of the Searched word)
This means:
First row has first 8 followed bit on first occurrence of the word.
Second row has first 8 followed bit on second occurrence of the word.
Third row has first 8 followed bit on third occurrence of the word.
Fourth row has first 8 followed bit on fourth occurrence of the word.
etc ...
I will elaborate by examples:
function structure is
Code:
int ** SnifferPattern(int* givenArray , int* SearchedWord);
//it returns the corresponded matrix so used int** ;
example 1:
givenArray = {1,0,1,0,1,1,1,1,1,1,1,1,0,0};
SearchedWord = {1,0,1,0};
so the function returns a matrix(size 1x8 - 8 corresponds to 8followed bit)
the first row is {1,1,1,1,1,1,1,1}, which is the first 8 bit followed
the word 1010 the matrix here with one row because there's just
one occurrence of the `SearchedWord` in the given array.
example 2:
givenArray = {1,1,0,0,1,1,1,1,1,1,1,1,1,1,0,0,1,0,1,0,1,0,1,0};
SearchedWord = {1,1,0,0}
so the function returns a matrix the first row is {1,1,1,1,1,1,1,1}
which is the first 8 bit followed the word 1010 for the first occurrence.
for the second occurrence we see the word appear , so the second row of
the returned matrix(size 2x8) will include the first 8bit followed the
word 1010 of the second occurrence. so second row of the matrix
is {1,0,1,0,1,0,1,0} so the returned matrix (size 2x8) has two rows
(because there's two occurrences of the SearchedWord) which each row
corresponds to each occurrence of the SearchedWord.
example 3:
givenArray = {1,1,1,0,1,1,1,1,1,1,1,1,0,0};
SearchedWord = {0,1,0}
so the function returns a matrix zero row (like an array with zero values)
size 1x8 (8 columns is corresponded to 8followed bit). There's no
occurrence of the SearchedWord within the givenArray so we return a zero
matrix. There's no overlap between the occurrences of the searchedWords ,
so we assume always correctness of input.
I will explain my algorithm (a pleasure if there's another suggestions more compatible to my case)
My algorithm is searching for the word at every occurrence and then take at every occurrence the first followed 8bit. I take them and store them in a matrix's rows. But it sounds much hard to complete with this.
what I succeeded / tried to implement in C is this:
int ** SnifferPattern(int* s ; int* w)
{
// s is the given array, w is the searched Word , number occurrences
// here 2 , so it should be two prints on the output of the program.
int n;
int a[1000];
int i=0;
int j;
int k = 0;
int l;
int found = 0;
int t = 0;
a[k++] = i;
j = 0;
for (i = 0; i < k; i++)
{
n = a[i] - j;
if (n == (sizeof(w)/sizeof(w[0])))
{
t = 0;
for (l = 0; w[l]; l++)
{
if (s[l + j] == w[l])
{
t++; // Matched a character.
}
}
if (t == (sizeof(w)/sizeof(w[0])))
{
found++; // We found a match!
printf("word occurred at location=%d \n", j); // Pint location
}
}
j = a[i] + 1;
}
}
int main() {
int s[1000] = {1,0,1,1,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,1};
int w[1000] = {1,0,1};
// s is the given array, w is the searched Word , number occurrences
// here 2 , so it should be two prints on the output of the program.
SnifferPattern(s , w)
//I should print all the matrix's row in the main function .
return 0;
}
I think I have figured out what you need. And, as stated in your question ("at each occurrence of your word there's always follows 8 bits"), the following requires that a least 8-integers follow any match of w in s. Since you will include 8-integers in each row of the matrix you return, then using a pointer-to-array-of int[8] allows a single free() of the result in the caller.
Your sniffer function will loop over each integer in s keeping a counter index (ndx) of each time an integer in w matches the integer in s. When ndx equals the number of elements in w a match has been found and the next 8 integers are are collected as the columns in that row of your matrix using next8 as the index. You could write your sniffer function as:
#define AFTER 8
/* function returning allocated pointer to array of 8 int, *n of them */
int (*sniffer (int *s, int selem, int *w, int welem, int *n))[AFTER]
{
int ndx = 0, /* match index */
next8 = AFTER, /* counter for next 8 after match found */
found = 0, /* number of tiems w found in s */
(*matrix)[AFTER] = NULL;
for (int i = 0; i < selem; i++) { /* loop over each int in s */
if (next8 < AFTER) { /* count if next8 less than AFTER */
matrix[found-1][next8++] = s[i]; /* set next8 index in matrix row */
}
else if (s[i] == w[ndx]) { /* if s[i] matches w[ndx] */
if (++ndx == welem) { /* increment ndx, compare w/welem */
/* allocate storage for next row in matrix */
if (!(matrix = realloc (matrix, (found + 1) * sizeof *matrix))) {
perror ("realloc-matrix"); /* on failure, handle error */
*n = 0;
return NULL;
}
/* (optional) set all elements in row 0 */
memset (matrix[found], 0, sizeof *matrix);
found += 1; /* increment found count */
ndx = next8 = 0; /* reset ndx, set next8 to count */
}
}
else /* otherwise, not a match and not counting */
ndx = 0; /* set match index to 0 */
}
*n = found; /* update value at n to found, so n available in main */
return matrix; /* return allocated matrix */
}
(note: the number of elements in s is provided in selem and the number of elements in w is provided by welem)
Changing your s[] in main to int s[] = {1,0,1,0,0,0,0,1,1,1,1,1,0,1,1,1,1,1,0,0,0,0} so it is easy to verify the results, you could write you program as:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define ARSZ 1000 /* if you need a constant, #define one (or more) */
#define AFTER 8
/* function returning allocated pointer to array of 8 int, *n of them */
int (*sniffer (int *s, int selem, int *w, int welem, int *n))[AFTER]
{
int ndx = 0, /* match index */
next8 = AFTER, /* counter for next 8 after match found */
found = 0, /* number of tiems w found in s */
(*matrix)[AFTER] = NULL;
for (int i = 0; i < selem; i++) { /* loop over each int in s */
if (next8 < AFTER) { /* count if next8 less than AFTER */
matrix[found-1][next8++] = s[i]; /* set next8 index in matrix row */
}
else if (s[i] == w[ndx]) { /* if s[i] matches w[ndx] */
if (++ndx == welem) { /* increment ndx, compare w/welem */
/* allocate storage for next row in matrix */
if (!(matrix = realloc (matrix, (found + 1) * sizeof *matrix))) {
perror ("realloc-matrix"); /* on failure, handle error */
*n = 0;
return NULL;
}
/* (optional) set all elements in row 0 */
memset (matrix[found], 0, sizeof *matrix);
found += 1; /* increment found count */
ndx = next8 = 0; /* reset ndx, set next8 to count */
}
}
else /* otherwise, not a match and not counting */
ndx = 0; /* set match index to 0 */
}
*n = found; /* update value at n to found, so n available in main */
return matrix; /* return allocated matrix */
}
int main (void) {
int s[] = {1,0,1,0,0,0,0,1,1,1,1,1,0,1,1,1,1,1,0,0,0,0},
w[] = {1,0,1},
n = 0,
(*result)[AFTER] = NULL;
result = sniffer (s, sizeof s/sizeof *s, w, sizeof w/sizeof *w, &n);
for (int i = 0; i < n; i++) { /* loop over result matrix */
printf ("matrix[%d] = {", i); /* output prefix */
for (int j = 0; j < AFTER; j++) /* loop over column values */
printf (j ? ",%d" : "%d", result[i][j]); /* output column value */
puts ("}"); /* output suffix and \n */
}
free (result); /* free allocated memory */
}
Example Use/Output
$ ./bin/pattern_in_s
matrix[0] = {0,0,0,0,1,1,1,1}
matrix[1] = {1,1,1,1,0,0,0,0}
If I have misunderstood your question, please let me know in a comment below and I'm happy to help further. Let me know if you have any questions.
There are several issues you must solve.
How are arrays represented?
You have arrays of integers, whose valid values can be 0 or 1. How do you datermine the length of sich an array. There are basically two possibilities:
Use a sentinel value. That's how C strings are stored: The actual string is terminated by the special value '\0', the null terminator. The memory used to store the string may be larger. In your case, you could use a value that isn't used:
enum {
END = -1
};
int a[] = {0, 1, 0, 1, END};
The disadvantage here is that you must be careful not to forget the explicit terminator. Also, if you want to find out the length of an array, you must walk it to the end. (But that's not an issue with small arrays.)
Use an explicit length that goes along with the array.
int a[] = {1, 0, 1, 0};
int alen = sizeof(a) / sizeof(*a);
The disadvantage here is that you must pass the length to any function that operates on the array. The function f(a) does not know kow long a is; the function should be something like f(a, alen). (The sizeof(a) / sizeof(*a) mechanism works only when the array a is in scope. See here for a discussion on how to find the length of an array.)
You could, of course, define a struct that combines data and length.
How do you return an array from a function?
That's your actual question. Again there are several possibilities:
Return the array. That usually means to allocate the array you want to return on the heap with malloc, which means that the caller must call free on the result at some time. The caller must know how big the returned array is. You can use sentinels as described above or you could pass in a pointer to a sive variable, which the function fills in:
int **f(..., int *length) { ... }
Call this function like this:
int length;
int **p = f(..., &length);
for (int i = 0; i < length; i++) ...
Pass in an array and hve the function fill it. That means that the function must know about the size of the array. The return value can be used to return the actual size of the array:
int f(..., int **res, int max) { ... }
Call this function like this:
int *p[20];
int length = f(..., p, 20);
for (int i = 0; i < length; i++) ...
Let's apply this to your problem.
You want to match a pattern in a string and then return a list of all 8-bit sequences after the matches. Let's represent an array as array + length. Your function might then look like this:
int sniffer(const int *s, int slen, // haystack array + length
const int *w, int wlen, // needle array + length
const int **res, int reslen) // results array
{ ... }
It passes in the arrays s and w plus their lengths. It also passes in a third array plus its length. That array hold the results. The number of valid results – the number of rows in your matrix – is the returned value.
Call this function:
int s[] = {...};
int w[] = {...};
const int *res[8];
int n = sniffer(s, sizeof(s) / sizeof(*s),
w, sizeof(w) / sizeof(*w),
res, sizeof(res) / sizeof(*res));
What happens if there are more than reslen matches? The excess matches cannot be written, of course, but do they contribute to the return value? If they do, you could pass in an array length of 0 just to see how many matches there are. (That'
s what the string function snprintf does, in a way.) If they don't you get the exact length of the result array. Both strategies are valid.
Here's an example implementation. It uses your test case #2:
#include <stdlib.h>
#include <stdio.h>
/*
* test whether the next len elements of s and w match
*/
int match(const int *s, const int *w, int len)
{
while (len-- > 0) {
if (*s++ != *w++) return 0;
}
return 1;
}
int sniffer(const int *s, int slen, // haystack array + length
const int *w, int wlen, // needle array + length
const int **res, int reslen) // results array
{
int n = 0;
for (int i = 0; i <= slen - wlen - 8; i++) {
const int *p = s + i;
if (match(p, w, wlen)) {
if (n < reslen) res[n] = p + wlen;
n++;
}
}
return n;
}
int main(void)
{
int s[] = {1, 1, 0, 0, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 0, 0,
1, 0, 1, 0, 1, 0, 1, 0};
int w[] = {1, 1, 0, 0};
const int *res[8];
int reslen = sizeof(res) / sizeof(*res);
int n = sniffer(s, sizeof(s) / sizeof(*s),
w, sizeof(w) / sizeof(*w),
res, reslen);
printf("%d patterns:\n", n);
for (int i = 0; i < n && i < reslen; i++) {
printf("[%d] {", i);
for (int j = 0; j < 8; j++) {
if (j) printf(", ");
printf("%d", res[i][j]);
}
printf("}\n");
}
return 0;
}

Replace a subarray with a character in C

I have an array and I need to replace a subarray from this array with a character.
unsigned char * data = {'a','b','c','d','e'};
I need to delete 'a','b''c' and insert 'R'
The final array will be: unsigned char * data = {'R','d','e'};
With only 3 elements.
How can I do that in C?
You say you think of data as an array, therefore it is better that you declare data as an array instead of a pointer. (The way your code is now you have a pointer that is initialized incorrectly by casting the character 'a' to a char * pointer. That way it will not be pointing anywhere.)
You can replace characters by assigning to elements of the array, and you can shift parts of the data in the array using memmove.
Which means that maybe you want something like this:
unsigned char data[] = {'a','b','c','d','e'};
data[0] = 'R';
memmove(data + 1, data + 3, sizeof(data) - 3);
The memmove call moves sizeof(data) - 3 bytes of data from address data + 3 to address data + 1. The function memmove even works when the regions of memory between which you are moving bytes of data overlap.
If you then print the relevant part of your data:
fwrite(data, 1, sizeof(data) - 2, stdout);
putchar('\n');
This will get you the output:
Rde
However, notice that the size of the array will not have changed. It still will be five characters long. So replacing abc by something longer than three characters will not work like this. Also, this array is not a null-terminated string, which is the more usual way to have sequences of characters in C.
If you prefer to use a string "abcde" instead of what you are doing now (but then why call it "data"?), add a comment below this answer, and I'll extend it.
for(int i = 0; i < 5; i++){
if (data[i] > 96 && data[i] < 100) data[i] = 'R';
}
How about the following way?
unsigned char * data = {'a','b','c','d','e'};
int length = strlen(data);
unsigned char * output = (unsigned char *)malloc(sizeof(unsigned char)*length);
for(int i = 0, j =0; i < length; i++, j++){
if (i+2 < length && data[i] == 'a' && data[i+1] == 'b && data[i+2] == 'c') {
output[j]='R';
i++;
i++;
}
else
output[j]=data[i];
}

What does this C code snippet mean?

I've come across this piece of code here.
result = HMAC(EVP_md5(), key, 32, data, 28, NULL, NULL);
for (i = 0; i < result_len; i++) {
sprintf(&(res_hexstring[i * 2]), "%02x", result[i]);
}
what does the loop do? In particular what does &(res_hexstring[i * 2]) mean? Can't you just iterate through result as an array? Why is it an integer?
It converts the hash result to a string:
e.g., from:
char result[2] = {0xa1, 0xb2};
to
char res_hexstring[4 + 1] = {'a', '1', 'b', '2', '\0'}
The expression i * 2 appears in &res_hexstring[i * 2] because the byte 0xa1 needs two characters ('a' and '1') to be represented in a string.
The advantage of having a string is it can be then easily displayed:
printf("%s\n", res_hexstring); // display the hash result
for (i = 0; i < result_len; i++) {
sprintf(&(res_hexstring[i * 2]), "%02x", result[i]);
}
sprintf prints the result from the binary array result 1 byte <=> 2 nibbles / hexadecimal digits at a time into the buffer res_hexstring.
Which is the reason the left index goes 2 byte for each 1 byte the second is moved.
Of course, not using sprintf would be much faster, but it would also need a bit more code.
(Which might result in a bigger or smaller binary, but that must be measured if of interest.)
inline char to16digit(int x) { return x<10 ? '0'+x : 'A'-10+x; }
for (i = 0; i < result_len; i++) {
res_hexstring[i*2] = to16digit(result[i]>>4);
res_hexstring[i*2+1] = to16digit(result[i]&15);
}
res_hexstring[2*result_len] = 0;
There are various reasons you might want it in a human-readable form, serializing, printing and logging prominent among them. (And printf does not have a format to print such big numbers in hexadecimal notation.)

Resources