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
Related
I am trying to write a generic C function, that returns minimum of an array using function pointers.
The code is :
#include <stdio.h>
int min_index(void *arr, int size, int (*compare)(void *, void *))
{
int i;
int min = 0;
for (i = 1; i < size; i++)
{
if (((*compare)(&arr[i], &arr[min])) < 0)
min = i;
}
return min;
}
int comp_int(int *arr1, int *arr2)
{
if (*arr1 < *arr2)
return -1;
else
return 1;
}
int comp_char(char *arr1, char *arr2)
{
if (*arr1 < *arr2)
return -1;
else
return 1;
}
int main()
{
int arr1[5] = {45, 56, 34, 23, 19};
int index = min_index(arr1, 5, comp_int); // calling min_index with integer array
printf("Minimum value in the array is %d\n", arr1[index]);
char arr2[5] = {'a', 'b', 'c', 'd', 'e'};
int index2 = min_index(arr2, 5, comp_char); // calling min_index with char array
printf("Minimum value in the array is %c\n", arr2[index2]);
return 0;
}
This code worked for only char arrays. It did not work for int arrays.
I debugged the code. I found that, when I call min_index function with the integer array, only first value of arr is correct number, but remaining are some garbage values.
But, when I call min_index function with character array, all the values are correct. There are no garbage values in this case. I got correct output.
Question : Why does the code work for char arrays not for int arrays ?
It doesn't work because you need to cast the array itself on the original type and then access by index. Because C does not have template or a type check you will need to access the min_of() like functions by the size and the sign to get the correct conversion and sorting.
#include <stdio.h>
#define INVALID_VAL_TYPE (int)(~0)
int new_umin_index(void * arr, int arr_len, int vsize){
int i, index = 0;
switch (vsize) {
case sizeof(unsigned char):
for (i = 0; i < arr_len; i++) {
if ( ((unsigned char *)arr)[i] < ((unsigned char *)arr)[index] ){
index = i;
}
}
break;
case sizeof(unsigned):
for (i = 0; i < arr_len; i++) {
if ( ((unsigned *)arr)[i] < ((unsigned *)arr)[index] ){
index = i;
}
}
break;
default:
index = INVALID_VAL_TYPE;
break;
}
return index;
}
int new_imin_index(void * arr, int arr_len, int vsize){
int i, index = 0;
switch (vsize) {
case sizeof(signed char):
for (i = 0; i < arr_len; i++) {
if ( ((signed char *)arr)[i] < ((signed char *)arr)[index] ){
index = i;
}
}
break;
case sizeof(int):
for (i = 0; i < arr_len; i++) {
if ( ((int *)arr)[i] < ((int *)arr)[index] ){
index = i;
}
}
break;
default:
index = INVALID_VAL_TYPE;
break;
}
return index;
}
int main(void) {
int arr1[5] = {45, 56, 34, 23, 19};
int i_min_index = new_imin_index(&arr1, 5, sizeof(int));
printf("Minimum value in array<int> is %i \n", arr1[i_min_index]);
char arr2[5] = {'b', 'a', 'c', 'd', 'e'};
int c_min_index = new_umin_index(&arr2, 5, sizeof(char));
printf("Minimum value in array<char> is %c \n", arr2[c_min_index]);
return 0;
}
I came up with a solution, based on the comments of several users. This time I enabled all the warnings, and took care of every warning. The code is :
#include <stdio.h>
void* minimum(void *arr, int arr_count, size_t size, int (*compare)(const void *, const void *))
{
void* pmin = arr;
for(int i=1; i<arr_count; i++)
{
void* value = (char*)arr + i*size; // size is the sizeof the type.
if(((*compare)(value, pmin))<0)
pmin = value;
}
return pmin;
}
int compare_ints(const void* a, const void* b)
{
int arg1 = *(const int*)a;
int arg2 = *(const int*)b;
if (arg1 < arg2) return -1;
if (arg1 > arg2) return 1;
return 0;
}
int compare_chars(const void* a, const void* b)
{
char arg1 = *(const char*)a;
char arg2 = *(const char*)b;
if (arg1 < arg2) return -1;
if (arg1 > arg2) return 1;
return 0;
}
int main()
{
int arr1[5] = {45, 56, 34, 23, 19};
int *pmin = minimum(arr1, 5,4, compare_ints); // In my system sizeof(int) is 4
printf("Minimum value in the array is %d\n", *pmin);
char arr2[5] = {'a', 'b', 'c', 'd', 'e'};
char* pmin2 = minimum(arr2, 5,1, compare_chars); // sizeof(char) is 1
printf("Minimum value in the array is %c\n",*pmin2 );
return 0;
}
The output is (without any warnings) :
Minimum value in the array is 19
Minimum value in the array is a
I have an array of numbers that has been sorted in before, so there's no need to sort it, I need to insert an given value, named it val, at a valid position in my array.
My program works for a given value that is smaller than the last one, but for the case where the value is bigger than the last one, my program just doesn't want to insert the value.
For example, for the array {1, 2, 3, 4, 6} and the value 5, the array should be {1, 2, 3, 4, 5, 6}, but for the value 7 my array is looking like {1, 2, 7, 4, 6, 0}.
#include <stdio.h>
void insert(int val, int *n, int v[])
{
int index;
index = n - 1;
if (n == 0)
{
v[0] = val; // check if array is empty
n = n + 1; // v[0] becomes the given value
} // increase size of array
if (val > v[index])
{
v[index+1] = val; // given value is bigger than the last value in array
n = n + 1; // increase size
}
else
{
while (index >= 0 && v[index] > val)
{
v[index+1] = v[index]; //shift items to the right
index--;
}
v[index + 1] = val; //after moving elements to the right
n = n + 1; // i set the value to the valid position
}
}
void display(int n, int v[])
{
int i;
for (i = 0;i < n; i++)
printf("%d ", v[i]);
}
int main(void)
{
int v[10] = { 12, 23, 34, 41, 69, 71, 81, 91, 100 };
int n;
n = 9; // size of array
insert(101,n,v); // 101 is given value to insert
display(n,v);
return 0;
}
You have a couple of mistakes:
You are passing int instead of int * so you're not able to update array size
You are not correctly placing value in the array
This is how your code should look like:
#include <stdio.h>
void insert(int val, int *nPtr, int v[]);
void display(int n, int v[]);
int main(void) {
int v[10] = {12, 23, 34, 41, 69, 71, 81, 91, 100};
int n;
n = 9;
insert(101, &n, v);
display(n, v);
return 0;
}
void insert(int val, int *nPtr, int v[]) {
int n = *nPtr;
int i, j;
int k = 0;
for (i = 0; i < n + 1; i++)
if (!k) {
if (v[i] > val || i == n) {
for (j = n - 1; j >= i; j--) {
v[j + 1] = v[j];
}
v[i] = val;
n++;
k = 1;
}
}
*nPtr = n;
}
void display(int n, int v[]) {
int i;
for (i = 0; i < n; i++)
printf("%d ", v[i]);
printf("\n");
}
You can also try to insert number on the beginning, for example 0 and it will still work.
Here is the task i'm working on:
I am given a txt file containing the list of student names, id numbers, schools, majors, and test scores.
Read this contents and copy to the structure in C.
Sort this list using insertion sort.
Print sorted list on the screen.
I checked my coding by muting some parts, there is an error with my insertion sorting function.
I have no idea which part is incorrect. It all makes sense to me. I need help :( here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 1000
#define BUF_SIZE 80
typedef struct {
char name[20];
char studentID[10];
char department[20];
char major[20];
int mid;
int final;
} student;
FILE *fp;
void operation(student t, student list[], int j);
void insertion_sort(student list[], int n);
void printing(student list[], int n);
int main(int argc, char *argv[])
{
char filename[20] = "studentlist.txt";
int n = 1; /* (number of students) + 1 */
student list[MAX];
char buffer[BUF_SIZE];
int i;
fp = fopen(filename, "r");
while (1) {
if (fgets(buffer, BUF_SIZE, fp) == NULL)
break;
strncpy(list[n].name, buffer, strlen(buffer) - 1);
fgets(buffer, BUF_SIZE, fp);
strncpy(list[n].studentID, buffer, strlen(buffer) - 1);
fgets(buffer, BUF_SIZE, fp);
strncpy(list[n].department, buffer, strlen(buffer) - 1);
fgets(buffer, BUF_SIZE, fp);
strncpy(list[n].major, buffer, strlen(buffer) - 1);
fgets(buffer, BUF_SIZE, fp);
list[n].mid = atoi(buffer);
fgets(buffer, BUF_SIZE, fp);
list[n].final = atoi(buffer);
n++;
}
fclose(fp);
insertion_sort(list, n);
printing(list, n);
return 0;
}
void insertion_sort(student list[], int n)
{
int i;
student temp;
for (i = 2; i < n; i++) {
temp = list[i];
operation(temp, list, i - 1);
}
}
void operation(student t, student list[], int j)
{
list[0] = t;
while (t.studentID < list[j].studentID) {
list[j + 1] = list[j];
j--;
}
list[j + 1] = t;
}
void printing(student list[], int n)
{
int i;
for (i = 1; i < n; i++) {
printf(" %s ", list[i].name);
printf(" %s ", list[i].studentID);
printf(" %s ", list[i].department);
printf(" %s ", list[i].major);
printf(" %6d ", list[i].mid);
printf(" %6d ", list[i].final);
putchar('\n');
}
}
Continuing from the comments and the first answer, you are making tracking index error between the split insertion_sort and operation functions. There is no need for two functions when one will work (and arguably be smaller). There is little benefit to be obtained from the split (except for increased confusion).
Putting a simple insertion sort together in one function that will fit your needs (and using pointers to sort as opposed to repeatedly using the function copy-constructor to accomplish the swaps), you could do something similar to the following:
typedef struct {
int id, g;
} student;
void insertion_sort (student **list, int nmemb)
{
for (int i = 0; i < nmemb; i++)
for (int j = i; j > 0 && list[j]->id < list[j-1]->id; j--)
{
student *tmp = list[j];
list[j] = list[j-1];
list[j-1] = tmp;
}
}
Putting together a short (and limited struct member example), you can do something like the following to sort the student data by ID (or id below)
#include <stdio.h>
typedef struct {
int id, g;
} student;
void insertion_sort (student **list, int nmemb)
{
for (int i = 0; i < nmemb; i++)
for (int j = i; j > 0 && list[j]->id < list[j-1]->id; j--)
{
student *tmp = list[j];
list[j] = list[j-1];
list[j-1] = tmp;
}
}
void printing(student *list[], int n)
{
int i;
for (i = 0; i < n; i++) {
printf(" %d ", list[i]->id);
printf(" %d \n", list[i]->g);
}
}
int main (void) {
student s[] = { {.id = 5, .g = 72}, /* minimal student test data */
{.id = 2, .g = 91},
{.id = 4, .g = 77},
{.id = 1, .g = 96},
{.id = 3, .g = 85}};
int n = sizeof s / sizeof *s;
student *l[n];
for (int i = 0; i < n; i++) /* initialize pointers in l */
l[i] = &s[i];
insertion_sort (l, n); /* sort pointers in l */
printing (l, n); /* output sorted pointers */
return 0;
}
Example Use/Output
Sorted by student.id
$ ./bin/inssort_so
1 96
2 91
3 85
4 77
5 72
If you did want to avoid using the additional level of indirection involved in passing an array of pointers (actually a pointer-to-pointer-to-type), you can make your original approach work as follows:
void insertion_sort (student *list, int nmemb)
{
for (int i = 0; i < nmemb; i++)
for (int j = i; j > 0 && list[j].id < list[j-1].id; j--)
{
student tmp = list[j];
list[j] = list[j-1];
list[j-1] = tmp;
}
}
void printing (student *list, int n)
{
for (int i = 0; i < n; i++)
printf (" %d %d \n", list[i].id, list[i].g);
}
int main (void) {
student s[] = { {.id = 5, .g = 72},
{.id = 2, .g = 91},
{.id = 4, .g = 77},
{.id = 1, .g = 96},
{.id = 3, .g = 85}};
int n = sizeof s / sizeof *s;
insertion_sort (s, n);
printing (s, n);
return 0;
}
As you go forward, also consider passing a compare callback function to your sort routines. That allows you to sort many different types of data using your same sort routine -- just by changing the compare function (as is done for the C-library qsort routine.
I'm developing a program that read from CSV file and calculate score with a method "calculateMLpa". The method receive array of char and array of 10 float, and transform array of float in matrix 3x3. When read the position 3rd number from array, insert in matrix the 4th number and same for 6th number.
I.E.
array value[]={0.000000;123.814934;234.000000;100.000000;166.000000; 203.086639;383.000000;186.000000;338.000000;173.098419 }
array traj[]={"0-0";"0-1";"0-2";"1-0";"1-1";"1-2";"2-0";"2-1";"2-2"}
Xn_val[]={"0","1","2"}
When transform in matrix the result is:
123.814934 234.000000 166.000000
166.000000 203.086639 186.000000
186.000000 338.000000 173.098419
While the expected for [0;2] is 100.000000 and for [1;2]=383.000000, but when print the currently value of traj it's correct.
How can I fix this problem?
The code is all here:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <math.h>
#include <stdbool.h>
#include <ctype.h>
#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))
int csv_parse ( char *line, int size )
{
char *p;
char *dp;
int inquote;
int na;
int nTo_comma;
char prevc = ',';
char *list[256];
dp = NULL;
// inquote = 0;
na = 0;
prevc = ';';
nTo_comma=0;
for ( p = line; *p != '\n'; p++ )
{
nTo_comma++;
list[nTo_comma] = p;
if(*p == prevc)
{
printf("%s\t", list);
return na;
}
}
printf("\n");
return na;
}
double calculateMLpa(const char *Xn_val[], char *traj[], float value[], double alphaxixj, double tauxi, int sz, int dim) {
double mlx = 0;
double v;
double alphaxi;
char *state;
int i;
int p;
int j;
int k;
// int sz = sizeof(Xn_val) / sizeof(int);
// int dim = sizeof(traj) / sizeof(char);
double trns[sz][sz];
double m[sz];
char *trat="-";
// m[xi] values: the number of transitions leaving the state xi
printf("%d %d \n",sz,dim);
int cont=0;
for (i = 0; i <= sz; i++) {
m[i] = 0.0;
for (j = 0; j <= sz; j++) {
v = 0.0;
int newlength = strlen(Xn_val[i])+strlen(trat)+strlen(Xn_val[j])+1;
state = malloc(sizeof(char)*newlength);
if(state != NULL){
state[0] = '\0';
strcat(state,Xn_val[i]);
strcat(state,trat);
strcat(state,Xn_val[j]);
printf("%s ",state);
}else {
printf(stderr,"malloc failed!\n");
}
// for (k=0; k<=dim;++k){
if (traj[cont] != NULL ){
if (strcmp(traj[cont],state)==0){
v = value[cont+1];
printf("%f \n",v);
}
}
trns[i][j] = v;
printf("%f - \n",trns[i][j]);
if (strcmp(Xn_val[i],Xn_val[j])!=0)
m[i] = m[i] + v;
cont++;
}
}
for (i=0;i<=sz;++i){
for(j=0;j<=sz;++j){
printf("%f ",trns[i][j]);
}
printf("\n");
}
for (p=0;p<=sz;++p){
printf("%f - \n",m[p]);
}
printf("%f %f\n",trns[0][1],trns[0][2]);
alphaxi = alphaxixj * (((double) sz) - 1.0);
alphaxi = alphaxixj;
printf("%d ",sz);
for (i = 0; i <= sz; i++) {
for (j = 0; j <= sz; j++) {
// xi!=xj
if (strcmp(Xn_val[i], Xn_val[j])!=0) {
mlx = mlx + lgamma(alphaxixj + trns[i][j]) - lgamma(alphaxixj);
}
// xi
else {
mlx = mlx + lgamma(alphaxi) - lgamma(alphaxi + m[i]);
mlx = mlx + lgamma(alphaxi + m[i] + 1.0)+ (alphaxi + 1.0) * log(tauxi);
mlx = mlx - lgamma(alphaxi + 1.0)- (alphaxi + m[i] + 1.0) * log(tauxi + trns[i][j]);
}
}
}
return (mlx);
}
#define MAXFLDS 200 /* maximum possible number of fields */
#define MAXFLDSIZE 32 /* longest possible field + 1 = 31 byte field */
void parse(char *record, char *delim, char arr[][MAXFLDSIZE], int *fldcnt) {
char*p = strtok(record, delim);
int fld = 0;
while (p) {
strcpy(arr[fld], p);
fld++;
p = strtok('\0', delim);
}
*fldcnt = fld;
}
void main() {
printf("inizio\n");
FILE *pf;
int N=20;
bool first=true;
const char *a[]={"0","1","2"};
char *traject[]={"0-0","0-1","0-2","1-0","1-1","1-2","2-0","2-1","2-2"};
double bs=0;
char *trat="-";
pf=fopen("//home//user//prova.csv","r");
float array[10][10];
float *t;
char *str= "hello";
char *state;
t = (float *)malloc(N * sizeof(float));
int f=0;
if (pf)
{
size_t i, j, k;
char buffer[BUFSIZ], *ptr;
/*
* Read each line from the file.
*/
for ( i = 0; fgets(buffer, sizeof buffer, pf); ++i )
{
/*
* Parse the comma-separated values from each line into 'array'.
*/
for ( j = 0, ptr = buffer; j < ARRAYSIZE(*array); ++j, ++ptr )
{
array[i][j] = strtof(ptr, &ptr);
}
}
fclose(pf);}
else /* fopen() returned NULL */
{
perror(pf);
}
for(f=0; f<10; ++f){
if(f==0){}
else if(f==1 && array[f][8]==0)
array[f][8]=123.8149353;
t[f]=array[f][8];
//printf("%f \n",t[f]);
}
for (f=0;f<10; ++f){
printf("%f - ",t[f]);
}
//printf("%s, %s, %s \n",a[0],a[1],a[2]);
printf("start\n");
int sz = sizeof(a) / sizeof(char);
int dim = sizeof(traject) / sizeof(char);
printf("%d , %d \n",sz,dim);
bs=calculateMLpa(a,traject,t,1.0,0.1,sz,dim);
printf("done \n");
printf("%f ",bs);
}
EDIT
I try to pass array size
sz=sizeof(a)/sizeof(char)
dim = sizeof(traject) / sizeof(char);
but their value is 24 and 72 respectively, and the execution stops at 0-2 value 100.000000
Arrays passed to functions decay to pointers to the start of the array. So
#define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))
Will not return anything meaningful when checking for its size in that case
To fix, pass the Array size as an additional Argument.
One major problem is that when you pass arrays to functions, they decay to pointers, and the sizeof trick you use to get the array size will not work.
You need to pass the actual array sizes as arguments.
If I have an
int i = 11110001
How would I be able to convert this int into an int array where
int array[8] = {1, 1, 1, 1, 0, 0, 0, 1}
Using a little different approach and snprintf:
#include <stdio.h>
int main (void) {
int i = 11110001;
char arr[9]; //8 digits + \0
int array[8];
if ((snprintf(arr,9,"%d", i) == 8) { //return the 8 characters that were printed
int c;
for(c = 0; c < 8; c++)
array[c] = arr[c] - '0';
}
return 0;
}
P.S: I'm assuming positive values only
You may try like this:
#include <math.h>
char * convertNumber(unsigned int i) {
/* unsigned int length = (int)(log10((float)i)) + 1; */
/* char * arr = (char *) malloc(length * sizeof(char)), * x = arr; */
char * arr = malloc(8);
char * x = arr;
do
{
*x++ = i% 10;
i/= 10;
} while (i != 0);
return arr;
}
Try this :
#include<stdio.h>
void convert_int_to_array(unsigned int);
int main()
{
unsigned int a = 12345678;
convert_int_to_array(a);
return 0;
}
void convert_int_to_array(unsigned int a)
{
int array[25]; // array large enough for an integer
int i = 0, count = 0;
unsigned int num = a;
memset(array, '\0', 20); // I've not included the header file for this.
// gives a warning on compilation.
while(num > 0)
{
array[i] = num % 10;
num = num / 10;
++i;
++count;
}
for(i = count; i>=0;--i)
{
printf("array[%d] = %d\n",i, array[i]);
// or
printf("%d", array[i]);
// dont use both the printf statements, else you will see a
// messed up output.
}
}
BINARY REPRESENTATION :
#include<stdio.h>
struct bit
{
int a : 1;
};
int main()
{
struct bit b;
int d ,f,i;
d=f=256; // take any number of your choice
printf("binary representation of 256:\n");
for(i = 15; i>=0 ; i--) //assuming that the number wont have more than
// 15 DIGITS
{
f=f>>i;
b.a = f;
//d= d>>1;
f=d;
printf("%d",b.a);
}
return 0;
}