I have a 1 dimensional array in which ive initialized as 0 but for some reason when i go inside a loop and try to increase its contents by one the value at position 0 keeps reverting to 0 even after i increase it by 1.
#include <stdio.h>
#include <stdlib.h>
#define TOTAL_V 3
#define NUM_CANDIDATES 7
int hex_age(unsigned short hex){
unsigned short age = hex >> 9;
if (age >18 && age <101)
return age;
else return 0;
}
int hex_gender(unsigned short hex){
unsigned short gender = hex >> 7 & 3;
return gender;
}
int hex_vote(unsigned short hex){
unsigned short vote, tmp = hex & 0x7f , count = 0;
if (tmp == 0)
return 7;
for (int i = 0 ; i<7; i ){
if (tmp & 1 == 1){
count ;
vote = i;
}
tmp = tmp >> 1;
}
if (count > 1)
return 7;
return vote;
}
int main() {
int s_votes = 0, f_votes = 0, v_count[NUM_CANDIDATES] = {0};
unsigned short **v_info, hex_v_info , age , gender , vote;
FILE *fp;
fp = fopen("data1.dat" , "r");
if (fp == NULL){
fprintf(stderr ,"apotuxe o anoigmos tou arxeiou");
exit(-1);
}
if (feof(fp)){
fprintf(stderr, "to arxeio einai adeio");
exit(-1);
}
while (fscanf(fp ,"%x", &hex_v_info) != EOF){
age = hex_age(hex_v_info);
if(age == 0)
f_votes ;
else {
gender = hex_gender(hex_v_info);
if (gender == 0)
f_votes ;
else{
vote = hex_vote(hex_v_info);
if (vote == 7)
f_votes ;
else{
if (s_votes == 0){
v_info = malloc(sizeof(int *));
v_info[s_votes] =malloc(sizeof(int)* TOTAL_V);
}
else{
v_info = realloc(v_info , sizeof(int *)*(s_votes 1));
v_info[s_votes] = malloc(sizeof(int)*TOTAL_V);
}
v_info[s_votes][0] = age;
v_info[s_votes][1] = gender;
v_info[s_votes][2] = vote;
v_count[vote] ;
s_votes ;
}
}
}
}
fclose(fp);
for (int i = 0; i<s_votes; i )
free(v_info);
return 0;
}
and for some reason when i use calloc to create the array it doesnt have that problem. Does anyone know why that happens
CodePudding user response:
You declare
unsigned short hex_v_info
(2 bytes on my system), then read data from withfscanf(fp ,"%x", &hex_v_info)
where the format string%x
expect the address of an int (4 bytes on my system). This will certainly overwrite data unexpectedly.unsigned short **v_info
but you store an array ofint [s_votes]
. If your pointers are not uniform this will be a problem.realloc(NULL, 1)
is well defined so just use instead ofmalloc() of the first element. You need to assign the result of
realloc()` to e temporary variable, however, to be able handle NULL. Otherwise you lose data & leak memory.free(v_info);
results in a double free if s_votes > 1, and you still leak the memory you allocate atv_info[i]
.
#include <stdio.h>
#include <stdlib.h>
#define TOTAL_V 3
#define NUM_CANDIDATES 7
// 0x1111 1110 0000 0000
int hex_age(unsigned short hex){
unsigned short age = hex >> 9;
if (age >18 && age < 101)
return age;
return 0;
}
// 0x0000 0001 1000 0000
int hex_gender(unsigned short hex){
unsigned short gender = hex >> 7 & 3; // bit 7 and 6
return gender;
}
// 0x0000 0000 0111 1111
int hex_vote(unsigned short hex){
unsigned short vote, tmp = hex & 0x7f , count = 0; // bit 11 through 0
if (tmp == 0)
return 7;
for (int i = 0 ; i<7; i ){
if ((tmp & 1) == 1){
count ;
vote = i;
}
tmp = tmp >> 1;
}
if (count > 1)
return 7;
return vote;
}
int main() {
int s_votes = 0, f_votes = 0, v_count[NUM_CANDIDATES] = {0};
unsigned short hex_v_info;
int **v_info = NULL;
FILE *fp = fopen("data1.dat" , "r");
if (!fp){
fprintf(stderr ,"apotuxe o anoigmos tou arxeiou");
exit(-1);
}
for(;;) {
int rv = fscanf(fp ,"%hx", &hex_v_info);
if(rv == EOF) break;
if(rv != 1) {
printf("err\n");
return 1;
}
unsigned short age = hex_age(hex_v_info);
if(!age) {
f_votes ;
continue;
}
unsigned short gender = hex_gender(hex_v_info);
if (!gender) {
f_votes ;
continue;
}
unsigned short vote = hex_vote(hex_v_info);
if (vote == 7) {
f_votes ;
continue;
}
int **tmp = realloc(v_info, sizeof *tmp * (s_votes 1));
if(!tmp) {
// handle error: free v_info[i] and v_info?
return 1;
}
v_info = tmp;
v_info[s_votes] = malloc(sizeof **v_info * TOTAL_V);
v_info[s_votes][0] = age;
v_info[s_votes][1] = gender;
v_info[s_votes][2] = vote;
v_count[vote] ;
s_votes ;
}
fclose(fp);
printf("f_votes: %d\n", f_votes);
for(size_t i = 0; i < s_votes; i ) {
printf("%zu: %d %d %d\n",
i,
v_info[i][0],
v_info[i][1],
v_info[i][2]
);
}
for (int i = 0; i< s_votes; i )
free(v_info[i]);
free(v_info);
return 0;
}
and with input file file:
a081
a082
it appears to process the info data correctly:
f_votes: 0
0: 80 1 0
1: 80 1 1