changing size of array - c

I have the following code:
typedef struct my_data {
char* name;
}my_data;
my_data data[]={
{ .name = "Peter" },
{ .name = "James" },
{ .name = "John" },
{ .name = "Mike" }
};
void loaddata()
{
FILE * in;
if((in = fopen("data.txt","rt")) != NULL) {
memset(data, 0, sizeof(data));
int i = 0;
while(!feof(in))
{
fscanf(in,"%s", &data[i].name);
i++;
};
fclose(in);
}
}
to read contents and process them I use this:
for (i=0; i<sizeof(data)/sizeof(data[0]); i++)
but if the number of lines in file is less than the number of defined array I get a lot of empty records so I modified it into:
for (i=0; (i<sizeof(data)/sizeof(data[0])) && strlen(data[i].name)>0; i++)
which is working fine but I'm sure I will get errors if the number of lines in file will be larger than the defined array size.
Any idea how to make this code safe? To change array dynamically?
EDIT:
this way is working with size 300
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
typedef struct my_data {
char name[100];
}my_data;
struct my_data data[300];
my_data data_arr[]={
{ .name = "Peter" },
{ .name = "James" },
{ .name = "John" },
{ .name = "Mike" }
};
void process_data()
{
char name[100];
int i;
for (i=0; (i<sizeof(data)/sizeof(data[0])) && strlen(data[i].name)>0; i++) {
sprintf(name, "%s", data[i].name);
printf("%s\n", name);
}
}
void load_data()
{
int i = 0;
FILE * in;
if((in = fopen("data.txt","rt")) != NULL) {
while(!feof(in))
{
fscanf(in,"%s", &data[i].name);
i++;
};
fclose(in);
}
else
{
for (i=0; (i<sizeof(data_arr)/sizeof(data_arr[0])) && strlen(data_arr[i].name)>0; i++) {
sprintf(data[i].name, "%s", data_arr[i].name);
}
}
return;
}
int main()
{
load_data();
process_data();
return 0;
}

Arrays do not grow dynamically in C. So you have a few approaches:
get a pointer to a block of memory (using malloc) and use realloc whenever you need more space for an array - and index into your pointer
create a linked list using malloc for every new item you want to add to your list
Don't forget when using malloc to call free on every single block that you called malloc for.

Related

C structure printing wrong value even after initializing properly

In the program below, I am allocating memory for pointer to pointer properly and then allocating individual pointers and setting values properly, even though I am getting the garbage value to one of the structure member. I don't understand where exactly I am going wrong.
The sample output of below program is:
***CK: H2 nSupport: 0
CK: H2 nSupport: 1303643608
CK: FR2 nSupport: 0
CK: H2 nSupport: 1303643608
CK: FR2 nSupport: 0
***CK: SP2 nSupport: 0
I don't understand how I am getting the value 1303643608, though it is set properly at the beginning.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define NOK 15
#define ML 100
typedef struct sample_test_for_ties_t
{
char sender[NOK];
char receiver[NOK];
char message[ML];
}sample_test_for_ties;
typedef struct CUOfS_t{
char cK[NOK];
char eK[NOK];
char nK[NOK];
char AL[ML];
int nSupport;
}CUOfS;
CUOfS **Btenders = NULL;
sample_test_for_ties test_ties[] = {
{"H2","ICY", "fmaabghijklmmcdenoopqrstuvwxyz"},
{"FR2","AIY", "fmaabghijklmmcdenoopqrstuvwxyz"},
{"SP2","LAY", "fmaabghijklmmcdenoopqrstuvwxyz"},
{"H30","ICY", "fmaabghijklmmcdenoopqrstuvwxyz"},
{"F30","AIY", "fmaabghijklmmcdenoopqrstuvwxyz"},
{"W30","LAY", "fmaabghijklmmcdenoopqrstuvwxyz"},
};
void InitBtenders(int numOfBCtenders)
{
int count =0;
if(!Btenders)
{
if(Btenders = (CUOfS **)malloc(sizeof (**Btenders) * numOfBCtenders))
{
while(count < numOfBCtenders)
{
Btenders[count] = NULL;
count++;
}
}
else
{
printf("Malloc failed\n");
}
}
}
void freeBtenders(int numOfBCtenders)
{
int count =0;
if(Btenders)
{
while(count<numOfBCtenders)
{
if(Btenders[count]) {
free(Btenders[count]);
Btenders[count] = NULL;
}
count++;
}
free(Btenders);
Btenders = NULL;
}
}
void UpdateBtendersInfo(char *aContenders)
{
static int counter =0;
if(Btenders)
{
if(Btenders[counter] == NULL) {
Btenders[counter] = (CUOfS *)malloc(sizeof (Btenders[counter]));
if(Btenders[counter])
{
strcpy(Btenders[counter]->cK,aContenders);
strcpy(Btenders[counter]->eK,"\0");
strcpy(Btenders[counter]->nK,"\0");
memset(Btenders[counter]->AL,0,sizeof(Btenders[counter]->AL));
Btenders[counter]->nSupport = 0;
counter++;
}
else
{
printf("Insufficient memory for Btender\n");
}
}
}
else
{
printf("Looks like memory not allocated for Btenders\n");
}
int count =0;
while(count <counter && Btenders[count])
{
printf("***CK: %s nSupport: %d\n",Btenders[count]->cK,Btenders[count]->nSupport);
count++;
}
printf("\n");
}
int main()
{
int numOfBCtenders = 3;
int noc =0;
InitBtenders(numOfBCtenders);
while(noc < numOfBCtenders)
{
UpdateBtendersInfo(test_ties[noc].sender);
noc++;
}
freeBtenders(numOfBCtenders);
return 0;
}
I expect
***CK: H2 nSupport: 0
But I am getting
***CK: H2 nSupport: 1303643608
The way you allocate memory for Btenders is incorrect.
Btenders = (CUOfS **)malloc(sizeof (**Btenders) * numOfBCtenders) // WRONG
sizeof (**Btenders) is the same as sizeof(CUOfS), but you need sizeof(CUOfS*) :
Btenders = (CUOfS **)malloc(sizeof (*Btenders) * numOfBCtenders) // FIXED
Similarly for :
Btenders[counter] = (CUOfS *)malloc(sizeof (Btenders[counter])); // WRONG
sizeof (Btenders[counter]) is the same as sizeof(CUOfS*), but you need sizeof(CUOfS) :
Btenders[counter] = (CUOfS *)malloc(sizeof (*(Btenders[counter]))); // FIXED

Getting memory leak but memory allocated was deallocated

C noob over here. Created a program that simulates a soccer team to help me get a handle on memory allocation. My program works but valgrind is telling me that I have a memory leak in the methods "create_player" and "add_player_to_club"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 8
typedef struct player {
int id;
char *position;
} Player;
typedef struct club {
int size;
Player *team[SIZE];
} Club;
Player *create_player(int id, const char *description);
void create_team(Club *club);
void print_club(const Club *club);
void destroy_player(Player *player);
void add_player_to_club(Club *club, int id, const char *position);
void destroy_club(Club *club);
int main() {
Club club;
create_team(&club);
add_player_to_club(&club, 1, "forward");
add_player_to_club(&club, 2, "goalie");
print_club(&club);
destroy_club(&club);
return 0;
}
Player *create_player(int id, const char *description){
Player *player;
player = malloc(sizeof(Player));
if(description == NULL){
player->position = NULL;
} else {
player->position = malloc(strlen(description) + 1);
strcpy(player->position, description);
player->id = id;
}
return player;
}
void destroy_player(Player *player){
if (player == NULL){
return;
} else {
free(player->position);
free(player);
}
}
void create_team(Club *team){
team->size = 0;
}
void print_club(const Club *club) {
int i = 0;
if (club == NULL) {
return;
} else if (club->size == 0) {
printf("No team members\n");
} else {
for (i = 0; i < club->size; i++) {
printf("Id: %d Position: %s\n", club->team[i]->id,
club->team[i]->position);
}
}
}
void add_player_to_club(Club *club, int id, const char *position){
if (club == NULL || club->size >= SIZE) {
return;
} else {
club->team[club->size] = create_player(id, position);
club->size++;
}
}
void destroy_club(Club *club){
int i = 0;
if (club == NULL) {
return;
} else {
club->size = 0;
for (i = 0; i < club->size; i++) {
destroy_player(club->team[i]);
}
}
}
I think the problem might be with my "destroy club" method. Player "objects" are stored in the "team" array. I allocated memory for each player object and deallocating by iterating through team array and freeing each index. What did I screw up?
In destroy_club, you set size to 0, then use that to loop through the players, so it loops through nothing.
Set size to 0 after cleaning up the players:
for (i = 0; i < club->size; i++) {
destroy_player(club->team[i]);
}
club->size = 0;

Accessing certain elements in an Struct in C

So I have the following struct I created:
struct _I_TypeInstructions {
const char *instructionName;
char *opcode;
} I_TypeInstructions[] = { { "lw", "100011" }, { "sw", "101011" }, { "beq",
"000100" } };
typedef struct _I_TypeInstructions I_TypeInstructionsStruct;
If I have a new instructionName and I want to check if it is in the I_TypeInstructionsStruct how do I iterate through just the *instructionName part of the struct above. For example the function I want to write would look something like
bool checkIfInstructionIsI_Type(char *instructionName) {
// somehow iterate through instructionNames in the struct above
// checking if parameter char *instructionName in this method is equal to
// "lw" "sw" "beq" but skipping over the binary numbers.
}
Searching a list of structs is rather straight forward:
bool checkIfInstructionIsI_Type(char *instructionName)
{
for (int i = 0; i<NumInstructions; i++)
{
if (strcmp(I_TypeInstructions[i].instructionName, instructionName) == 0)
{
return true;
}
}
return false;
}
int i;
for(i = 0; i < 3; ++i)
{
if (strcmp(instructions[i].instructionName, instructionName) == 0)
{
printf("Match found");
}
}
It's generally more useful to return the actual element that matches your string. It's the same amount of work anyway.
Add an empty element to the end of your array and then you have a end marker.
typedef struct _I_TypeInstructions {
const char *instructionName;
char *opcode;
} I_TypeInstructionsStruct;
I_TypeInstructionsStruct I_TypeInstructions[] = {
{ "lw", "100011" },
{ "sw", "101011" },
{ "beq", "000100" },
{ 0, 0}
};
I_TypeInstructionsStruct *find_instruction(char *name)
{
I_TypeInstructionsStruct *i ;
for (i = I_TypeInstructions ; i->instructionName ; i++)
if (!strcmp(i->instructionName,name)) return i ;
return 0 ;
}

load file content into structure only if file exists or use default values

I have the following code:
typedef struct my_data {
char* name;
}my_data;
my_data data[]={
{ .name = "Peter" },
{ .name = "James" },
{ .name = "John" },
{ .name = "Mike" }
};
void loaddata()
{
FILE * in;
if((in = fopen("data.txt","rt")) != NULL) {
printf("start loading\n");
int i = 0;
while(!feof(in))
{
fscanf(in,"%s", &data[i].name);
printf("%s\n",data[i].name);
i++;
};
}
else
printf("loading not required\n");
fclose(in);
}
And it gives me a "killed" error.
How can I load data from file data.txt into existing structure and in case file doesn't exist to use default values which were defined ?
No need "&" in:
fscanf(in,"%s", &data[i].name);
and no need to close filestream if it's not opened.
void loaddata()
{
FILE * in;
if((in = fopen("data.txt","rt")) != NULL) {
printf("start loading\n");
int i = 0;
while(!feof(in))
{
fscanf(in,"%s", data[i].name);
printf("%s\n",data[i].name);
i++;
};
fclose(in); /* need closing */
}
else
printf("loading not required\n");
/* no need closing */
}
UPD: create structure with allocated memory, not pointer. Pointer accesses part of program, not memory, so you cannot save data there.
typedef struct my_data {
char name[10];
}my_data;

The Notorious Dynamic allocation of pointers to arrays of structures

I've a long version of a program that uses this code and a short version. This is the short version and oddly, this code runs perfectly fine in short version program, but because I get an access violation in the larger version, I get the feeling something is wrong. Does anyone see anything terribly wrong (that might lead to data corruption and/or access violation errors) with the following code? Or is this alright?
char strlist[5][11] = {
{ "file01.txt" },
{ "file02.txt" },
{ "file03.txt" },
{ "file04.txt" },
{ "file05.txt" }
};
typedef struct DYNAMEM_DATA {
char *string;
int strlen;
} DYNAMEM_DATA;
typedef struct DYNAMEM_STRUCT {
struct DYNAMEM_DATA **data;
int num_elements;
} DYNAMEM_STRUCT;
DYNAMEM_STRUCT *create_dynamem_struct(int num_elements, char *strlist)
{
DYNAMEM_STRUCT *ds = (DYNAMEM_STRUCT *)calloc(1, sizeof(DYNAMEM_STRUCT));
wchar_t wstring[128];
char len[3];
int i;
ds->data = (DYNAMEM_DATA **)calloc(num_elements, sizeof(DYNAMEM_DATA *));
ds->num_elements = num_elements;
for(i = 0; i < num_elements; i++) {
ds->data[i] = (DYNAMEM_DATA *)calloc(1, sizeof(DYNAMEM_DATA));
ds->data[i]->string = (char *)calloc(1, strlen(&strlist[i*11])+5);
ds->data[i]->strlen = strlen(&strlist[i*11]);
sprintf(ds->data[i]->string, "%s, %d", &strlist[i*11], ds->data[i]->strlen);
mbstowcs(wstring, ds->data[i]->string, 128);
MessageBox(NULL, wstring, TEXT("Error"), MB_OK);
}
return ds;
}
This code runs, produces 5 'Error' messages (which is to be expected), and doesn't leak any memory. Running valgrind (3.7.0) on Mac OS X 10.7.4 (using GCC 4.7.1), it is given a clean bill of health.
The problem is not, apparently, in this version of the code.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <wchar.h>
char strlist[5][11] = {
{ "file01.txt" },
{ "file02.txt" },
{ "file03.txt" },
{ "file04.txt" },
{ "file05.txt" }
};
typedef struct DYNAMEM_DATA {
char *string;
int strlen;
} DYNAMEM_DATA;
typedef struct DYNAMEM_STRUCT {
struct DYNAMEM_DATA **data;
int num_elements;
} DYNAMEM_STRUCT;
enum { MB_OK = 0 };
static void destroy_dynamem_data(DYNAMEM_DATA *dd)
{
free(dd->string);
free(dd);
}
static void destroy_dynamem_struct(DYNAMEM_STRUCT *ds)
{
for (int i = 0; i < ds->num_elements; i++)
destroy_dynamem_data(ds->data[i]);
free(ds->data);
free(ds);
}
static void MessageBox(const void *null, const wchar_t *wcs, const char *ncs, int status)
{
if (null == 0 || status == MB_OK)
fprintf(stderr, "%s\n", ncs);
else
fwprintf(stderr, L"%s\n", wcs);
}
static const char *TEXT(const char *arg) { return arg; }
extern DYNAMEM_STRUCT *create_dynamem_struct(int num_elements, char *strlist);
DYNAMEM_STRUCT *create_dynamem_struct(int num_elements, char *strlist)
{
DYNAMEM_STRUCT *ds = (DYNAMEM_STRUCT *)calloc(1, sizeof(DYNAMEM_STRUCT));
wchar_t wstring[128];
//char len[3];
int i;
ds->data = (DYNAMEM_DATA **)calloc(num_elements, sizeof(DYNAMEM_DATA *));
ds->num_elements = num_elements;
for(i = 0; i < num_elements; i++) {
ds->data[i] = (DYNAMEM_DATA *)calloc(1, sizeof(DYNAMEM_DATA));
ds->data[i]->string = (char *)calloc(1, strlen(&strlist[i*11])+5);
ds->data[i]->strlen = strlen(&strlist[i*11]);
sprintf(ds->data[i]->string, "%s, %d", &strlist[i*11], ds->data[i]->strlen);
mbstowcs(wstring, ds->data[i]->string, 128);
MessageBox(NULL, wstring, TEXT("Error"), MB_OK);
}
return ds;
}
int main(void)
{
DYNAMEM_STRUCT *ds = create_dynamem_struct(5, strlist[0]);
destroy_dynamem_struct(ds);
return 0;
}

Resources