Thread: Input program with structures

  1. #1
    Registered User
    Join Date
    Jun 2011
    Posts
    19

    Input program with structures

    I am writing a code that is a menu driven program that takes the input several files, arranges them into structures, and links those structures.

    I'm having some difficulty scanning in to the structure though. I can take it from there, I'm just missing this step.

    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<string.h>
    #include<ctype.h>
    #define ST_SCHED_FILE "sched.txt"
    #define COURSE_FILE ""course.txt"
    #define ST_ID_FILE "id.txt"
    void add_class(void);
    void drop_class(void);
    void print_classes(void);
    
    int main(void)
    {
       FILE *fp_schedule, *fp_course, *fp_id;
       int command;
       
       struct student_info
       {
       int student_id;
       char last_name[21];
       char first_name[21];
       char phone_num[11];
       struct class_node *first_node;
       };
       
       struct class_node
       {
         char prefix[7];
         int section;
         int credit_hours;
         struct class_node *next_node;
       };
       
       if((fp_schedule = fopen(ST_SCHED_FILE, "r")) == NULL)
       {
            printf("Schedule file cannot be opened. Press enter to exit.");
            getchar();
            exit(EXIT_FAILURE);
       }
    /*   else
       {
    
       }*/
    
       if((fp_course = fopen(COURSE_FILE, "r")) == NULL)
       {
            printf("Course file cannot be opened. Press enter to exit.");
            getchar();
            exit(EXIT_FAILURE);
       }
    /* else
       {
           
       }*/
      
       if((fp_id = fopen(ST_ID_FILE, "r")) == NULL)
       {
            printf("ID cannot be opened. Press enter to exit.");
            getchar();
            exit(EXIT_FAILURE);
       }
    /*   else
       {
           
       }*/
          
       printf("\t\tRegistry\n\n");
       printf("[0] Add a class to a student schedule\n");
       printf("[1] Drop a class from a student schedule\n");
       printf("[2] List the classes for a given student\n");
       printf("[3] Exit\n");
       command:
       printf("Command: ");
       scanf(" %d", &command);
       
       switch(command)
       {
         case 0:
              add_class();
              printf("Case 0\n");//just debug to make sure it worked properly
              break;
         case 1:
               drop_class();
               printf("Case 1\n");
              break;
         case 2:
               print_classes();
               printf("Case 2\n");
              break;
         case 3:
              return 0;
         default:
              printf("You have entered an invalid entry.\n");
              goto command;//yes, the ancient goto used once again
       }
       
       printf("All files successfully accessed.\n");
       getchar();
       return 0;   
    }
    void add_class(void)
    {
         
    }
    
    void drop_class(void)
    {
         
    }
    
    void print_classes(void)
    {
         
    }
    For the first file has a list of student numbers and classes associated with it, the course prefix and section.

    The course file or second fopen contains the list of classes offered, the section, and credit hours applicable.

    The student id file or last fopen contains the student id, last name, first name, and telephone number. Struct class_node is the pointer that I'm going to use for the linked list to link the student information and the classes the person has.

    fscanf has not worked for me yet. Also I'm not even sure my structures are correct, but it compiles. Thanks in advance for any help. Any links to examples would be helpful as well.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    structs must be declared outside of main, especially if you want to use them in other functions as I suspect you will. Also, struct definitions just define a type; you still need to declare variables of that type if you want to actually have some variables (just like you need to declare variables of type int if you want some ints).

  3. #3
    Registered User
    Join Date
    Jun 2011
    Posts
    19
    Ah, I see! The structs need to have file scope rather than block scope so I can pass them to the other functions. Thanks for the catch.

  4. #4
    Registered User
    Join Date
    Jun 2011
    Posts
    19
    I have an idea.

    Code:
    while(ch = fgetc(fp_schedule) != EOF)
    Since I have the ctype.h header I have access to isalpha(), isdigit(), and other wonderful functions like that. The problem is there are multiple entries per item, so that means my structure itself needs to be an array.

    Hmmm.... Would this be viable?

    Code:
    struct class_node
       {
         char prefix[7];
         int section;
         int credit_hours;
         struct class_node *next_node;
       }Array[num_classes];
    It compiles, but that doesn't necessarily mean it's right.
    [/code]

  5. #5
    Registered User
    Join Date
    May 2011
    Location
    Around 8.3 light-minutes from the Sun
    Posts
    1,949
    Are you making a linked list or just using an array? I am getting a little confused. In your student struct you have this:
    Code:
    struct student_info
       {
       int student_id;
       char last_name[21];
       char first_name[21];
       char phone_num[11];
       struct class_node *first_node;
       };
    And then in your class node you have:
    Code:
    struct class_node
       {
         char prefix[7];
         int section;
         int credit_hours;
         struct class_node *next_node;
       };
    This looks like you originally intended to setup the classes as a linked list from the student structure. Mind you, you can just use arrays instead of linked lists.
    Quote Originally Posted by anduril462 View Post
    Now, please, for the love of all things good and holy, think about what you're doing! Don't just run around willy-nilly, coding like a drunk two-year-old....
    Quote Originally Posted by quzah View Post
    ..... Just don't be surprised when I say you aren't using standard C anymore, and as such,are off in your own little universe that I will completely disregard.
    Warning: Some or all of my posted code may be non-standard and as such should not be used and in no case looked at.

  6. #6
    Registered User
    Join Date
    Jun 2011
    Posts
    19
    For purposes of this code, I am using linked lists. I am taking the data in student info and linking the class info to the student info. For example, if a student is enrolled in a class, I want to link that class with his or her information so that when the user calls the function to print the classes it displays the student info along with the class they are taking.
    Last edited by usernameisvalid; 07-18-2011 at 11:10 PM. Reason: remove error

  7. #7
    Registered User
    Join Date
    May 2011
    Location
    Around 8.3 light-minutes from the Sun
    Posts
    1,949
    Then there is no reason for this:
    Code:
    struct class_node
       {
         char prefix[7];
         int section;
         int credit_hours;
         struct class_node *next_node;
       }Array[num_classes];
    Each class that gets read in then needs to be stored in a new node for your linked list. That is if you have to use linked lists, arrays would be much easier for this problem.

    EDIT: Prelude's Linked List Tutorial is a good place for a quick refresher.
    Last edited by AndrewHunter; 07-18-2011 at 11:15 PM.
    Quote Originally Posted by anduril462 View Post
    Now, please, for the love of all things good and holy, think about what you're doing! Don't just run around willy-nilly, coding like a drunk two-year-old....
    Quote Originally Posted by quzah View Post
    ..... Just don't be surprised when I say you aren't using standard C anymore, and as such,are off in your own little universe that I will completely disregard.
    Warning: Some or all of my posted code may be non-standard and as such should not be used and in no case looked at.

  8. #8
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    I would either, add the students more detailed data, into the student struct, directly, as a struct member,

    or

    I'd nest the more detailed students data, as a struct inside the student struct.

    Then make an array of the structs. Of the two, I like the simpler first one, unless you know it's unsuitable for some reason.

    You read in data into struct members, the same way you read in any data type the member has, unless you are using all fixed fields, and want to go the binary file fread, and fwrite() way.

    I'd suggest the straight forward way:

    Code:
    fscanf(myFilePointer, "%s %d", students[i].name, &student[i].age);
    //etc.

    God gave Adam and Eve a linked list as punishment, when he ran 'em out of the Garden of Eden, you know that, right?

    Linked lists --> phooey! Waste of time when you make 'em, and waste of time when you have to run programs with em.

  9. #9
    Registered User
    Join Date
    Jun 2011
    Posts
    19
    Unfortunately, I have to use linked lists. I'm currently working on the part that reads in the text file for the first fopen statement. I understand what I want it to do, but am having a difficult time implementing it.

    I walked it through on paper and know the steps I need to take for this part of the code.

    1: Read four digit integer. Copy or scan integer into student_id.
    2: Encounter space character. Ignore.
    3: Encounter string and read in to prefix[7], null terminate string, then read space character and ignore.
    4: Encounter single digit. Copy or scan into credit_hours.
    5: Encounter new line character and repeat scanning in each entry until EOF.

    This may be a dumb question, but if this code is written as I have listed it will it actually have enough memory allocated to store more than one instance of each variable, or would the code simply keep copying over every new instance of each variable?

  10. #10
    Registered User
    Join Date
    May 2011
    Location
    Around 8.3 light-minutes from the Sun
    Posts
    1,949
    Just use a fgets/sscanf pair to read an entire line from the file (fgets) and then parse it out into your structure (sscanf).

    That is why you always check the return value of malloc(). If the program runs out of the memory assigned to it malloc will fail and return a NULL pointer. As for the concern of overwriting memory that is not quite how program memory is setup so don't worry about that.

    Random access files would be the way to go if your database gets to large to hold it all in memory at the same time.
    Quote Originally Posted by anduril462 View Post
    Now, please, for the love of all things good and holy, think about what you're doing! Don't just run around willy-nilly, coding like a drunk two-year-old....
    Quote Originally Posted by quzah View Post
    ..... Just don't be surprised when I say you aren't using standard C anymore, and as such,are off in your own little universe that I will completely disregard.
    Warning: Some or all of my posted code may be non-standard and as such should not be used and in no case looked at.

  11. #11
    Registered User
    Join Date
    Jun 2011
    Posts
    19
    I went a slightly different route reading in character by character.

    Code:
    else
       {
          while((ch = fgetc(fp_schedule)) != EOF)
          {
             if(isdigit(ch))
             {
                structArray[i].student_id = ch;
                in_stid = 1;
             }
             if((ch == ' ')&&(in_stid == 1))
             {
                 i++;   
                 in_stid = 0;
             }
          }
       }

    Code:
    struct student_info
       {
       int student_id;
       char last_name[21];
       char first_name[21];
       char phone_num[11];
       struct class_node *first_node;
       }structArray[LEN];
    I also modified struct. LEN = 100.

    It was crashing, but I fixed that, and now when I print structArray[i].student_id it returns 50...

  12. #12
    Registered User
    Join Date
    May 2011
    Location
    Around 8.3 light-minutes from the Sun
    Posts
    1,949
    It is because you are reading in a char, not an int. This really is done much simpler with fgets/sscanf. But with your solution you need to use:
    Code:
    structArray[i].student_id = atoi(ch);
    to change the char to an int. Here is a quick example.
    Quote Originally Posted by anduril462 View Post
    Now, please, for the love of all things good and holy, think about what you're doing! Don't just run around willy-nilly, coding like a drunk two-year-old....
    Quote Originally Posted by quzah View Post
    ..... Just don't be surprised when I say you aren't using standard C anymore, and as such,are off in your own little universe that I will completely disregard.
    Warning: Some or all of my posted code may be non-standard and as such should not be used and in no case looked at.

  13. #13
    Registered User
    Join Date
    Jun 2011
    Posts
    19
    Ok, I want to make this code run as smoothly as possible so I will look more into fgets/sscanf when I wake up. Thank you for your help so far.

    Before I go, I do have one more question.

    In the link you posted for atoi, it shows an example of fgets. I understand that the second argument is the length of the array and the third is the input file pointer. The first argument is the name of the array. Would that make the first argument for my fgets structArray?

  14. #14
    Registered User
    Join Date
    May 2011
    Location
    Around 8.3 light-minutes from the Sun
    Posts
    1,949
    No, unfortunately that is not how you would use fgets. Here is a quick link. Basically you would:
    1.Open your file
    2. Use fgets to read an entire line from your file into a temp buffer(a char array)
    3. Use sscanf to read from that buffer to your elements in your structure.
    4. repeat until fgets reaches EOF
    5. close file

    EDIT: I'm not sure what your original LEN was but if you intend to have a large number of these student structs I would reccomend allocating the struct array with malloc to ensure you don't blow right past your stack limit, typically 1MB. This could have been why the program crashed.
    Last edited by AndrewHunter; 07-19-2011 at 01:38 AM.
    Quote Originally Posted by anduril462 View Post
    Now, please, for the love of all things good and holy, think about what you're doing! Don't just run around willy-nilly, coding like a drunk two-year-old....
    Quote Originally Posted by quzah View Post
    ..... Just don't be surprised when I say you aren't using standard C anymore, and as such,are off in your own little universe that I will completely disregard.
    Warning: Some or all of my posted code may be non-standard and as such should not be used and in no case looked at.

  15. #15
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by usernameisvalid View Post
    I went a slightly different route reading in character by character.

    Code:
    else
       {
          while((ch = fgetc(fp_schedule)) != EOF)
          {
             if(isdigit(ch))
             {
                structArray[i].student_id = ch;
                in_stid = 1;
             }
             if((ch == ' ')&&(in_stid == 1))
             {
                 i++;   
                 in_stid = 0;
             }
          }
       }
    I'm going to side with Andrew on this one... character by character is probably the worst way to do this...

    If (for example) your file is a series of lines like <id> <first> <last> <phone> you can simply do this...
    Code:
    char buf[256];
    
    while ( fgets(buf,255,pFile) )
      { sscanf ( buf, "%d" %s %s %s",new->id, new->first_name, new->last_name,new->phone_num); }
    Note: This is for concept only, you will need to flesh it out with some error trapping and field size limits...

    There have been numerous discussions on these forums about the best way to "get stuff" and far as I can tell this is the best of the bunch. If you were reading the keyboard you could substitute stdin for pFile and still use the same method.

    @Andrew: I was thinking a brief example might be helpful here.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C++: Help with program using array structures
    By We'reGeeks in forum C++ Programming
    Replies: 5
    Last Post: 11-29-2010, 01:47 AM
  2. payroll program using structures
    By tiger6425 in forum C Programming
    Replies: 3
    Last Post: 07-24-2010, 11:38 PM
  3. input from text using structures
    By ehj3000 in forum C Programming
    Replies: 12
    Last Post: 09-16-2005, 10:30 PM
  4. Nested Structures - User Input
    By shazg2000 in forum C Programming
    Replies: 2
    Last Post: 01-09-2005, 10:53 AM
  5. Input output with structures
    By barim in forum C Programming
    Replies: 10
    Last Post: 04-27-2004, 08:00 PM