How to convert an array of char to array of int [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Is there a way to convert an array of char to array of int32 without iterating every member.
I need to convert a huge amount of data so I'm looking for some faster than:
char ac[1000000];
int32_t ai[1000000];
for(int i=0;i<1000000;i++) {
ai[i]=ac[i];
}
Notes:
I'm not asking about how to convert '3' to 0x03, I'm talking about convert 0x03 (one byte) to 0x00000003 (to 4 bytes)
Not portable is not a problem (platform linux AMD64).
The proposed method is slow.
looking for a library that use SSE instructions or similar.
I need it to feed a math function that works with int32 numbers and my original data is in 8 bits size, so I need to convert it, and obviously I can't cast because is an memory area not a value.

Is there a way to convert an array of char to array of int without iterate every member.
No.
Trying to explain this (I assumed it would be obvious): an int is a different size than a char, so no block copies would ever help you. In one or another way, you have to touch each element.
There might be solutions parallelizing this, e.g. by partitioning the array and using threads to handle the parts. But you would still have to convert each and every element.
Regarding your edit:
convert 0x03 (one byte) to 0x0003 (to bytes)
[...] not portable is not a problem (platform linux AMD64)
There seems to be another misconception: int on Linux x86_64 has four bytes, not two. If you really need two bytes per input value, you should use int16_t.
And yet another remark: Typical SIMD instructions (like in SSE2) won't help you either. They assume the same layout of input and output areas. As already stated, the only "optimization" I can possibly see is parallelizing. There's no way around having to touch each element.

Not sure if this will be faster, you have to check (also it will be depend on the sizeof(int) == 4):
// note: untested
char ac[1000000];
int ai[1000000];
memset(ai, 0, sizeof(int) * 1000000); // this should be very fast
char * d = (char *) (ai + 3); // go to last byte of the first int
for(int i=0;i<1000000;i++) {
d += 4; // go to last byte of the next int
*d=ac[i];
}

Are you sure you need ints?
If not, you could do
char ac[1000000];
uint8_t *ai = (uint8_t*)ac;
if the reason you want them to be ints is because a function takes an int as argument and you need to pass some of the values of the array to it, then there is no problem with this method, as they will be implicitly casted to ints.
I think that converting them to ints just makes you use more memory than you actually need.
EDIT:
If you actually DO need an int array, here is a workaround that does not store more than it needs.
You can make a helper function that just extracts the char value casted to an int from the newly created int array, hence behaving like an int array.
// Endianness test to extract the char number
constexpr bool endianness() {
return *(int*)const_cast<char*>("\x00\x01") & 1;
}
// Get char value casted to int from the int array
int getVal(int *i, int idx) {
int iidx = idx / sizeof(int);
int rem = idx % sizeof(int);
if(endianness()) rem = sizeof(int) - rem - 1;
return (i[iidx] & (0xff << 8*rem)) >> 8*rem;
}
To use this you just convert the char array to an int pointer and just use it, like so.
char ac[1000000];
int *ai = (int*)ac;
cout << getVal(ai, 0);
This will print the value of the first element casted into an int and is actually portable.

Related

digit to integer in same order C [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have a function called fun(int num, int * array); which takes an int and int array as its arugments. I'm trying to convert int to the array.
When i run the program i don't get the array displayed properly
int fun(int num, int*array) {
int count =0;
while(num>0) {
num/= 10;
count++;
}
array[count];
// for loop works
}
When i print the array in the program i.e. everytime I run the program i get random digits.
What this line is supposed to do ?
array[count];
Since your integer array will change in your fun function, you have to allocate the memory (by using malloc, realloc, ...).
edit : plus, you already change the value hold by "num" when you count how many digit there are in "num".
Make a copy of "num" !
edit 2 : the more i look your function, the more it seem you will have problem using it.
Fisrt, you want to explode your integer into an array of int.
Okay, but integer have range, thus meaning integer have a maximum digit.
From my memories, there are 20 digit in an 64bit integer.
So you can simply use "int array[NB_DIGIT_INT_MAX];" with "#define NB_DIGIT_INT_MAX 21".
So, allocating is not necessary AND add complexity in your code (the caller will have to free after the function call).
Second, your fun function doesn't say how many case will hold your integer.
Let's say num = 12, your array will have "array[0] = 1, array[1] = 2", but how do you know where to stop ?
If num = 2345, how do you know that only the 4 first case in your array is legit ?
There are 2 way : You have an another variable that hold the actual size of the array, or you have a special value in your array that say "it's the end" (like '\0' for char array used as string).
You can use "-1".
Let's give a try, and don't hesitate to ask question if thing are unclear (english is not my motherlanguage)
Your array is not even allocated, this can not work as expected. You are even lucky not to have a segmentation fault. If you want to add an integer to an array making it grow, you need to allocate a larger array, copy the values and add the new one to the new array and delete the previous array, keeping array variable as a pointer to the new array. Moreover, you need to pass the size of the actual array as an argument of fun.
The count variable can be global, Initialize it outside all functions like this
short count;
The whole program could be modified like below
#include<stdio.h>
#include<stdlib.h>
short count;
void fun(int num, int **ptr) {
// You need a pointer to a pointer and return type can be void
int num_copy=num;
count=0; // Setting the count to zero
while(num_copy>0) {
num_copy/= 10; // Don't modify the original number
count++;
}
//Allocate enough memory to store the digits
*ptr=malloc(count*sizeof **ptr);
if(NULL==*ptr){
perror("Can't allocate memory");
exit(1);
}
// Then do the loop part with original num
for(int i=count -1; i>=0; i--) {
(*ptr)[i] = num%10;
num /= 10;
}
// By now you have an array 'array' of integers which you could print in main.
}
int main()
{
int number = 123456789;
int *array;
fun(number,&array); // &array is of type pointer to a pointer to integers
//Now print the individual digits
printf("Individual digits are : \n");
for(int i=count-1;i>=0;i--)
printf("%d\n",array[i]);
}
Looks to me like you are converting from an integer to digits. But I don't see where your code writes anything to the array.
If the array wasn't initialized before this, that would explain why it still contains random values.

Looking at and using individual bytes in void pointers in C [duplicate]

This question already has answers here:
What does void* mean and how to use it?
(10 answers)
Closed 5 years ago.
I'm trying to make a calculator that takes a void pointer called yourVal, look at the first byte and decide if it's a '*' or '/'. Based on the sign, i multiply bytes 3+4, 5+6, and 7+8. say i have *1234567. I multiply 23 * 45 * 67. With the division, I divide byte 5(45) by byte 3(23). I'm a novice with pointers in C, and I really have no idea how to even set a value to a void pointer. When I do the following in main
void *yourVal;
*yourVal = "*1234567";
printf("%s\n", yourVal);
I'm not able to dereference a void pointer. But I tried with a char pointer, and I have the same issue.
This is my code for the calculator function. Based on whether I use printf or not, I get different results.
int calculator(void *yourVal){
char *byteOne;
short int *byteThree, *byteFive, *byteSeven;
int value;
byteOne = (char *)yourVal;
byteThree = (short int *)yourVal+2;
byteFive = (short int *)yourVal+4;
byteSeven= (short int *)yourVal+6;
if(*byteOne == '*') {
value = *byteThree * *byteFive * *byteSeven;
printf("You multiplied\n");
}
else if(*byteOne == '/') {
if (*byteThree == 0) {
value = 0xBAD;
printf("Your input is invalid\n");
}
else {
value = *byteFive / *byteThree;
printf("You divided\n");
}
}
else {
value = 0xBAD;
printf("Your input is invalid\n");
}
}
The division isn't working at all, and the multiplication only grabs one digit. Any tips would be appreciated. I looked at various sources but I'm not seeing how to work with void pointers efficiently. Also, I can't use any library functions other than printf, and this is a school assignment, so try not to give too many spoilers or do it for me. We were given one hint, which is to cast yourVal to a structure. But I'm lost on that. Thanks
byteOne = (char *)payload;
byteThree = (short int *)yourVal+2;
byteFive = (short int *)yourVal+4;
byteSeven= (short int *)yourVal+6;
This doesn't do what you think it does. If you want to read the numbers at these positions, you need to do something like.
char* Value = yourValue;
unsigned byteOne, byteThree, byteFive, byteSeven;
byteOne = Value[0] - '0';
byteThree = Value[2] - '0';
byteFive = Value[4] - '0';
byteSeven = Value[6] - '0';
What I have done here is read the byte at that position and subtract the ASCII value of '0' to get the numerical value of that character. But again this will work only for a single character.
If you need to read more characters you will have to use library functions like sscanf or atoi.
The void pointer adds no functionality you need to solve this problem, it just complicates things. Use a char pointer instead.
"*1234567" is a string, not an array of integers. You cannot treat it as an array of integers. Each character would have to be converted to an integer before you do arithmetic. The easiest way to do that is to subtract by the ASCII character '0'.
"...i multiply bytes 3+4..." When counting bytes, you always start at 0. In the string "*1234567", the 2 is the byte with index 2 not 3.
"Based on the sign, i multiply bytes 3+4, 5+6, and 7+8. say i have *1234567. I multiply 23 * 45 * 67. With the division, I divide byte 5(45) by byte 3(23)"
I fail to see how this algorithm makes any sense. What is the 1 there for? Why aren't you using some conventional formatting such as prefix, postfix or just plainly typed-out equations?
Example:
int calculator (const char* yourVal)
...
int byte2 = yourVal[2] - '0';

How do I add numbers that are successive bytes to display an integer using the printf function? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I'm trying to get successive bytes to print on the screen for the file that I'm reading. The file that is being read in a .vdi file and I'm trying to display the size of the virtual drive in a printf format.
How can I display the integer values of the read in byte values from the file?
I'm still kind of fuzzy on how C works with the printf function. My code:
void get_file_size(u32 fd) {
u8* HDDsize = (u8 *)malloc(8);
if(HDDsize == NULL) {
printf("Memory not allocated!");
}
lseek(fd,DRIVE_SIZE,SEEK_SET);
read(fd,HDDsize,8);
printf("The file system size is: %lli\n",
HDDsize[7]+HDDsize[6]+HDDsize[5]+HDDsize[4]+
HDDsize[3]+HDDsize[2]+HDDsize[1]+HDDsize[0]);
free(HDDsize);
}
To print a value of 4-bytes stored in little endian (least significant byte in lowest address), code needs to scale each byte, not simple add them up. Each byte is 256x more significant than the neighboring byte. Use:
#include <stdint.h>
#include <stdio.h>
void Print_Size4(int fd) {
uint8_t HDDsize[4];
if (lseek(fd, DRIVE_SIZE,SEEK_SET) == -1) return;
if (read(fd, HDDsize, sizeof HDDsize) != sizeof HDDsize) return;
printf("The file system size is: %lu\n",
// LU --> insure all math is at least of unsigned long
(((HDDsize[3] * 256LU + HDDsize[2]) * 256 + HDDsize[1]) * 256 + HDDsize[0]));
}
Better to use standard fixed types like uint8_t than u8. malloc() not needed.
I'll leave it to OP to make an 8-byte one-line solution. Hint: also use LLU or uint64_t math.
Maybe use a loop.
uint64_t size = 0;
for (unsigned i=sizeof HDDsize; i>0; i--) {
size = size*256 + HDDsize[i-1];
}
Research <inttypes.h> to find the best printf() format specifier for uint64_t.
What you are doing is just summing the values of all those bytes and then printing the resulting sum.
Since those bytes are in an array, so they are consecutive in the memory, you can try something like this:
long long number = *((long long*)HDDSize);
so it will look at those 8 bytes as a long long variable.
it might show it backwards though (so you will need to reverse that array).

Initialising array with unknown size in C [duplicate]

This question already has answers here:
Length of array in function argument
(9 answers)
Closed 7 years ago.
I have this piece of code:
#include <stdio.h>
int average(int array []);
int main () {
int num_array[];
int x = 0;
while(num_array[x] != -1){
printf("Enter a number\n");
scanf("%d",&num_array[x]);
x++;
}
printf("%d\n", average(num_array));
return 0;
}
int average(int array[]){
int i;
int total_size = (int)sizeof(array);
int sum = 0;
for(i = 0; i < total_size; i++){
sum = sum + array[i];
}
return sum/total_size;
}
But i get an error at compile time, because i'm not initialising the array. However i can't do it, since i don't know it's size.
How can i solve this ?
You can't declare an array like
int num_array[];
in C except when it is a parameter of a function. You must have to specify the size.
This is actually a surprisingly tricky problem in C unless you're using an array library. What you're actually talking about is a growable array. For what you're trying to do, you start with an initial size, say 10, using malloc() and as the inputs grow, you have to realloc() the array to a larger size. Generally, you double the size of the array every time the limit is hit. If you're a beginning C programmer, this is probably too much to take on. I would set a fixed limit, and enforce it by not accepting any more input after the limit is hit. Given that you can comfortably allocate 1000's of ints and a human won't want to type that much, you can easily make a practical limit ahead of time and declare the array as such:
int num_array[1000];
You need to provide the size of the array here: int num_array[];.
If you are working with a structure of unknown size, you could:
Ask the user how many numbers are going to be entered (not really practical, but might suffice if your case is a trivial one).
Initialize it with a default size, say 10 and then if you need, create larger arrays and copying your current data to the new one.
Or else, you use a linked list like data structure and create new elements as you go along, thus allowing your list to grow as much as you need it to be.

converting data types in c

Let me start by saying that I openly admit this is for a homework assignment, but what I am asking is not related to the purpose of the assignment, just something I don't understand in C. This is just a very small part of a large program.
So my issue is, I have a set of data that consists various data types as follows:
[16 bit number][16 but number][16 bit number][char[234]][128 bit number]
where each block represents a variable from elsewhere in the program.
I need to send that data 8bytes at a time into a function that accepts uint32_t[2] as an input. How do I convert my 234byte char array into uint32_t without losing the char values?
In other words, I need to be able to convert back from the uint32_t version to the original char array later on. I know a char is 1byte, and the value can also be represented as a number in relation to its ascii value, but not sure how to convert between the two since some letters have a 3 digit ascii value and others have 2.
I tried to use sprintf to grab 8byte blocks from the data set, and store that value in a uint32_t[2] variable. It works, but then I lose the original char array because I can't figure out way to go back/undo it.
I know there has to be a relatively simple way to do this, i'm just lacking enough skill in C to make it happen.
Your question is very confusing, but I am guessing you are preparing some data structure for encryption by a function that requires 8 bytes or 2 uint32_t's.
You can convert a char array to uint32_t as follows
#define NELEM 234
char a[NELEM];
uint64_t b[(NELEM+sizeof(uint64_t)-1)/sizeof(uint64_t)]; // this rounds up to nearest modulo 4
memcpy(b,a,NELEM);
for(i .. ) {
encryption_thing(b[i]);
}
or
If you need to change endianess or something, that is more complicated.
#include <stdint.h>
void f(uint32_t a[2]) {}
int main() {
char data[234]; /* GCC can explicitly align with this: __attribute__ ((aligned (8))) */
int i = 0;
int stride = 8;
for (; i < 234 - stride; i += stride) {
f((uint32_t*)&data[i]); }
return 0; }
I need to send that data 8bytes at a time into a function that accepts
uint32_t[2] as an input. How do I convert my 234byte char array into
uint32_t without losing the char values?
you could use a union for this
typedef union
{
unsigned char arr[128]; // use unsigned char
uint32_t uints[16]; // 128/8
} myvaluetype;
myvaluetype value;
memcpy(value.arr, your_array, sizeof(value.arr));
say the prototype that you want to feed 2 uint32_t at a time is something like
foo(uint32_t* p);
you can now send the data 8 bytes at the time by
for (int i = 0; i < 16; i += 2)
{
foo(myvaluetype.uints + i);
}
then use the same struct to convert back.
of course some care must be taken about padding/alignment you also don't mention if it is sent over a network etc so there are other factors to consider.

Resources