Thread: C passing an array of struct to delete one problems (from a newbie)

  1. #16
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by phantomotap View Post
    You know what, I should be ashamed. I knew that you weren't as experienced as you claim.
    Do try not to be a complete idiot.

    I'll take bets that you've never worked with random access files... not even as a learning experience.

    Tell me one good reason why I should have to write all this extra code when I can simply copy the string data into a buffer inside the struct and write the whole thing to disk?

    Here's a little learning experience for you...
    Write an inventory program capable of accessing/maintaining a 1gb+ inventory data file with over 400,000 entries in it... Do you really think you're going to load that whole thing into a linked list and work with string literals?

    CLUE TIME!

  2. #17
    Registered User
    Join Date
    Mar 2011
    Posts
    8
    Quote Originally Posted by phantomotap View Post
    ^_^

    Are you writing a download manager?

    Anyway, considering the state of your program, I'd say you are a long way from managing whatever it is you are doing. Why not grab a C implementation of a linked list and see if you can follow it? Better yet, why not write one yourself first because that will surely help with your memory management problems.

    In any event, a tree indexed with the most relevant data is probably your best bet.

    Soma
    Well yes an no, kinda.

    I'm watching the packets (all of them). Now packets destined for a certain ports are the ones that I'm after. In a simple case let's say IM.

    What I have working so far...

    I get each packet. If tcp AND that port, process it. In processing I already have everything for capturing and logging to disk the "conversation"... no problems there. It knows how/where to get the username from/to, how to distinguish that it is a properly constructed im packet, etc.

    Now usera sends userb a file. I see that, I have that already. User b accepts the file. See it, got it. Now what I want to do is when userb accepts, It will have a certain signature and filename that I will see in the originating request packet for the file. I store this signature and filename and watch for it. Working fine. Now I see that request packet, and parsing it, I know where the data is going (destination port) and what size it is expecting to get.

    I want to store all that and be watching for it in the main loop. Basically I want this array, or list, or whatever is the best way to rack this information to be checked back at the beginning.

    So I get a packet - I check this watch list. If nothing in the list - continue. If something in the watch list - check that destination port. Did I find a match? Yes - ok - run a different packet_processing function that is basically going to take the data element from this packet, and append it to a temporary file of the filename stored (actually the md5 hash of the origin datetime request+filename... in case multiple files of same filename are sent). Now in this second process (writing data to the file) - at the end of each receipt - stat the file... is it correct? Do I have all the data expected? Yes? Move the file to a processing directory. Remove that port, filename, etc from the watch list.

  3. #18
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by snowolfe View Post
    Currently looking into linked list.
    Once it comes to a point that the filesize is >= the size stored in the global tracking, it can move the file, name it accordingly, and then remove that entry from tracking.

    I hope that's not too much gibberish to follow :P

    And thanks for the help so far. Like I said - it's been yeeeeaaaaarrrrrsss for me.
    You could use a linked list here but I do not think it is very necessary, esp. since it sounds like you are not going to be adding to the list, just removing stuff from it.

    You can use a pointer array:
    Code:
    struct ts *eg[20];
    Now you malloc and assign the array. When you want to "remove" an entry, free() it and set the pointer to NULL:

    Code:
    free(eg[i]);
    eg[i] = NULL;
    In your loop, skip null pointers:

    Code:
    for (i = 0; i < num_of_structs; i++) {
           if (!eg[i]) continue;   // pointer is NULL
           [...]
    }
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  4. #19
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by snowolfe View Post
    Well yes an no, kinda.
    Just so you know snowolfe ... I've just put that total idiot Phantomotap in my ignore list.

    I'm going to bow out of this and let you continue with the others.

  5. #20
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    *shrug*

    Well, it depends on how much traffic you may process, but yea, you are almost certainly better off with a tree indexed on the port number.

    The point I was trying to make to you though, is that this isn't trivial and you are much better served starting with something simpler until and build up to modifying your program.

    Soma

  6. #21
    Registered User
    Join Date
    Mar 2011
    Posts
    8
    Ok - how's this look?

    (Seems to work the way I need it)

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct ts{
      char *fname;
      char *lname;
      char *fingers;
      char *toes;
      struct ts *next;
    }TS;
    
    TS *mainrec=NULL;
    
    void addone(char *, char *, char *, char *);
    void printout();
    void findandprint(char *, char *);
    
    int delone(char *, char*);
    
    int main(int argc, char **argv){
      
      addone("joe", "bob", "1", "1");
      printout();
    
      addone("bobby", "sue", "2", "2");
      printout();
    
      addone("blah", "blah", "3", "3");
      printout();
    
      addone("bobby", "joe", "4", "4");
      printout();
    
      addone("bobby", "hill", "5", "5");
      printout();
    
      if(delone("joe", "bob")){
        printf("Did not find - error\n\n");
      }
      else{
        printf("found and deleted\n\n");
      }
    
      if(delone("joey", "bob")){
        printf("Did not find - error\n\n");
      }
      else{
        printf("found and deleted\n\n");
      }
    
      printout();
    
      if(delone("bobby", "hill")){
        printf("Did not find - error\n\n");
      }
      else{
        printf("found and deleted\n\n");
      }
    
      printout();
    
      findandprint("blah", "blah");  
    
      return 0;
    }
    
    void addone(char *pfname, char *plname, char *pfingers, char *ptoes){
      TS *trec;
      trec=(TS *)malloc(sizeof(TS));
      trec->fname=pfname;
      trec->lname=plname;
      trec->fingers=pfingers;
      trec->toes=ptoes;
    
      if(mainrec==NULL){
        mainrec=trec;
        mainrec->next=NULL;
      }
      else{
        trec->next=mainrec;
        mainrec=trec;
      }
    }
    
    int delone(char *pfname, char *plname){
      TS *tprev, *tcur;
    
      tcur=mainrec;
    
      while(tcur!=NULL){
        if(tcur->fname==pfname && tcur->lname==plname){
          if(tcur==mainrec){
            mainrec=tcur->next;
            free(tcur);
            return 0;
          }
          else{
            tprev->next=tcur->next;
            free(tcur);
            return 0;
          }
        }
        else{
          tprev=tcur;
          tcur=tcur->next;
        }
      }
    
      return 1;
    }
    
    void printout(){
      TS *trec;
    
      trec=mainrec;
    
      if(trec==NULL){
        return;
      }
      else{
        printf("What we have so far\n");
        printf("___________________\n");
    
        while(trec!=NULL){
          printf("fname: %s\n", trec->fname);
          printf("lname: %s\n", trec->lname);
          printf("fingers: %s\n", trec->fingers);
          printf("toes: %s\n\n", trec->toes);
          trec=trec->next;
        }
      }
      return;
    }
    
    void findandprint(char *pfname, char *plname){
      TS *trec;
    
      trec=mainrec;
    
      if(trec==NULL){
        return;
      }
      else{
        while(trec!=NULL){
          if(trec->fname==pfname && trec->lname==plname){
            printf("found record for fname:%s, lname:%s\n", pfname, plname);
            printf("___________________________________\n");
            printf("fname: %s\n", trec->fname);
            printf("lname: %s\n", trec->lname);
            printf("fingers: %s\n", trec->fingers);
            printf("toes: %s\n\n", trec->toes);
            return;
           }
          trec=trec->next;
        }
      }
      return;
    }

  7. #22
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Still assigning string literals I see....

    Ok, something to ponder... Joe has changed his name to John, which you have in NewName[30] and now you need to update that record...

  8. #23
    Registered User
    Join Date
    Mar 2011
    Posts
    8
    Quote Originally Posted by CommonTater View Post
    Still assigning string literals I see....

    Ok, something to ponder... Joe has changed his name to John, which you have in NewName[30] and now you need to update that record...
    Just doing the literals for working with it - actually are already char *'s in the function that will be calling the add/delete/find.

    Was not actually concerned with anything changing. Basically I will be tracking a service, time, destination port, filename. None of that is going to change, so all I was looking for was basically to add onto the stack, or remove off the stack and find in the stack.

    But, in interest of learning, couldn't I simply create a proc that would take arguments such as

    Code:
    TS *replace(char *oldfname, char *oldlname, char *newfname, char *newlname){
      TS *trec;
        
    
      trec=mainrec;
      if(trec==NULL){
        return trec;
      }
      else{
        while(trec!=NULL){
          if(trec->fname==oldfname && trec->lname==oldlname){
            trec->fname=newfname;
            trec->lname=newlname;
            return trec;
           }
          trec=trec->next;
        }
      }
      return trec;
    }

  9. #24
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    In the case that all you are doing is reassigning pointers, yes something like that could be made to work. But you do have to be aware that a process such as that is loaded with pitfalls that may not be immediately apparent...

    Code:
    char* GetName(void)
      { char name[20];
         printf("Enter your first name  : ");
         scanf("%19s",name);
         printf("\n|%s|\n", name);   // all is well so far?
         return name; }
    
    int main (void)
      {  char *Name1;
          char *Name2;
          Name1 = GetName();   // all perfectly logical, right?
          Name2 = GetName();
          printf("%s %s",Name1,Name2);  // Ummm... what happened?
          return 0; }
    Last edited by CommonTater; 03-30-2011 at 10:40 AM.

  10. #25
    Registered User
    Join Date
    Mar 2011
    Posts
    8
    Quote Originally Posted by CommonTater View Post
    In the case that all you are doing is reassigning pointers, yes something like that could be made to work. But you do have to be aware that a process such as that is loaded with pitfalls that may not be immediately apparent...

    Code:
    char* GetName(void)
      { char name[20];
         printf("Enter your first name  : ");
         scanf("%19s",name);
         printf("\n|%s|\n", name);   // all is well so far?
         return name; }
    
    int main (void)
      {  char *Name1;
          char *Name2;
          Name1 = GetName();   // all perfectly logical, right?
          Name2 = GetName();
          printf("%s %s",Name1,Name2);  // Ummm... what happened?
          return 0; }
    instead of return name i'm thinking two different possibilities

    return strdup(name)

    or

    add in

    char *ret;
    ret=(char *)malloc(sizeof(name));
    strcpy(ret, name);

    return ret;

    tried both those and they work... kinda understand returning the strdup(name), but foggy on why if i create another local var *ret, and either strdup, or alloc and strcpy and return it, that this works.
    Last edited by snowolfe; 03-30-2011 at 11:00 AM.

  11. #26
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by snowolfe View Post
    instead of return name i'm thinking two different possibilities

    return strdup(name)

    or

    add in
    Code:
    char *ret;
    ret=(char *)malloc(sizeof(name));
    strcpy(ret, name);
    return ret;
    All this to avoid using char[20]; (or such) in a struct? Really...
    Watch this...
    Code:
    // the struct
    typedef struct t_User
       { char Name1[20];
         char Name2[20];
         // whatever else you need 
        } User;
    
    // get names
    void GetName(char *Name)
      { printf("Enter your name  : ");
         scanf("%19s", Name); }
    
    int main (void)
       {  User Users;
           GetName(Users.Name1);
           GetName(Users.Name2);
           printf("%s %s\n", Users.Name1,Users.Name2); 
           return 0; }
    See how much easier that is? And it works...

    In your code where you have something in a string just use strcpy();
    Code:
    strcpy(users.name1,NewName);
    Over my time dabbling in C I've probably tried a dozen different "bright idea" ways of assigning strings across the equals sign... exactly none of them worked.
    Last edited by CommonTater; 03-30-2011 at 11:02 AM.

  12. #27
    Registered User
    Join Date
    Mar 2011
    Posts
    8
    Quote Originally Posted by CommonTater View Post
    All this to avoid using char[20]; (or such) in a struct? Really...
    Watch this...
    Code:
    // the struct
    typedef struct t_User
       { char Name1[20];
         char Name2[20];
         // whatever else you need 
        } User;
    
    // get names
    void GetName(char *Name)
      { printf("Enter your name  : ");
         scanf("%19s", Name); }
    
    int main (void)
       {  User Users;
           GetName(Users.Name1);
           GetName(Users.Name2);
           printf("%s %s\n", Users.Name1,Users.Name2); 
           return 0; }
    See how much easier that is? And it works...

    In your code where you have something in a string just use strcpy();
    Code:
    strcpy(users.name1,NewName);
    Over my time dabbling in C I've probably tried a dozen different "bright idea" ways of assigning strings across the equals sign... exactly none of them worked.

    Thanks much for all the help... like I said - been years and now re-learning. I'm used to perl and php where I can do simple assignments and not worry so much with reference to, address, pointers, etc (mostly web programming).

  13. #28
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    Quote Originally Posted by CommonTater View Post
    See how much easier that is? And it works...
    It works if the user's name is less than 20 characters and doesn't contain any spaces (Eddie Van Halen would not approve!).
    bit∙hub [bit-huhb] n. A source and destination for information.

  14. #29
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by snowolfe View Post
    Thanks much for all the help... like I said - been years and now re-learning. I'm used to perl and php where I can do simple assignments and not worry so much with reference to, address, pointers, etc (mostly web programming).
    No worries... helping is one of the best ways to learn!

    C isn't a baby-sitter language. If you want something to happen, you have to make it happen.
    I'm fond of describing it as a "totally obedient idiot" that you have to tell everything in minute steps and, if you tell it to do the wrong thing, it will do the wrong thing without complaint or hesitation.

    C has no native string type. Forget it, it's just not there and you can't fake it. What we call strings are actually arrays of characters (or wide characters, for unicode). The only difference between these arrays and numerical arrays is that the library functions tag the end of the used buffer with a 0 (hense the term "null terminated"). By cooperation of the library functions --not the compiler-- we get to play with pseudo-strings in arrays. This means that none of C's operators ( + - < > = etc) will work on strings. It's all up to the library's functions...

    Yes, that's very different than Perl or PHP, and half the other programming languages on the planet... but it is what it is and we get to work within it.

    The C Library Reference Guide
    Last edited by CommonTater; 03-30-2011 at 11:48 AM. Reason: edit is marked

  15. #30
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    I just want to point out that the only reason assignment does not work with C strings is because C strings are a particular kind of array. You can't assign a C string because you can't assign arrays.

    You can use initialization, though.
    Code:
    char username[] = "John Doe";
    Perfectly legal, but not useful at any other time.

    There is no real trick to get string assignment, so don't waste your time. You have to use something like strncpy. Or strncat even: As long as dest[0] is '\0' you will always get a C string in return.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Help with delete - Binary search tree
    By lazyme in forum C Programming
    Replies: 10
    Last Post: 03-21-2010, 12:19 PM
  2. Struct Char Array Problems
    By RMDan in forum C Programming
    Replies: 5
    Last Post: 06-18-2009, 07:16 PM
  3. Replies: 1
    Last Post: 12-03-2008, 03:10 AM
  4. Help with an Array
    By omalleys in forum C Programming
    Replies: 1
    Last Post: 07-01-2002, 08:31 AM
  5. Hi, could someone help me with arrays?
    By goodn in forum C Programming
    Replies: 20
    Last Post: 10-18-2001, 09:48 AM

Tags for this Thread