is there a function that lets me look at the next char? - c

is there a function in c that lets me look at the next char in an array? Also where could I find this information on my own, I tried Google and looking for existing threads on this site.
I am trying to pull numbers from a line, and store those numbers. So I want to do something like
if(c = a number and c "next character" is not a number){value is = value*10+c-'0', store number}

If the current character is array[i], the next character is array[i+1].

You could write a method to do this:
char next_char(char *array, int i, int size){
return (++i) < size ? array[i] : '\0';
}
EDIT: After reading your question something like this may be reasonable.
if(isdigit(array[i]) && !isdigit(next_char(array,i,size)){
..
}
A better solution would be a for loop:
int val = 0;
for(i = 0; i < size; i++){
if(isdigit(i)){
val = 10 * val + array[i] - '0';
}else{
// Store the value
val = 0;
}
}

To get a char from a char array, you just use:
array[i]
where is is an index.
If you want to read every char, you can use a loop:
for(size_t i = 0; i < sizeof(array); i++)
{
char cur = array[i];
}
You could also increment a pointer.

Related

Concatenating uint8_t to a char*

im really new to C and im having a bit of a complication creating a char* from various uint8_t
My idea is to create a char* where in each location I place a number form a matrix
For example if I have a matrix with:
[1][2][3][4]
[5][6][7][8]
[9][0][1][2]
[3][4][5][6]
id like a char* thats "01234567890123456"
what im doing bit its not working is:
char* string = malloc(sizeof(char)*matrix->height*matrix->width);
for (int i = 0; i < matrix->height ; ++i) {
for (int j = 0; j < matrix->width ; ++j) {
string[i*matrix->height+j] = matrix->value[i][j];
}
}
of course its not working but im a bit lost on how to proceed and I cant find more information regarding this problem.
Any help would be nice,
thanks
Since you're trying to print a string, you need the ASCII character for 0. So, simply add '0' to each number, like so
char* string = malloc(sizeof(char)*(matrix->height*matrix->width + 1));
for (int i = 0; i < matrix->height ; ++i) {
for (int j = 0; j < matrix->width ; ++j) {
string[i*matrix->width+j] = matrix->value[i][j] + '0';
}
}
string[matrix->height*matrix->width] = 0; //null terminator
Note however this isn't exactly the most portable solution.
Also, notice that you want to multiply i by the width, because if you didn't have a square matrix your calculation wouldn't work correctly.
It's kind of unnecessary to have sizeof(char), because the size of a char is defined to be 1 regardless of the byte size.

Remove some elements from array and re-size array in C

Regards
I want to remove some elements from my array and re-size it.
for example my array is:
char get_res[6] = {0x32,0x32,0x34,0x16,0x00,0x00};
Now I want to remove elements after 0x16, so my desire array is:
get_res[] = {0x32,0x32,0x34,0x16};
what is solution?
You cannot resize arrays in C (unlike Python, for example). For real resizing, at least from an API user's point of view, use malloc, calloc, realloc, and free (realloc specifically).
Anyway, "resizing" an array can be imitated using
a delimiter; for example, a delimiter like 0xff could mark the end of the valid data in the array
Example:
#define DELIMITER 0xff
print_data(char* data) {
for (size_t i = 0; data[i] != DELIMITER; ++i)
printf("%x", data[i]);
}
a member counter; count the number of valid data from the beginning of the array onward
Example:
size_t counter = 5;
print_data(char* data) {
for (size_t i = 0; i < counter; ++i)
printf("%x", data[i]);
}
Notes:
Use unsigned char for binary data. char may be aliasing signed char, which you might run into problems with because signed char contains a sign bit.
There is no need to "remove" them. Just don't access them. Pretend like they don't exist. Same like in stacks, when you "pop" a value from the top of the stack, you just decrement the stack pointer.
Manipulating arrays in C isn't easy as it is for vector in C++ or List in Java. There is no "remove element" in C. I mean that you have to do the job yourself, that is, create another array, copy only the elements you want to this new array, and free the memory occupied by the previous one.
Can you do that? Do you want the code?
EDIT:
Try that. It's just a simple program that simulates the situation. Now, you have to see the example and adapt it to your code.
#include <stdio.h>
#include <stdlib.h>
int main() {
char get_res[6] = {0x32,0x32,0x34,0x16,0x00,0x00};
char target = 0x16;
int pos, i, length = 6; // or specify some way to get this number
for(i = 0; i < length; i++)
if(get_res[i] == target) {
pos = i;
break;
}
pos = pos + 1; // as you have to ignore the target itself
char *new_arr = malloc(pos);
for(i = 0; i < length; i++) {
new_arr[i] = get_res[i];
i++;
}
for(i = 0; i < pos; i++)
printf("%c ", new_arr[i]);
return 0;
}

How to find an element in an array of structs in C?

I have to write a function that finds a product with given code from the given array. If product is found, a pointer to the corresponding array element is returned.
My main problem is that the given code should first be truncated to seven characters and only after that compared with array elements.
Would greatly appreciate your help.
struct product *find_product(struct product_array *pa, const char *code)
{
char *temp;
int i = 0;
while (*code) {
temp[i] = (*code);
code++;
i++;
if (i == 7)
break;
}
temp[i] = '\0';
for (int j = 0; j < pa->count; j++)
if (pa->arr[j].code == temp[i])
return &(pa->arr[j]);
}
Why don't you just use strncmp in a loop?
struct product *find_product(struct product_array *pa, const char *code)
{
for (size_t i = 0; i < pa->count; ++i)
{
if (strncmp(pa->arr[i].code, code, 7) == 0)
return &pa->arr[i];
}
return 0;
}
temp is a pointer which is uninitialized and you are dereferencing it which will lead to undefined behavior.
temp = malloc(size); // Allocate some memory size = 8 in your case
One more mistake I see is
if (pa->arr[j].code == temp[i]) // i is already indexing `\0`
should be
strcmp(pa->arr[j].code,temp); // returns 0 if both the strings are same
This code can completely be avoided if you can use strncmp()
As pointed out by others, you are using temp uninitialized and you are always comparing characters with '\0'.
You don't need a temp variable:
int strncmp ( const char * str1, const char * str2, size_t num );
Compare characters of two strings
Compares up to num characters of the
C string str1 to those of the C string str2.
/* Don't use magic numbers like 7 in the body of function */
#define PRODUCT_CODE_LEN 7
struct product *find_product(struct product_array *pa, const char *code)
{
for (int i = 0; i < pa->count; i++) {
if (strncmp(pa->arr[i].code, code, PRODUCT_CODE_LEN) == 0)
return &(pa->arr[i]);
}
return NULL; /* Not found */
}
When you write char* temp; you are just declaring an uninitialized pointer
In your case since you say that the code is truncated to 7 you could create a buffer
on the stack with place for the code
char temp[8];
Writing
temp[i] = (*code);
code++;
i++;
Can be simplified to:
temp[i++] = *code++;
In your loop
for (int j = 0; j < pa->count; j++)
if (pa->arr[j].code == temp[i])
return &(pa->arr[j]);
You are comparing the address of code and the character value of temp[i] which incidentally could be 8 and outside the array.
Instead what you want to do is compare what code points to and what temp contains:
for (int j = 0; j < pa->count; j++)
if (!strncmp(pa->arr[j].code, temp, 7)
return &(pa->arr[j]);
You should also return NULL; if nothing was found, seems you do not return anything.
Probably a good thing is also to make sure your temp[] always contains 7 characters.

realloc() seems to affect already allocated memory

I am experiencing an issue where the invocation of realloc seems to modify the contents of another string, keyfile.
It's supposed to run through a null-terminated char* (keyfile), which contains just above 500 characters. The problem, however, is that the reallocation I perform in the while-loop seems to modify the contents of the keyfile.
I tried removing the dynamic reallocation with realloc and instead initialize the pointers in the for-loop with a size of 200*sizeof(int) instead. The problem remains, the keyfile string is modified during the (re)allocation of memory, and I have no idea why. I have confirmed this by printing the keyfile-string before and after both the malloc and realloc statements.
Note: The keyfile only contains the characters a-z, no digits, spaces, linebreaks or uppercase. Only a text of 26, lowercase letters.
int **getCharMap(const char *keyfile) {
char *alphabet = "abcdefghijklmnopqrstuvwxyz";
int **charmap = malloc(26*sizeof(int));
for (int i = 0; i < 26; i++) {
charmap[(int) alphabet[i]] = malloc(sizeof(int));
charmap[(int) alphabet[i]][0] = 0; // place a counter at index 0
}
int letter;
int count = 0;
unsigned char c = keyfile[count];
while (c != '\0') {
int arr_count = charmap[c][0];
arr_count++;
charmap[c] = realloc(charmap[c], (arr_count+1)*sizeof(int));
charmap[c][0] = arr_count;
charmap[c][arr_count] = count;
c = keyfile[++count];
}
// Just inspecting the results for debugging
printf("\nCHARMAP\n");
for (int i = 0; i < 26; i++) {
letter = (int) alphabet[i];
printf("%c: ", (char) letter);
int count = charmap[letter][0];
printf("%d", charmap[letter][0]);
if (count > 0) {
for (int j = 1; j < count+1; j++) {
printf(",%d", charmap[letter][j]);
}
}
printf("\n");
}
exit(0);
return charmap;
}
charmap[(int) alphabet[i]] = malloc(sizeof(int));
charmap[(int) alphabet[i]][0] = 0; // place a counter at index 0
You are writing beyond the end of your charmap array. So, you are invoking undefined behaviour and it's not surprising that you are seeing weird effects.
You are using the character codes as an index into the array, but they do not start at 0! They start at whatever the ASCII code for a is.
You should use alphabet[i] - 'a' as your array index.
The following piece of code is a source of troubles:
int **charmap = malloc(26*sizeof(int));
for (int i = 0; i < 26; i++)
charmap[...] = ...;
If sizeof(int) < sizeof(int*), then it will be performing illegal memory access operations.
For example, on 64-bit platforms, the case is usually sizeof(int) == 4 < 8 == sizeof(int*).
Under that scenario, by writing into charmap[13...25], you will be accessing unallocated memory.
Change this:
int **charmap = malloc(26*sizeof(int));
To this:
int **charmap = malloc(26*sizeof(int*));

Concat LPSTR in C

Trying to use as basic C as I can to build a list of numbers from 1-52 in a random order (deck of cards). Everything works, but all of my attempts to concat the strings and get a result end in failure. Any suggestions? NOTE: This is not homework it's something I'm using to create a game.
// Locals
char result[200] = ""; // Result
int card[52]; // Array of cards
srand(time(0)); // Initialize seed "randomly"
// Build
for (int i=0; i<52; i++) {
card[i] = i; // fill the array in order
}
// Shuffle cards
for (int i=0; i<(52-1); i++) {
int r = i + (rand() % (52-i));
int temp = card[i]; card[i] = card[r]; card[r] = temp;
}
// Build result
for (int c=0; c<52; c++) {
// Build
sprintf(result, "%s%d", result, card[c]);
// Comma?
if ( c < 51 )
{
sprintf(result, "%s%s", result, ",");
}
}
My end result is always garbled text. Thanks for the help.
You keep writing to the same position of "result".
sprintf is not going to do the appending for you.
You may consider, after each sprintf, get the return value (which is the number of char written), and increment the pointer to result buffer. i.e. something like:
(psuedo code):
char result[200];
char * outputPtr = result;
for (int c=0; c<52; c++) {
// Build
int n = sprintf(outputPtr, "%d%s", card[c], (c<51 ? "," : ""));
outputPtr += n;
}
Are we writing C++ or C? In C++, concat-ing a string is just:
string_out = string_a + string_b
…since you'd be using std::string.
Furthermore, if this is C++, the STL has a std::shuffle function.
If this is C, note that all your sprintfs aren't concatenating strings, they're just overwriting the old value.
I think, if memory serves, that sprintf will always write into the buffer starting at byte 0. This means that you would be writing the first couple of bytes over and over again with a number, then a comma, then a number. Check if your first bytes are ",[0-9]" - if so, that's your issue.
This would add a comma between each number in the result string:
// Get a pointer to the result string
char* ptr = &result[0];
for (int c = 0; c < 52; c++) {
// Add each cards number and increment the pointer to next position
ptr += sprintf(ptr, "%d", card[c]);
// Add a separator between each number
if (c < 51) {
*ptr++ = ',';
}
}
// Make sure the result string is null-terminated
*ptr = 0;

Resources