Copy value of short array to long array - c

The following is an example showing what I want:
int buf[3] = {10, 20, 30};
int * send_buf = (int *)malloc(5 * sizeof(int));
*send_buf = 1;
*(send_buf + 4) = 1;
After copy buf to send_buf, the values in send_buf should be :
1 10 20 30 1
Could anyone let me know what's the most efficient way to do this without using memcpy() or memmove()?

Try the following changes-
int buf[3] = {10, 20, 30};
int * send_buf = (int *)malloc(5 * sizeof(int));
*send_buf = 1;
for(i=1;i<=3;i++) // this will work for you.
*(send_buf+i)=buf[i-1];
*(send_buf + 4) = 1;

A simple implementation of memcpy() is:
memcpy(uint8_t *dest, uint8_t *src, size_t num_bytes) {
for (size_t i=0; i<num_bytes; ++i)
dest[i] = src[i];
}
So, since we can't use memcpy() for no good reason, let's just inline the body:
int buf[3] = {10, 20, 30};
int *send_buf = malloc(5 * sizeof(int));
send_buf[0] = 1;
send_buf[4] = 1;
for (int i=0; i<3; ++i)
send_buf[i + 1] = buf[i];

Well, one can always do it with sprintf and sscanf
char buffer[1024];
sprintf(buffer, "%d %d %d", buf[0], buf[1], buf[2]);
sscanf(buffer, "%d%d%d", send_buf[1], send_buf[2], send_buf[3]);

Related

I have a problem when i'm printing char** array

I'm working with grap.
My graph is a structure like this
typedef struct{
int order; // number of node
int **mat; // matrix graphe
}graphe;
I'm working on school project and I need to build a set of binary's number from 0 to N (where is the order of the graph)
Actually I did this, it's working. When I'm printing the final variable, it displays all declinaison of binary number (000, 001, 010, 011, etc...)
char** construireSousEnsemble(graphe g){
int size = pow(2, g.order);
char** D = (char**)malloc(sizeof(char*)*g.order-1);
for (int i = 0; i < size; i++){
D[i] = (char*)malloc(g.order-1);
char buffer[g.order-1];
char tmp[g.order-1];
char final[g.order-1];
for (int j = g.order-1; j >= 0; j--){
int bin = (i >> j)&1;
sprintf(buffer, "%d", bin);
snprintf(tmp, sizeof(tmp), "%s", buffer);
strcat(final, tmp);
if (j == 0){
strcpy(D[i], final);
//printf("%s\n", D[i]);
//printf("%d | %s\n", i, D[i]);
memset(final, 0, sizeof(final)); // reset the zone
}
}
//printf("\n");
}
return D;
}
But in the main function, when I'm calling the function like this:
char** zones = construireSousEnsemble(g);
But when I'm printing the content with zones, I have this:
So I'm a bit lost.
This example is for a 3 nodes graph. If I have a 4 nodes, the weird symbol increase and I won't have 0001 or 0010 etc.., same with 5 or 6 nodes.
So my question is, why is this happening?
By the way, I'm not confortable with C so maybe I made some mistakes.
Thank you all :)
Here is the solution (posting if for the future)
char ** construireSousEnsemble(graphe g){
int size = pow(2, g.order);
char **D = (char **) malloc (sizeof (char *) * size);
char buffer[g.order];
char final[g.order];
for (int i = 0; i < size; i++) {
D[i] = (char *)malloc(g.order + 1);
final[0] = 0;
for (int j = g.order - 1; j >= 0; j--) {
int bin = (i >> j) & 1;
sprintf (buffer, "%d", bin);
strcat (final, buffer);
}
strcpy (D[i], final);
}
return D;
}

How to convert int array to char array

So I'm trying to convert an integer array to a char array in a specific style. What I want to end up with is:
charArray[] = "084 438 038 002 093 249 168"
This is what I started with before realizing that each int will be more than 1 char.
#include <stdio.h>
#include <stdlib.h>
void intToChar(int n, int numArray[], char charArray[]);
int main() {
int i;
int n = 7;
int numArray[] = {84, 438, 38, 2, 93, 249, 168};
char *charArray = (char*)malloc(sizeof(char) * (4 * n - 1);
intToChar(n, numArray, charArray);
for (i = 0; i < n; i++) {
printf("%c ", charArray[i]);
}
printf("\n");
return 0;
}
void intToChar(int n, int numArray[], char charArray[]) {
int i;
for (i = 0; i < n; i++) {
charArray[i] = numArray[i] + '0';
}
}
Is there a way to turn an int like 123 into "123" exactly?
char *intToChar(size_t n, const int *numArray, size_t m, char *charArray)
{
int pos = 0;
while(n--)
pos += snprintf(charArray + pos, m - pos, "%03d%s", *numArray++, n ? " " : "");
return charArray;
}
int main() {
int i;
int n = 7;
int numArray[] = {84, 438, 38, 2, 93, 249, 168};
char *charArray = (char*)malloc(4 * n - 1);
printf("`%s`\n", intToChar(n, numArray, n * 4, charArray));
free(charArray);
return 0;
}
Here you have a bit more complicated version which will calculate how much space it needs and alloctes the memory accordingly.
char *intToChar(size_t n, const int *numArray)
{
int pos = 0;
char *charArray;
//dry run
for(size_t m = 0; m < n; m++)
pos += snprintf(NULL, 0, "%03d%s", numArray[m], m == n -1 ? " " : "");
charArray = malloc(pos + 1);
pos = 0;
if(charArray)
while(n--)
pos += sprintf(charArray + pos, "%03d%s", *numArray++, n ? " " : "");
return charArray;
}
int main() {
int i;
int numArray[] = {84, 438, 38, 245654, 93, 249, 168};
size_t n = sizeof(numArray) / sizeof(numArray[0]);
char *charArray;
//you should check if the function returned valid pointer before using it
printf("`%s`\n", (charArray = intToChar(n, numArray)));
free(charArray);
return 0;
}
sprintf and strcat could be useful.
Something like:
int main() {
int n = 7;
int numArray[] = {84, 438, 38, 2, 93, 249, 168};
char charArray[256];
char tmp[32];
sprintf(charArray, "%03d", numArray[0]); // Put first number in the
// result string
for (int i = 1; i < n; i++) {
sprintf(tmp, " %03d", numArray[i]); // Create a string with current number
// Note: the 03 after % which
// puts zero in front of numbers
// having less than 3 digits
strcat(charArray, tmp); // Append the temporare string
// to the result
}
printf("%s\n", charArray); // Print the result
return 0;
}
Output:
084 438 038 002 093 249 168

Problem with 2D dynamic allocation of arrays and passing it as parameter

I have the following problem:
I am populating a 2D array whose number of rows is the number of files I am reading. Therefore the number of columns in each row corresponds to the bytes of data read from the file.
With this picture in mind I have the following program:
I have to return a byte array of data read from each file and the size of each file. This is what I have:
void fillArrays(unsigned char **array, size_t dataSize[], int *nFiles)
{
printf("Calling fillArrays\n");
int i, j, nrows;
nrows = 3;
*nFiles = nrows; // assuming no. of files to be read = 3
dataSize = (size_t *)malloc(nrows * sizeof(size_t));
array = (unsigned char**)malloc(nrows * sizeof(unsigned char *));
dataSize[0] = 4; // assuming file 1 contains 4 bytes
dataSize[1] = 3; // assuming file 2 contains 3 bytes
dataSize[2] = 1;// assuming file 3 contains 1 bytes
//populating file data into a 2D array. Here for test purpose assuming each file has data = 0x03!!
for(i = 0; i < nrows; i++)
{
array[i] = (unsigned char *) malloc(dataSize[i] * sizeof(unsigned char));
for(j = 0; j < dataSize[i]; j++){
printf("round %d %d\n", i,j);
array[i][j] = 0x03;
printf("array [%d][%d] = %02X\n ", i, j , array[i][j]);
}
//array[i][dataSize[i]]= '\0';
}
}
int main(int argc, char *argv[])
{
unsigned char **fileArray;
int noFiles = 0;
size_t *fileSize;
fillArrays(fileArray,fileSize, &noFiles);
printf("Returned no. of files = %d\n", noFiles);
printf("fileSize[0] = %lu\n", fileSize[0]);
printf("fileSize[1] = %lu\n", fileSize[1]);
printf("fileSize[2] = %lu\n", fileSize[2]);
int j = 0;
for (int i = 0; i < noFiles; i++){
printf("i = %d\n", i);
for (int j = 0; j < fileSize[i]; j++){
printf("Obtained data from file %d : (fileArray [%d][%d]) = %02X\n ", i, i, j , fileArray[i][j]);
//j++;
}
}
return 0;
}
the code is segfaulting in the 'j' loop in the main function. Could someone throw some light?
How can this be done better?
Thanks.
You are passing fileArray by value, so in fillArrays you are modyfing copy of this pointer to pointer, so after executing fillArrays function, fileArray in main function is not affected - it is still uninitialized, you need to pass this variable by reference (pass pointer to fileArray):
fillArrays(&fileArray,fileSize, &noFiles);
then in fillArrays you need to add these modifications:
void fillArrays(unsigned char ***array, size_t dataSize[], int *nFiles)
{
//...
*array = (unsigned char**)malloc(nrows * sizeof(unsigned char *));
//...
(*array)[i] = (unsigned char *) malloc(dataSize[i] * sizeof(unsigned char));
///...
(*array)[i][j] = 0x03;
}
your array and dataSize are local to fillArrays function and
allocating memory to them inside fillArrays will not affect the arrays inside main.
// Allocates the memory to local variables
dataSize = (size_t *)malloc(nrows * sizeof(size_t));
array = (unsigned char**)malloc(nrows * sizeof(unsigned char *));
Hence you need to use pointer to pointer to char* for fileArray and
pointer to size_t* for fileSize.
Your prototype will become as below.
void fillArrays(unsigned char ***array, size_t **dataSize, int *nFiles)
And you call the function as below.
fillArrays(&fileArray,&fileSize, &noFiles);
Sample code:
void fillArrays(unsigned char ***array, size_t **dataSize, int *nFiles)
{
printf("Calling fillArrays\n");
int i, j, nrows;
nrows = 3;
*nFiles = nrows; // assuming no. of files to be read = 3
*dataSize = (size_t *)malloc(nrows * sizeof(size_t));
*array = (unsigned char**)malloc(nrows * sizeof(unsigned char *));
(*dataSize)[0] = 4; // assuming file 1 contains 4 bytes
(*dataSize)[1] = 3; // assuming file 2 contains 3 bytes
(*dataSize)[2] = 1;// assuming file 3 contains 1 bytes
//populating file data into a 2D array. Here for test purpose assuming each file has data = 0x03!!
for(i = 0; i < nrows; i++)
{
(*array)[i] = (unsigned char *) malloc((*dataSize)[i] * sizeof(unsigned char));
for(j = 0; j < (*dataSize)[i]; j++){
printf("round %d %d\n", i,j);
(*array)[i][j] = 0x03;
printf("array [%d][%d] = %02X\n ", i, j , (*array)[i][j]);
}
//array[i][dataSize[i]]= '\0';
}
}
int main(int argc, char *argv[])
{
unsigned char **fileArray;
int noFiles = 0;
size_t *fileSize;
fillArrays(&fileArray,&fileSize, &noFiles);
printf("Returned no. of files = %d\n", noFiles);
printf("fileSize[0] = %lu\n", fileSize[0]);
printf("fileSize[1] = %lu\n", fileSize[1]);
printf("fileSize[2] = %lu\n", fileSize[2]);
int j = 0;
for (int i = 0; i < noFiles; i++){
printf("i = %d\n", i);
for (int j = 0; j < fileSize[i]; j++){
printf("Obtained data from file %d : (fileArray [%d][%d]) = %02X\n ", i, i, j , fileArray[i][j]);
//j++;
}
}
return 0;
}
Alternate approach:
I suggest you to not have pointer to pointer to char* as parameter instead you just return the filled array from fillArrays as below.
char** fillArrays(size_t **dataSize, int *nFiles)
{
printf("Calling fillArrays\n");
int i, j, nrows;
char **array = NULL;
nrows = 3;
*nFiles = nrows; // assuming no. of files to be read = 3
*dataSize = (size_t *)malloc(nrows * sizeof(size_t));
array = (unsigned char**)malloc(nrows * sizeof(unsigned char *));
(*dataSize)[0] = 4; // assuming file 1 contains 4 bytes
(*dataSize)[1] = 3; // assuming file 2 contains 3 bytes
(*dataSize)[2] = 1;// assuming file 3 contains 1 bytes
//populating file data into a 2D array. Here for test purpose assuming each file has data = 0x03!!
for(i = 0; i < nrows; i++)
{
array[i] = (unsigned char *) malloc((*dataSize)[i] * sizeof(unsigned char));
for(j = 0; j < (*dataSize)[i]; j++){
printf("round %d %d\n", i,j);
array[i][j] = 0x03;
printf("array [%d][%d] = %02X\n ", i, j , array[i][j]);
}
//array[i][dataSize[i]]= '\0';
}
return array;
}
and you call the function as below.
fileArray = fillArrays(&fileSize, &noFiles);

c; converting 2 bytes to short and vice versa

I want to convert array of bytes bytes1 (little endian), 2 by 2, into an array of short integers, and vice versa . I expect to get final array bytes2, equal to initial array bytes1. I have code like this:
int i = 0;
int j = 0;
char *bytes1;
char *bytes2;
short *short_ints;
bytes1 = (char *) malloc( 2048 );
bytes2 = (char *) malloc( 2048 );
short_ints = (short *) malloc( 2048 );
for ( i=0; i<2048; i+=2)
{
short_ints[j] = bytes1[i+1] << 8 | bytes1[i] ;
j++;
}
j = 0;
for ( i=0; i<2048; i+=2)
{
bytes2[i+1] = (short_ints[j] >> 8) & 0xff;
bytes2[i] = (short_ints[j]) ;
j++;
}
j = 0;
Now, can someone tell me why I haven't got bytes2 array, completely the same as bytes1 ? And how to do this properly?
Suggest 2 functions. Do all combining and extraction as unsigned to remove issues with the sign bit in short and maybe char.
The sign bit is OP's code biggest problem. short_ints[j] = bytes1[i+1] << 8 | bytes1[i] ; likely does a sign extend with bytes1[i] conversion to int.
Also (short_ints[j] >> 8) does a sign extend.
// Combine every 2 char (little endian) into 1 short
void charpair_short(short *dest, const char *src, size_t n) {
const unsigned char *usrc = (const unsigned char *) src;
unsigned short *udest = (unsigned short *) dest;
if (n % 2) Handle_OddError();
n /= 2;
while (n-- > 0) {
*udest = *usrc++;
*udest += *usrc++ * 256u;
udest++;
}
}
// Break every short into 2 char (little endian)
void short_charpair(char *dest, const short *src, size_t n) {
const unsigned short *usrc = (const unsigned short *) src;
unsigned char *udest = (unsigned char *) dest;
if (n % 2) Handle_OddError();
n /= 2;
while (n-- > 0) {
*udest++ = (unsigned char) (*usrc);
*udest++ = (unsigned char) (*usrc / 256u);
usrc++;
}
}
int main(void) {
size_t n = 2048; // size_t rather than int has advantages for array index
// Suggest code style: type *var = malloc(sizeof(*var) * N);
// No casting of return
// Use sizeof() with target pointer name rather than target type.
char *bytes1 = malloc(sizeof * bytes1 * n);
Initialize(bytes, n); //TBD code for OP-best to not work w/uninitialized data
// short_ints = (short *) malloc( 2048 );
// This is weak as `sizeof(short)!=2` is possible
short *short_ints = malloc(sizeof * short_ints * n/2);
charpair_short(short_ints, bytes1, n);
char *bytes2 = malloc(sizeof * bytes2 * n);
short_charpair(bytes2, short_ints, n);
compare(bytes1, bytes2, n); // TBD code for OP
// epilogue
free(bytes1);
free(short_ints);
free(bytes2);
return 0;
}
Avoided the union approach as that is platform endian dependent.
Here's a program that demonstrates that you are experiencing the problem associated with bit-shifting signed integral values.
#include <stdio.h>
#include <stdlib.h>
void testCore(char bytes1[],
char bytes2[],
short short_ints[],
int size)
{
int i = 0;
int j = 0;
for ( i=0; i<size; i+=2)
{
short_ints[j] = bytes1[i+1] << 8 | bytes1[i] ;
j++;
}
j = 0;
for ( i=0; i<size; i+=2)
{
bytes2[i+1] = (short_ints[j] >> 8) & 0xff;
bytes2[i] = (short_ints[j]) ;
j++;
}
for ( i=0; i<size; ++i)
{
if ( bytes1[i] != bytes2[i] )
{
printf("%d-th element is not equal\n", i);
}
}
}
void test1()
{
char bytes1[4] = {-10, 0, 0, 0};
char bytes2[4];
short short_ints[2];
testCore(bytes1, bytes2, short_ints, 4);
}
void test2()
{
char bytes1[4] = {10, 0, 0, 0};
char bytes2[4];
short short_ints[2];
testCore(bytes1, bytes2, short_ints, 4);
}
int main()
{
printf("Calling test1 ...\n");
test1();
printf("Done\n");
printf("Calling test2 ...\n");
test2();
printf("Done\n");
return 0;
}
Output of the program:
Calling test1 ...
1-th element is not equal
Done
Calling test2 ...
Done
Udate
Here's a version of testCore that works for me:
void testCore(char bytes1[],
char bytes2[],
short short_ints[],
int size)
{
int i = 0;
int j = 0;
unsigned char c1;
unsigned char c2;
unsigned short s;
for ( i=0; i<size; i+=2)
{
c1 = bytes1[i];
c2 = bytes1[i+1];
short_ints[j] = (c2 << 8) | c1;
j++;
}
j = 0;
for ( i=0; i<size; i+=2)
{
s = short_ints[j];
s = s >> 8;
bytes2[i+1] = s;
bytes2[i] = short_ints[j] & 0xff;
j++;
}
for ( i=0; i<size; ++i)
{
if ( bytes1[i] != bytes2[i] )
{
printf("%d-th element is not equal\n", i);
}
}
}
It is tested with:
char bytes1[4] = {-10, 0, 25, -4};
and
char bytes1[4] = {10, -2, 25, 4};
Well, what you need is a UNION:
#include <stdio.h>
#include <string.h>
union MyShort {
short short_value;
struct {
char byte1;
char byte2;
};
};
int main(int argc, const char * argv[])
{
char a[4]="abcd";
char b[4]="1234";
short c[5]; c[4]=0;
union MyShort d;
for (int i = 0; i<4; i++) {
d.byte1 = a[i];
d.byte2 = b[i];
c[i] = d.short_value;
}//next i
printf("%s\n", (char*)c);
return 0;
}
the result should be a1b2c3d4.

Append a character to a list n times

I want to create random data for testing. I want to fill an array with 100 strings of random length with the letter 'A'.
example:
array[0] = "AAAAA"
array[1] = "AAAAAAAA"
array[2] = "A"
...
char **create_string()
{
char **array = malloc(sizeof(**array));
srand((unsigned int)time(NULL));
int random = 0;
int i, j;
for(int i=0; i<100; i++)
{
random = rand() % 100;
for(j=0; j < random; j++)
{
array[i] = // some sort of string append that would be cheap.
}
}
}
I was looking at this C string append and they use strcat. Is there a better way to solve my problem? Since I will be running in a loop to create those random size strings.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
char **create_string(size_t n) {
char **array = malloc(sizeof(char*) * n);
int i, j;
for(i=0; i<100; i++)
{
size_t sz = rand() % 100;
array[i] = malloc(sz + 1);
for(j=0; j < sz; j++) {
array[i][j] = 'A';
}
array[i][sz] = 0;
}
return array;
}
int main() {
char **array;
size_t i;
srand((unsigned int)time(NULL));
array = create_string(100);
for (i = 0; i < 100; i++)
printf("%s\n", array[i]);
return 0;
}
Alternatively, you can create a template string and copy required number of characters into each random string:
char **create_string(size_t n) {
char template[101];
char **array = malloc(sizeof(char*) * n);
int i;
for (i = 0; i < 100; i++)
template[i] = 'A';
template[100] = 0;
for(i = 0; i < n; i++) {
size_t sz = rand() % 100;
array[i] = malloc(sz + 1);
strncpy(array[i], template, sz);
array[i][sz] = 0;
}
return array;
}
This will depend on the distribution of string lengths that you want. This is a uniform distribution of string lengths, from 0 to 200.
int n = rand() % 200 * sizeof(*array);
array[i] = malloc(n + 1);
memset(array[i], 'A', n);
array[i][n] = '\0';
But you could have a Gaussian distribution, a Poisson distribution, etc.
char **create_string()
{
char **array = malloc(sizeof(char *) * 100);
srand((unisgned int)time(NULL));
int i;
for (i = 0; i <100;i++)
{
int random = rand() % 100;
array[i] = malloc(random);
memset(array[i],'A',random-1);
array[random-1] = '\0';
}
return array;
}
Problem for you to fix: what happens if random is 0? Also the random numbers will not be equaly distributed. Only modulo by a power of 2 will achieve that.
Here's an approach that doesn't put an upper bound on any individual string, but does put an exact bound on the total length of all strings. It also only calls malloc twice.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TOT_SIZE (5000) /* adjust to taste */
#define TOT_STRS (100)
char **create_strings()
{
char **array = (char**) malloc(TOT_STRS * sizeof(char *));
char *str = (char*) malloc(TOT_SIZE);
int zeros = 1;
int i;
memset(str, 'A', TOT_SIZE - 1);
str[TOT_SIZE - 1] = 0;
while (zeros < TOT_STRS)
{
int pos = rand() % TOT_SIZE;
if (str[pos] != 0)
{
str[pos] = 0;
zeros++;
}
}
array[0] = str;
for (i = 1; i < TOT_STRS; i++)
{
array[i] = array[i - 1] + strlen(array[i - 1]) + 1;
}
return array;
}
And a short test program:
int main()
{
char **a = create_strings();
int i;
for (i = 0; i < TOT_STRS; i++)
{
printf("%3d: %s\n", i, a[i]);
}
return 0;
}
This code assumes that all the random strings need to be non-overlapping. If they can overlap in memory, you only need one string, and an array of pointer to different starting points in that one string.
You do not have to allocate the real 100 strings. Firstly you just declare a long enough array char long_array[100]. and then you use random = rand() % 100; get the random. Secondly you just pass the long_array and the random to your function. Then your problem is solved.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
char **create_string(const size_t array_size,
const size_t string_size,
const unsigned char chr)
{
srand((unsigned)time(NULL));
char ** array = malloc(array_size * sizeof (char *));
size_t t;
for (t = 0; t < array_size; ++t) {
array[t] = malloc(string_size * sizeof(char));
array[t][string_size] = '\0';
memset(array[t], chr, (rand() % string_size) + 1);
}
return array;
}
main() {
char ** randstring = create_string(10, 7, 'A');
int t = 0;
for (; t < 10; ++t)
printf("%s\n", randstring[t]);
return 0;
}
Possible output
AAAAAA
AAAAA
AAAAAA
AAA
AAAAA
AAAAAA
AAAAAA
AAAAAAA
AAAA
AAAA

Resources