Thread: Help doing an e-mail program in c...

  1. #46
    Guest Sebastiani's Avatar
    Join Date
    Aug 2001
    Location
    Waterloo, Texas
    Posts
    5,708
    well, the way things are set up you can't really delete items very easily (since you're using a single structure as opposed to an array, linked list, etc.). to be honest, there's too much wrong with the code to come up with a simple fix - I'm afraid you're on your own there. not sure if this helps any but perhaps looking at a similar program might be useful.

    Code:
    struct info {
      char data[MAX+1];
      struct info * next;
     };
    
    struct info * newInfo(const char * buffer) {
     struct info * info = (struct info*)malloc(sizeof(struct info));
     strncpy(info->data, buffer, MAX);
     info->next = NULL;
     return info;
     } 
     
    void deleteInfoList(struct info ** list) {
     struct info * goner, * iterator = *list;
     while(iterator != NULL) {
      goner = iterator;
      iterator = iterator->next;
      free(goner);
      }
     *list = NULL;  
     }  
     
    void readInfo(const char * filename, struct info ** list) {
     struct info * info, * iterator;
     char buffer[MAX+1];
     FILE * fp = fopen(filename, "r");
     if(fp != NULL) {
      deleteInfoList(list);
      while(fgets(buffer, MAX, fp)) {
       info = newInfo(buffer);
       if(*list == NULL) {
        *list = iterator = info;
        } else {
        iterator->next = info;
        iterator = iterator->next;
        }    
       }
      }
     }
     
    void writeInfo(const char * filename, struct info * list) {
     FILE * fp = fopen(filename, "w");
     if(fp != NULL) {
      chsize(fileno(fp), 0);
      while(list != NULL) {
       fprintf(fp, "%s", list->data);
       list = list->next;
       }
      }
     }
     
    void printInfo(struct info * list) {
     int index = 1;
     printf(" ***** Database *****\n");
     while(list != NULL) {
      printf(" %d) %s", index++, list->data);
      list = list->next;
      }
     printf("\n"); 
     } 
     
    void deleteInfo(struct info ** list) {
     char temp[MAX];
     unsigned which, index = 1;
     struct info * iterator, * prev = NULL;
     printf(" Enter the item # to delete: ");
     which = atoi(fgets(temp, MAX, stdin));
     for(iterator = *list; iterator != NULL; prev = iterator, iterator = iterator->next, ++index) {
      if(index == which) {
       if(prev != NULL) {
        prev->next = iterator->next;
        } else {
        *list = iterator->next; 
        } 
       free(iterator);
       break; 
       }
      } 
     } 
     
    void addInfo(struct info ** list) {
     char buffer[MAX+1];
     struct info * info, * iterator = *list;
     printf(" Enter the new data: ");
     fgets(buffer, MAX, stdin);
     info = newInfo(buffer);
     if(*list == NULL) {
      *list = info;
      } else {
      while(iterator->next) {
       iterator = iterator->next;
       }  
      iterator->next = info; 
      } 
     }  
     
    int menu(void) {
     int ch;
     char buffer[MAX+1];
      printf(
      " ***** Main Menu *****\n"
      " a) Add Info\n"
      " d) Delete Info\n"
      " p) Print Info\n"
      " x) Exit\n" 
      );
     ch = tolower(fgets(buffer, MAX, stdin)[0]); 
     printf("\n"); 
     return ch;
     } 
     
    int main() {
     const char * file = "info.txt";
     struct info * list = NULL;
     int choice;
     readInfo(file, &list);
     while((choice = menu()) != 'x') {
      switch(choice) {
       case 'p' : 
        printInfo(list); 
        break;
       case 'a' : 
        addInfo(&list);
        writeInfo(file, list);
        break;
       case 'd' :
        deleteInfo(&list);
        writeInfo(file, list);
        break;
       default:
        printf("Invalid Selection\n");   
       }
      }
     return 0; 
     }
    Code:
    #include <cmath>
    #include <complex>
    bool euler_flip(bool value)
    {
        return std::pow
        (
            std::complex<float>(std::exp(1.0)), 
            std::complex<float>(0, 1) 
            * std::complex<float>(std::atan(1.0)
            *(1 << (value + 2)))
        ).real() < 0;
    }

  2. #47
    Registered User
    Join Date
    Dec 2004
    Posts
    45
    I'm now going to try this program you gave me to see what I can do but could you just help me with the problem I'm having passing from the file to a struct... It is eliminating some letters...when passing from the file to the struct it goes from this:
    From: bla bla
    To: bla bla
    Subject:bla bla
    Message: bla bla

    (to this)
    From: bla bla
    o: bla bla
    bject:bla bla
    sage: bla bla

  3. #48
    Quote Originally Posted by Tyler_Durden
    progmail.h
    <...>
    Why do you have two identical structure definitions ? A mail is a mail.
    Unless you have planned some divergent evolution, you can remove the MAILR thing.

    By the way, you don't need the tags.

    One more detail, I suggest that the identifier used by the guard (here PROGMAIL_H_INCLUDED) begin with H_, hence H_PROGMAIL_xxx. The reason is that is prevents from using an identifier commencing with E. Those are reserved by the language for error numbers (ERANGE, EDOM etc.).

    Try this (and fix your code consequently)

    Code:
    #ifndef H_PROGMAIL
    #define H_PROGMAIL
    
    /* progmail.h */
    
    typedef struct
    {
      char from[120];
      char to[120];
      char sub[120];
      char msg[120];
    } MAIL;
    
    void leficheiro(MAIL *m);
    void comandom(MAIL *m);
    void comandoC(MAIL *m);
    void comandoL(MAIL *m);
    #endif
    [EDIT]
    I have reread the thread, and I have seen that you have posted this
    Code:
    #define MAX 120
    
    typedef struct mailr{
      char from[MAX+1];
      char to[MAX+1];
      char sub[MAX+1];
      char msg[MAX+1];
    }MAILR;
    Why was there a copy in 'progmail.h'

    Ther are 2 design rules that have to be printed into you brain:

    - Definitions shall be unique
    - An implementation shll include it's interface file

    This means, by example, that in "comandoC.c", you should have

    #include "progmail.h"

    hence a double definition for MAILR. Remove it.

    That said, I think the way the definition of MAILR was made in "comandoC.c" was more clever than in "progmail.h". Hence, I suggest this new version of progmail.h:
    Code:
    #ifndef H_PROGMAIL
    #define H_PROGMAIL
    
    /* progmail.h */
    
    #define MAX 120
    
    typedef struct
    {
      char from[MAX+1];
      char to[MAX+1];
      char sub[MAX+1];
      char msg[MAX+1];
    }MAIL;
    
    void leficheiro(MAIL *m);
    void comandom(MAIL *m);
    void comandoC(MAIL *m);
    void comandoL(MAIL *m);
    #endif
    Last edited by Emmanuel Delaha; 12-31-2004 at 10:47 AM. Reason: Amendment
    Emmanuel Delahaye

    "C is a sharp tool"

  4. #49
    Registered User
    Join Date
    Dec 2004
    Posts
    45
    thanks for your tips ... =)
    I need to different structs because I have to deal differently with the mails that are input, and the ones read from the file....
    I only have a question.I've been able to do the leficheiro.c, that is the command that reads the file into a struct but it only works with one e-mail.. I need it to be able to read more e-mails (10, for example) and give them different names and variables..for example mail1, would have sub1,to1,from1,msg1 ..mail 2 would have to2,from2,subject2,etc... If I can do that then I will be able to present the info in the screen , and delete mails, etc...coudl you help me with this task?
    my leficheiro.c is like this until now:
    Code:
    #include <stdio.h>
    #include <string.h>
    #include "progmail.h"
    
    void leficheiro(MAILR *ptr)
    {
      FILE *fp;
    
    fp = fopen("mail.txt","r");
    
     fgets(ptr->to,50,fp);
     fgets(ptr->from,50,fp);
     fgets(ptr->sub,50,fp);
     fgets(ptr->msg,50,fp);
     fclose(fp);
    
    }
    thanks a lot and sorry for the bother.

    EDIT - I knwo I need to make a loop and all that, and I tried, but can't figure out how to give the different names to each mail's variables..

  5. #50
    Registered User caroundw5h's Avatar
    Join Date
    Oct 2003
    Posts
    751
    if you want to have more than one struct to use. simply make an array of structs. Say you have a structure.
    Code:
    #define NUM[100];
    struct mail{
    char person[NUM];
    char name[NUM];
    char addy[NUM];
    char whatever[NUM];
    };
    
    /*make an arrray of 100 structs. */
    struct mail MAILNUM[NUM];
    
    
    /*to call each field in the struct */
    MAILNUM[1].person = "harry";
    MAILNUM[2].person = "tyler";
    
    etc...

    also
    From: bla bla
    To: bla bla
    Subject:bla bla
    Message: bla bla

    (to this)
    From: bla bla line 0
    o: bla blap line 1
    bject:bla bla line 2
    sage: bla bla line 3
    do you notice a pattern here? for each call to fgets it seems to print from that linenum.
    ex: line 0 prints from 0, line 1 prints from 1 etc...

    [edit] I notice you were up early in the morning doing this. I hope you get a decent grade. if you're really interested in learing C. Take a look here. you can get your feet wet. [/edit]
    Last edited by caroundw5h; 12-31-2004 at 12:12 PM.
    Warning: Opinions subject to change without notice

    The C Library Reference Guide
    Understand the fundamentals
    Then have some more fun

  6. #51
    Registered User
    Join Date
    Dec 2004
    Posts
    45
    Yes, I've been doing this intensively but I don't know if it is enough to get a positive grade =\
    Now I will implement this technique to have numerous arrays to see if I can get what I want..hehe....
    appreciated...

  7. #52
    Quote Originally Posted by Tyler_Durden
    Now I will implement this technique to have numerous arrays to see if
    It's not 'numerous arrays'. It's ONE array of numerous structures.
    Emmanuel Delahaye

    "C is a sharp tool"

  8. #53
    Registered User
    Join Date
    Dec 2004
    Posts
    45
    Yes...my mistake..
    I tried to use the function that way and made a progmail.h like this:
    Code:
    #ifndef PROGMAIL_H_INCLUDED
    #define PROGMAIL_H_INCLUDED
    #define MAX 120
    #define NUM 20
    
    typedef struct mail
    {
      char from[MAX+1];
      char to[MAX+1];
      char sub[MAX+1];
      char msg[MAX+1];
    } MAIL;
    
    typedef struct mailr
    {
      char from[MAX+1];
      char to[MAX+1];
      char sub[MAX+1];
      char msg[MAX+1];
      char spc[MAX+1];
    }MAILR[NUM];
    
    
    void leficheiro(MAILR[]);
    void comandom(MAIL *m);
    void comandoC(MAIL *m);
    void comandoh(MAILR[]);
    void comandoL(MAIL *m);
    #endif
    and a leficheiro.c like this:
    Code:
    #include <stdio.h>
    #include <string.h>
    #include "progmail.h"
    
    void leficheiro(MAILR *ptr)
    {
      FILE *fp;
    
    fp = fopen("mail.txt","r");
    
     fgets("MAILR[0].to",50,fp);
     fgets("MAILR[0].from",50,fp);
     fgets("MAILR[0].sub",50,fp);
     fgets("MAILR[0].msg",50,fp);
    
     fclose(fp);
    
    }
    now, in main I call the function le ficheiro this way:
    leficheiro(&mailr);

    but when I run the program I get segmentation fault..it must be a simple change to get the error out but I can't find it.... Right now I only want to test it with one mail, then I'll have to make the loops to MAILR[i], to be able to get the structs....

  9. #54
    Quote Originally Posted by Tyler_Durden
    Code:
    #ifndef PROGMAIL_H_INCLUDED
    #define PROGMAIL_H_INCLUDED
    #define MAX 120
    #define NUM 20
    
    typedef struct mail
    {
      char from[MAX+1];
      char to[MAX+1];
      char sub[MAX+1];
      char msg[MAX+1];
    } MAIL;
    
    typedef struct mailr
    {
      char from[MAX+1];
      char to[MAX+1];
      char sub[MAX+1];
      char msg[MAX+1];
      char spc[MAX+1];
    }MAILR[NUM];
    #endif
    Redundent. Remember my quote:
    - Definitions shall be unique
    Better to do that:
    Code:
    #ifndef PROGMAIL_H_INCLUDED
    #define PROGMAIL_H_INCLUDED
    #define MAX 120
    #define NUM 20
    
    typedef struct
    {
      char from[MAX+1];
      char to[MAX+1];
      char sub[MAX+1];
      char msg[MAX+1];
    } MAIL;
    
    typedef struct
    {
       MAIL mail;
    }MAILR[NUM];
    #endif
    And for your memory problems, be careful that MAILR is a big type. Could be too big for local memory.

    How is defined the MAILR type object ?
    Last edited by Emmanuel Delaha; 12-31-2004 at 01:53 PM.
    Emmanuel Delahaye

    "C is a sharp tool"

  10. #55
    Registered User
    Join Date
    Dec 2004
    Posts
    45
    I still get segmentation faulkt when trying to run leficheiro, when progmail.c starts... I changed my progmail.h like you said...
    help, pls =)

    Happy 2005!


    EDIT - I really need your help, sorry for asking this much but I have to deliver the program after tomorrow...then I won't bug you anymore
    Last edited by Tyler_Durden; 01-01-2005 at 01:57 PM.

  11. #56
    Registered User
    Join Date
    Dec 2004
    Posts
    45
    Quote Originally Posted by Emmanuel Delaha
    This is the expected behaviour when you use fgets() 'rawly'. It also 'catches' the '\n'. All you have to do is to 'clean-up' the string once you have got it (actually, fgets() is a 'line reader')

    The usual and minimum trick is the "search'n kill" procedure:
    Code:
    char *p = strchr(line, '\n'); /* needs <string.h> */
    
    if (p != NULL)
    {
       *p = 0;
    }
    Of course, it's more clever to stick this code in some function...
    I tried this piece of code substituting the "line" with "ptr->from", for example, but the problem is still there...I put it in the comandom.c, which gets the info and puts it in the mail.txt...

  12. #57
    Registered User
    Join Date
    Dec 2004
    Posts
    45
    Bump...
    sorry but I only wanted help solving the segmentation fault error, please...I won't ask you nothing more, really

  13. #58
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,656
    It's probably a good idea to ZIP all your source files and header files, then attach that single zip file to a post.

  14. #59
    Registered User
    Join Date
    Dec 2004
    Posts
    45
    so there it is..
    the extension is ".c" but rename it to ".zip" and all the files are there.. I dunno if it will give some errors that I didn't have because last time I worked in the program I forgot to save, so I made the alterations now in windows without testing....

  15. #60
    Registered User
    Join Date
    Dec 2004
    Posts
    45
    Bump...

    Just this last help, guys... I only need to solve the segmentation fault error, and the rest is easy...the program is in the post abose, and the segmentation fault error happens when main trys to run leficheiro...

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Issue with program that's calling a function and has a loop
    By tigerfansince84 in forum C++ Programming
    Replies: 9
    Last Post: 11-12-2008, 01:38 PM
  2. Need help with a program, theres something in it for you
    By engstudent363 in forum C Programming
    Replies: 1
    Last Post: 02-29-2008, 01:41 PM
  3. Replies: 4
    Last Post: 02-21-2008, 10:39 AM
  4. My program, anyhelp
    By @licomb in forum C Programming
    Replies: 14
    Last Post: 08-14-2001, 10:04 PM