简体   繁体   中英

C (linux) passing array of structs to delete element

I have the following issues in my C Program,

FIRST, I have the following structure,

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct ts{
  char *fname;
  char *lname;
  char *fingers;
  char *toes;
};

void delelement(char *, struct ts *);
int i;

int main(int argc, char **argv){
  struct ts *ex=(struct ts*)malloc(sizeof(struct ts));

  ex[0].fname="joe";
  ex[0].lname="bob";
  ex[0].fingers="11";
  ex[0].toes="9";

  ex[1].fname="billy";
  ex[1].lname="bronco";
  ex[1].fingers="10";
  ex[1].toes="10";

  ex[2].fname="martha";
  ex[2].lname="sue";
  ex[2].fingers="12";
  ex[2].toes="20";

  delelement("billy", ex);

  return 0;
}

For debugging I loop through and print the values in the array of structs - this works (nevermind I'm not returning a value in this function - the problem I'm running into is before we even get to that).

void delelement(char *delwhat, struct ts *passedex){

  //struct ts *tempex=(struct ts*)malloc(sizeof(struct ts));
  for(i=0; i<sizeof(passedex)-1; i++){
    printf("passedex[%d].fname is %s\n", i, passedex[i].fname);    
    printf("passedex[%d].lname is %s\n", i, passedex[i].lname);
    printf("passedex[%d].fingers is %s\n", i, passedex[i].fingers);
    printf("passedex[%d].toes is %s\n", i, passedex[i].toes);
  }
  return;
}

now THAT works fine - prints out information correctly.

now let's simply remove the comment and define the temporary array of structs

void delelement(char *delwhat, struct ts *passedex){

  struct ts *tempex=(struct ts*)malloc(sizeof(struct ts));
  for(i=0; i<sizeof(passedex)-1; i++){
    printf("passedex[%d].fname is %s\n", i, passedex[i].fname);    
    printf("passedex[%d].lname is %s\n", i, passedex[i].lname);
    printf("passedex[%d].fingers is %s\n", i, passedex[i].fingers);
    printf("passedex[%d].toes is %s\n", i, passedex[i].toes);

  }
  return;
}

BOOM - segfault

passedex[0].fname is joe
passedex[0].lname is bob
passedex[0].fingers is 11
passedex[0].toes is 9
passedex[1].fname is billy
Segmentation fault

OK so I tried a different approach - which kind of works

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct ts{
  char *fname;
  char *lname;
  char *fingers;
  char *toes;
};
void delelement(char *, struct ts *, struct ts *);
int i;
int main(int argc, char **argv){
  struct ts *ex=(struct ts*)malloc(sizeof(struct ts));
  struct ts *tempex=(struct ts*)malloc(sizeof(struct ts));

  ex[0].fname="joe";
  ex[0].lname="bob";
  ex[0].fingers="11";
  ex[0].toes="9";
  ex[1].fname="billy";
  ex[1].lname="bronco";
  ex[1].fingers="10";
  ex[1].toes="10";
  ex[2].fname="martha";
  ex[2].lname="sue";
  ex[2].fingers="12";
  ex[2].toes="20";
  delelement("billy", ex, tempex);
  return 0;
}
void delelement(char *delwhat, struct ts *passedex, struct ts *tempex){
  //struct ts *tempex=(struct ts*)malloc(sizeof(struct ts));
  for(i=0; i<sizeof(passedex)-1; i++){
    printf("passedex[%d].fname is %s\n", i, passedex[i].fname);    
    printf("passedex[%d].lname is %s\n", i, passedex[i].lname);
    printf("passedex[%d].fingers is %s\n", i, passedex[i].fingers);
    printf("passedex[%d].toes is %s\n", i, passedex[i].toes);
  }
  return;
}

WORKS fine... (tempex now defined in main)

passedex[0].fname is joe
passedex[0].lname is bob
passedex[0].fingers is 11
passedex[0].toes is 9
passedex[1].fname is billy
passedex[1].lname is bronco
passedex[1].fingers is 10
passedex[1].toes is 10
passedex[2].fname is martha
passedex[2].lname is sue
passedex[2].fingers is 12
passedex[2].toes is 20

now lets start assigning values to *tempex - no segfault with tempex defined in main

void delelement(char *delwhat, struct ts *passedex, struct ts *tempex){

  //struct ts *tempex=(struct ts*)malloc(sizeof(struct ts));

  for(i=0; i<sizeof(passedex)-1; i++){
    printf("passedex[%d].fname is %s\n", i, passedex[i].fname);    
    printf("passedex[%d].lname is %s\n", i, passedex[i].lname);
    printf("passedex[%d].fingers is %s\n", i, passedex[i].fingers);
    printf("passedex[%d].toes is %s\n", i, passedex[i].toes);
    tempex[i].fname=passedex[i].fname;
    tempex[i].lname=passedex[i].lname;
    tempex[i].fingers=passedex[i].fingers;
    tempex[i].toes=passedex[i].toes;
  }
  return;
}

but NOW - weirdness

passedex[0].fname is joe
passedex[0].lname is bob
passedex[0].fingers is 11
passedex[0].toes is 9
passedex[1].fname is billy
passedex[1].lname is bronco
passedex[1].fingers is joe
passedex[1].toes is bob
passedex[2].fname is 11
passedex[2].lname is 9
passedex[2].fingers is billy
passedex[2].toes is bronco

I am getting errors here. The goal is to have a dynamic array of structures containing char *'s. Once past this issue, there will be an instance in main (or wherever) that I wish to delete one of those structures.

What I was going for was something like,

struct ts* delelement(char *delwhat, struct ts *passedex, struct ts *tempex){

  //struct ts *tempex=(struct ts*)malloc(sizeof(struct ts));

  for(i=0; i<sizeof(passedex)-1; i++){
    printf("passedex[%d].fname is %s\n", i, passedex[i].fname);    
    printf("passedex[%d].lname is %s\n", i, passedex[i].lname);
    printf("passedex[%d].fingers is %s\n", i, passedex[i].fingers);
    printf("passedex[%d].toes is %s\n", i, passedex[i].toes);
    //load tempex with everything except the one I want to delete
    if(!(passedex[i].fname==delwhat)){
      tempex[i].fname=passedex[i].fname;
      tempex[i].lname=passedex[i].lname;
      tempex[i].fingers=passedex[i].fingers;
      tempex[i].toes=passedex[i].toes;
    }
  }
  free(passedex); //haven't got here yet - dunno if needed
  //realloc if needed - gotta get here first - pass segfault and/or jumbled data

  for(i=0; i<sizeof(passedex)-1; i++){
    passedex[i].fname=tempex[i].fname;
    passedex[i].lname=tempex[i].lname;
    passedex[i].fingers=tempex[i].fingers;
    passedex[i].toes=tempex[i].toes;
  }

  return passedex;
}

So it would create (or have) a temporary array of structs to work with... load that array minus the one to be deleted... reload the passed array of structs and pass it back.

You only allocated one struct, not 3 as you think.

You should do something like :

struct ts *ex = malloc( sizeof(struct ts) * 3 );

What you do is OK with the const char (string literal) assignments. But you should change your definition of struct ts to:

struct ts{
  const char *fname;
  const char *lname;
  const char *fingers;
  const char *toes;
};

This way your compiler will warn you if you try to change the contents of those strings.

Otherwise you can use malloc() and strcpy() for your char* 's in the struct .And

ex[0].fname = malloc(sizeof(char) * 128);
//...
strcpy(ex[0].fname , "myString");
//...

Also :

This code snippet looks a bit weird

void delelement(char *delwhat, struct ts *passedex){

  for(i=0; i<sizeof(passedex)-1; i++){
      //...
  }
  return;
}

I think you mean

void delelement(char *delwhat, struct ts *passedex , int array_size)
{
    int i;
    for( i=0 ; i < array_size ; i++ )
    {
         //...

You need to pass the size of the array as an argument. You may find some posts on this link interesting : newbie questions about malloc and sizeof

you are allocating space only for one ts struct

struct ts *ex=(struct ts*)malloc(sizeof(struct ts));

fact that you can access and work fine with the memory after your allocated space it's just pure luck

Next problem:

for(i=0; i<sizeof(passedex)-1; i++){

The sizeof operator does not return the number of element in an array, it returns the number of bytes one passedex occupies. As this is a pointer, it will have a value like 4 or 8, depending on the kind of machine you are using.

In fact, in C, there is no way of knowing how big an array, if all you have is a pointer to it. This means that you have to pass in new parameter informing your routine how big the array is.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM