Adding element to array, random number outcome - c

I'm trying to be able to add a pic to the existing staff using this function:
Staff addpic(Staff array[], int staffCount)
{
Staff newStaff = {};
printf("type in the name you would like to add pic to \n");
fgets(newStaff.name, 30, stdin);
for(int i = 0; i< staffCount; i++) {
if(strcmp(array[i].name,newStaff.name)==0) {
if(array[i].imagecount<5) {
printf("type in pic\n");
int newpic;
scanf("%d",&newpic);
array[i].imagecount++;
int *newpics = realloc(newStaff.pic, (array->imagecount) * sizeof(int));
newpics[array->imagecount-1] = newpic;
newStaff.pic = newpics;
}
}
}
return newStaff;
}
but it does now work as I was hoping. it adds a new pic but just a random number.
the out come will look like this:
type in the name you would like to add pic to
Anna
type in pic
99
1.Show existing
2.add pic to a staff
1
Adam 1,2,3,
Anna 1,2,3,-455802818,

The mistakes are:
array[i] is updated, but imagecount of array[0] is used to select the element to be updated.
array[i].pic is not updated while array[i].imagecount is updated. newStaff.pic, which is passed to realloc() and updated, is initialized to NULL and not related with array[i].pic.
Corrected verson:
Staff addpic(Staff array[], int staffCount)
{
Staff newStaff = {};
printf("type in the name you would like to add pic to \n");
fgets(newStaff.name, 30, stdin);
for(int i = 0; i< staffCount; i++) {
if(strcmp(array[i].name,newStaff.name)==0) {
if(array[i].imagecount<5) {
printf("type in pic\n");
int newpic;
scanf("%d",&newpic);
array[i].imagecount++;
/* use array[i].pic instead of newStaff.pic and use array[i].imagecount instead of array->imagecount */
int *newpics = realloc(array[i].pic, (array[i].imagecount) * sizeof(int));
/* use array[i].imagecount instead of array->imagecount */
newpics[array[i].imagecount-1] = newpic;
/* update array[i].pic instead of newStaff.pic */
array[i].pic = newpics;
}
}
}
return newStaff;
}

Related

How to solve printing error using malloc method?

The below code reads and stores the content of a .txt file into an array.
However instead of printing all the names in the file, it only prints the last line Matthew 789 30 times. My print function looks right but not sure where am I going wrong.
main
while (fscanf( in , "%s %s", name, num) == 2) {
array_of_students[i] = make_node(name, num);
}
printf("\nOriginal unsorted array\n");
print_array(array_of_students, 30);
Function:
Student * make_node(char * name, char * number) {
Student * new_student;
new_student = (Student * ) malloc(CLASS_SIZE * sizeof(Student));
int i = 0;
new_student[i].name = NULL;
new_student[i].number = NULL;
new_student[i].name = name;
new_student[i].number = number;
i++;
return new_student;
}
void print_array(Student * array_of_students[], int size) {
for (int i = 0; i < 30; i++) {
printf("%s %s\n", array_of_students[i] -> name, array_of_students[i] -> number);
}
}
txt file:
John 123
Walter 456
Matthew 789
You're assigning the same pointer values for name and number for each Student object you're creating, and overwriting the arrays those pointers point to each time.
You need to allocate space for the name and number members to point to space to store the strings in question and copy them over. You're also allocating space for too many Student objects. You only need one here:
Student *make_node(char * name, char * number) {
Student *new_student = malloc(sizeof(Student));
new_student->name = strdup(name);
new_student->number = strdup(number);
return new_student;
}
You also need to increment i in the scanf loop:
i = 0;
while (fscanf( in , "%s %s", name, num) == 2) {
array_of_students[i++] = make_node(name, num);
}
array_of_students[i] = make_node(name, num);
But nothing's incrementing i when you go around the loop. Should be i++?
print_array(array_of_students, 30);
Probably should pass i instead of 30.
for (int i = 0; i < 30; i++)
and you didn't use size here

How to delete all that match

Right now this function is deleting the last name given by the user from a list, but I need it to delete all the names that match the name given by the user, not just the first occurrence of the user input, and need to free up allocated memory of the names that got deleted. How can I do this?
int deleteR(char**Fname,char **Lname,float *score,int count)
{
int i=0,j=0;
char *Lastname;
printf("\n Enter the Last Name of the Student you would like to delete from the records. ");
Lastname = (char *)malloc(15 * sizeof(char));
printf("\nLast Name: ");
scanf("%s",Lastname);
int counter = count;
for(i=0;i<count-1;i++)
{
if(strcmp(Lname[i],Lastname)==0)
{
for(j=i;j<count;j++)
{
Lname[j]=Lname[j+1];
Fname[j]=Fname[j+1];
score[j]=score[j+1];
}
counter--;
}
}
count=counter;
return count;
}
In case your loop on j remove entries because you do not change count later in a loop on i you will access values already checked and may freed because removed
You also have a memory leak because you allocate memory for Lastname but you never free it, and in fact there is no reason to not have Lastname as an array in the stack. Also your scanf can write out of Lastname without limit in size.
You do not need to have two embedded loops as you do, only one is enough to move entries managing an index to write and an other to read :
int deleteR(char**Fname, char **Lname, float *score, int count)
{
char lastname[16];
printf("\nEnter the Last Name of the Student you would like to delete from the records: ");
if (scanf("%15s", lastname) == 1) {
int i;
/* that first loop to search if the lastname is present */
for (i = 0; i < count; ++i) {
if (!strcmp(Lname[i], lastname)) {
/* at least present one time, update lists */
int futureCount = count - 1;
int j;
/* it seems you want to free removed resources */
free(Lname[i]);
free(Fname[i]);
/* that loop to move useful elements */
for (j = i + 1; j < count; ++j) {
if (strcmp(Lname[j], lastname)) {
/* still usefull */
Lname[i] = Lname[j];
Fname[i] = Fname[j];
score[i] = score[j];
i += 1;
}
else {
/* useless */
/* it seems you want to free removed resources */
free(Lname[j]);
free(Fname[j]);
futureCount -= 1;
}
}
return futureCount;
}
}
}
else
puts("EOF");
return count;
}
Using that main function to check :
int main()
{
char * fname[5];
char * lname[5];
float score[5];
int count, i;
fname[0] = strdup("Wolfgang Amadeus");
lname[0] = strdup("Mozart");
score[0] = 0;
fname[1] = strdup("Johann Sebastian");
lname[1] = strdup("Bach");
score[1] = 1;
fname[2] = strdup("Leopold");
lname[2] = strdup("Mozart");
score[2] = 2;
fname[3] = strdup("Johann Christian");
lname[3] = strdup("Bach");
score[3] = 3;
fname[4] = strdup("Ludwig van");
lname[4] = strdup("Beethoven");
score[4] = 4;
count = deleteR(fname, lname, score, 5);
printf("new lists:\n");
for (i = 0; i != count; ++i)
printf("%s %s : %g\n", fname[i], lname[i], score[i]);
return 0;
}
Compilation and executions :
pi#raspberrypi:/tmp $ gcc -Wall d.c
pi#raspberrypi:/tmp $ ./a.out
Enter the Last Name of the Student you would like to delete from the records: Chopin
new lists:
Wolfgang Amadeus Mozart : 0
Johann Sebastian Bach : 1
Leopold Mozart : 2
Johann Christian Bach : 3
Ludwig van Beethoven : 4
pi#raspberrypi:/tmp $ ./a.out
Enter the Last Name of the Student you would like to delete from the records: Mozart
new lists:
Johann Sebastian Bach : 1
Johann Christian Bach : 3
Ludwig van Beethoven : 4
pi#raspberrypi:/tmp $

Saving int value into Eeprom and loading it back into a value again

so i am trying to save an integer value into Eeprom and load it back into a value again. But the problem is, that i can't load the saved int value correctly into the new int value.
I am doing this, because I want to compare the new int value with the already saved one, to control a stepper motor with the rotations got from that value.
void SaveParam(int* param) {
Serial.print("Saving Param: ");
//Serial.println(param);
EEPROM.begin(512);
for (int i = 0; i < 4; i++)
EEPROM.write(i+500, (int)param[i]);
EEPROM.end();
}
int LoadParam(){
int b[10];
EEPROM.begin(512);
for (int i = 0; i < 4; i++)
b[i]= byte(EEPROM.read(i+500));
EEPROM.end();
return b[10];
}
// main part
int b = (int)LoadParam();
int* val = &i;
if (i>b) {
Serial.print("Motor is going down (clockwise) ");
MotorMoveDown(i);
SaveParam(val);
Serial.println(b);
} else if (i<b) {
Serial.print("Motor is going up (counter-clockwise)");
MotorMove(i);
}

Adding element to array, old values turns to 0 but new shows

I have written this program where I can add pics to a staff using their names. but right now it adds the new value but the already existing values becomes 0.
this is the outcome:
type in the name you would like to add pic to
Anna
type in pic
55
1.Show existing
2.add pic to a staff
1
Adam 1,2,3,
Anna 0,0,0,55,
the rest of the code:
typedef struct Staff
{
char name[30];
int *pic;
int imagecount;
} Staff;
void printStaff(Staff *pStaff)
{
printf("%s ", pStaff->name);
if ( pStaff->pic) {
for(int i=0; i<pStaff->imagecount; i++){
printf("%d,",pStaff->pic[i]);
}
}
printf("\n");
}
void PrintList(Staff aLista[], int staffCount)
{
for (int i = 0; i < staffCount; i++) {
printStaff(&aLista[i]);
}
}
UPDATED CODE:
Staff addpic(Staff array[], int staffCount)
{
Staff newStaff = {};
printf("type in the name you would like to add pic to \n");
fgets(newStaff.name, 30, stdin);
for(int i = 0; i< staffCount; i++) {
if(strcmp(array[i].name,newStaff.name)==0) {
if(array[i].imagecount<5) {
printf("type in pic\n");
int newpic;
scanf("%d",&newpic);
array[i].imagecount++;
int *newpics = realloc(newStaff.pic, (array[i].imagecount) * sizeof(int));
newpics[array[i].imagecount-1] = newpic;
array[i].pic = newpics;
}
}
}
return newStaff;
the rest of the code:
int main(void)
{
int staffCount=0;
int input;
int test[3] = {1,2,3};
Staff myStaff[5] = { {"Adam", test, 3},{"Anna",test,3} };
staffCount=2;
do
{
printf("1.Show existing \n");
printf("2.add pic to a staff");
printf("\n");
scanf("%d", &input);
switch(input)
{
case 1:
PrintList(myStaff,staffCount);
break;
case 2:
addpic(myStaff,staffCount);
break;
default:
printf("inccorect inpput\n");
break;
}
}while (input<'1' ||input<'2');
return 0;
}
any help is appreciated, but I'm new to coding so keep that in mind.
In the addpic function you do
int *newpics = realloc(array[i].pic, ...);
One problem is that if you do it for one of the two elements you have initialized in array, then array[i].pic is pointing to the first element of an array (the array test in the main function).
Arrays can not be reallocated. If you want to reallocate the memory you need to allocate the original memory dynamically as well.
newStaff.pic is initialized to NULL and not updated then, so realloc(newStaff.pic, (array[i].imagecount) * sizeof(int)); is equivalent to malloc((array[i].imagecount) * sizeof(int));.
Elements allocated via malloc() and not initialized hae indeterminate value, and they happened to be zero in this case.
You can take over the contents by manually copying them.
int *newpics = realloc(newStaff.pic, (array[i].imagecount) * sizeof(int));
/* add this line to copy contents */
for (int j = 0; j < array[i].imagecount-1; j++) newpics[j] = array[i].img[j];
newpics[array[i].imagecount-1] = newpic;
Unfortunately, this method is not good because this may cause memory leak if addition like this to the same element of array is done multiple times.
Better way is to allocate the buffer to assign to img dynamically and pass them to realloc(). Then, realloc() will do the copying for you.
Initialization part:
int test[3] = {1,2,3};
Staff myStaff[5] = { {"Adam", test, 3},{"Anna",test,3} };
staffCount=2;
/* add this to change statically allocated arrays to dynamically allocated ones */
for (int i = 0; i < staffCOunt; i++) {
int* newpics = malloc(myStaff[i].imagecount * sizeof(int));
for (int j = 0; j < myStaff[i].imagecount; j++) newpics[j] = myStaff[i].img[j];
myStaff[i].img = newpics;
}
Updating part:
/* use array[i].pic instead of newStaff.pic */
int *newpics = realloc(array[i].pic, (array[i].imagecount) * sizeof(int));
/* then, no manual copying is required */
(error checkings are omitted)

increment in a loop and keeping state

gcc 4.4.4 c89
I have the following code and 2 structures that have to be filled.
I have 3 functions that will fill the handles for each of the devices.
However, the device_type structure will need to increment from where the last function finished.
For example:
load_resources() starts at 0 and finishes at 9
dev_types starts at 0 and finishes at 9
load_networks() starts at 0 and finishes at 9
dev_types starts at 10 and finishes at 19
load_controls() starts at 0 and finishes at 9
dev_types starts at 20 and finishes at 29
However, as I don't want to use a static or global variable is there any way I can increment a
value for this. So it will start where the last function finished.
Many thanks for any suggestions,
#define NUMBER_OF_DEVICES 10
#define NUMBER_OF_TYPES 3 /* resources
networks
controls */
int events(int evt);
int load_resources();
int load_networks();
int load_controls();
static struct device_table {
int resource_handle;
int network_handle;
int control_handle;
} dev_tbl[NUMBER_OF_DEVICES];
struct device_types {
size_t id;
int dev_handle;
int dev_type;
}dev_types[NUMBER_OF_DEVICES * NUMBER_OF_TYPES];
enum dev_name_types {RESOURCE, NETWORK, CONTROL};
/* Simulates the API calls, by returning a dummy handle */
int get_resources();
int get_networks();
int get_controls();
int main(void)
{
srand(time(NULL));
load_resources();
load_networks();
load_controls();
return 0;
}
int load_resources()
{
size_t i = 0;
for(i = 0; i < NUMBER_OF_DEVICES; i++) {
dev_tbl[i].resource_handle = get_resources();
printf("dev_tbl[i].resource_handle [ %d ]\n", dev_tbl[i].resource_handle);
dev_types[i].id = i;
dev_types[i].dev_handle = dev_tbl[i].resource_handle;
dev_types[i].dev_type = RESOURCE;
}
}
int load_networks()
{
size_t i = 0;
for(i = 0; i < NUMBER_OF_DEVICES; i++) {
dev_tbl[i].network_handle = get_networks();
printf("dev_tbl[i].network_handle [ %d ]\n", dev_tbl[i].network_handle);
dev_types[i].id = i;
dev_types[i].dev_handle = dev_tbl[i].network_handle;
dev_types[i].dev_type = NETWORK;
}
}
int load_controls()
{
size_t i = 0;
for(i = 0; i < NUMBER_OF_DEVICES; i++) {
dev_tbl[i].control_handle = get_controls();
printf("dev_tbl[i].control_handle [ %d ]\n", dev_tbl[i].control_handle);
dev_types[i].id = i;
dev_types[i].dev_handle = dev_tbl[i].control_handle;
dev_types[i].dev_type = CONTROL;
}
}
Why not change the prototypes to something like:
void load_resources(int*)
(they're not actually returning anything) then, in your main code, have:
int base = 0;
load_resources (&base);
load_networks (&base);
load_controls (&base);
Each function is then responsible for using and updating *base like this:
void load_resources (int *pBase) {
size_t i = 0;
for(i = 0; i < NUMBER_OF_DEVICES; i++, (*pBase)++) { // <-- see here!
dev_tbl[i].resource_handle = get_resources();
printf("dev_tbl[i].resource_handle [ %d ]\n", dev_tbl[i].resource_handle);
dev_types[*pBase].id = i;
dev_types[*pBase].dev_handle = dev_tbl[i].resource_handle;
dev_types[*pBase].dev_type = RESOURCE;
}
}
One option is to have each of your functions take the base index as a parameter, and returning the first available index:
int index = 0;
index = load_resources(index);
index = load_network(index);
// and so on
With this yout functions would look something like this:
int load_resources(int base_index)
{
size_t i = 0;
size_t index;
for(i = 0; i < NUMBER_OF_DEVICES; i++) {
index = base_index + i;
dev_tbl[index].resource_handle = get_resources();
//
}
return index + 1;
}
By the way, your functions do have int return types, but do not return anything.
Hold a pointer or index variable within the structure itself. It's an indicator for how far the structure has been filled up generally.
There are only two ways to persist data from one scope to the next - on the stack and on the heap. Since you have already ruled out any global variables here, that would require you to use stack variables, by passing in a parameter and returning a value, or passing in a pointer to a parameter.

Resources