Thread: file i/o dilemma

  1. #1
    Registered User
    Join Date
    Oct 2008
    Posts
    21

    file i/o dilemma

    okay so i am now writing code for an assignment where i have to write to a binary file a report for a teacher to use for a class where it will write to the file in this format:

    idNumber Name gender classlvl ProgrammingScores TestScores
    111111111 last, first M 11 00 00 00 00 00 00

    for any amount of students and with the only thing is that i can only use 44 bytes per student meaning a stucture with members all type char.....

    the other thing is that i have to have each function on it's own file, so making a header file and compiling the .o files of the functions with the main function that will be using the functions to do things....

    my problem is so far with the deleting and adding scores....now i was wondering if there was a simple way to just call a function that could help me to find the student by id number and append one of the three scores???

    also i have the problem of having to once i find the data freeing it well that is easy just make an array and once i find a match just freading it to a tmp pointer and then freeing it..the problem is that is there also a way to find the student by idnumber so i can call free()???

    if not i will have to read to an array manipulate that array to either delete and then write over...but that seems to time consuming...and probably slow utilizing more resources to make it happen...

    same for the scores should i just read to an array the file and then manipulate just the scores and then write them back???

    but without knowing the end of the file i would most likely get an error because it is difficult to manipulate a binary file in such way...

    any suggestion would help sorry i don't have any plausible source code since most of my source code right now is being converted to the more complex way of having multiple loops where it will read to an array, then manipulate the array, and then rewrite the students back to the file...
    Last edited by adramalech; 11-03-2008 at 11:34 PM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    A file with fixed-length records is essentially an array, where the [ ] operator is replaced by calls to fseek().

    So if you have a way of turning a student ID into a record number, so you can do seeks to 44*RecNum, then you can achieve that.

    Also like an array, you can't just delete things in the middle, and have all the following data shuffle down one place automatically. As you say, this could be expensive. Actual databases reserve a unique pattern which means "deleted data". Perhaps using student 999999999 for this purpose.

    > my source code right now is being converted to the more complex way of having multiple loops
    Try making it simpler first. If you're thinking it's hard to write now, just wait until you try to debug it.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Oct 2008
    Posts
    21
    okay so your like saying do this:

    while(!eofe(file_ptr)){ <--to make sure doesn't seek beyond the limit of written data
    then use fseek to set to to beginning of file with SEEK_(whatever it is..)

    then will have to read at that exact position using ftell() then will have to check if not won't delete else free at ftell() then check and make everything move up!!!

    thanks for the help i was just writing down to much code and trying to modulize everything!!!

  4. #4
    Registered User
    Join Date
    Oct 2008
    Posts
    21
    okay finally got some source code to show i still am having some issues with arrays and pointers...but this is as far as i have got...

    student.h (aka header file)
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #define FILE_NAME "~/CSC60/lab5/out.txt"
    #define MAX_SIZE 29
    #define SCORE_TEST 3
    #define SCORE_PROGRAM 5
    #define ID 9
    #define SIZE 3
    
    typedef struct the_student {
            char idNumber[ID], name[MAX_SIZE], gender,
            classLvl, age[SIZE], testScore[SCORE_TEST],
            programScore[SCORE_PROGRAM];
    }student;
    
    void addStudent();
    
    void deleteStudent(char[], int);
    
    void addTestScore(char[], int);
    
    void addProgramScore(char[], int);
    
    void outputClassReport();
    test.c (aka the main method)
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "student.h"
    
    int main(){
            int num, quit = 0;
            char id [];
            while(quit != 6){
                    printf("Please enter the number of the option you wish to run:\n");
                    printf("1. add student\n2. delete student\n3. add test score\n");
                    printf("4. add program score\n5. output class status\n 6. quit\n");
                    scanf("&#37;d\n", &num);
                    switch(num){
                            case 1: addStudent();
                                    break;
                            case 2: printf("Please enter the 9-digit idNumber of the student");
                                    scanf("%s" &id);
                                    deleteStudent(id, sizeof(id));
                                    break;
                            case 3: printf("Please enter the 9-digit idNumber of the student");
                                    scanf("%s" &id);
                                    addTestScore(id, sizeof(id));
                                    break;
                            case 4: printf("Please enter the 9-digit idNumber of the student");
                                    scanf("%s" &id);
                                    addProgramScore(id, sizeof(id));
                                    break;
                            case 5: outputClassReport();
                                    break;
                            case 6: quit = 6;
                                    break;
                    }//end switch statement
            }//end while loop
            return 0;
    }//end main
    addP.c (aka adding students with no scores)
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "student.h"
    
    void addProgramScore(char id[], int size){
            int found =0, i=0,z=0, pos=0;
            char chars[SCORE_PROGRAM];
            FILE* FILE_PTR;
            FILE_PTR = fopen(FILE_NAME, "rb+");
            fseek(FILE_PTR, 0, SEEK_END);
            pos = ftell(FILE_PTR);
            rewind(FILE_PTR);
            student *tmp, array[pos];
            tmp = malloc(sizeof(student));
            tmp->idNumber = id;
            fread(array, sizeof(student), pos, FILE_PTR);
            printf("What number Program score do you wish to enter: ");
            scanf("%d", &z);
            printf("What is score you are inputing to program score number %d :" &z);
            scanf("%s\n", chars);
            for(i =0; i<pos; i++){
                    if(array[i]->idNumber == tmp->idNumber){
                            array[i]->programScore[z] = chars;
                    }//end if statement
            }//end for loop
            fclose(FILE_PTR);
    }//end deleteStudent
    delete.c (aka deleting students)
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "student.h"
    
    void deleteStudent(char num[], int size){
            FILE* FILE_PTR;
            int found = 0, pos, i=0, z=0;
            student *find;
            FILE_PTR = fopen(FILE_NAME, "ab+");
            find = malloc(sizeof(student));
            find->idNumber = num;
            fseek(FILE_PTR, 0, SEEK_END);
            pos = ftell(FILE_PTR);
            rewind(FILE_PTR);
            student array[pos];
            fread(array, sizeof(student), pos, FILE_PTR);
            while(z++ < pos){
                    if(array[z]->idNumber == find->idNumber){
                            for(i=z; i< pos; i++){
                                    array[z] = array[z+1];
                            }//end for loop
                    }//end if statement
                    fseek(FILE_PTR, 1, SEEK_CUR);
            }//end while loop
            fclose(FILE_PTR);
    }//end deleteStudent
    addT.c (aka adding test scores to students by idnumber)
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "student.h"
    
    void addTestScore(char *id[], int size){
            int found =0, i=0,z=0, pos;
            char chars[SCORE_TEST];
            FILE *FILE_PTR;
            FILE_PTR = fopen(FILE_NAME, "rb+");
            fseek(FILE_PTR, 0, SEEK_END);
            pos = ftell(FILE_PTR);
            rewind(FILE_PTR);
            student *tmp, *array[pos];
            tmp = malloc(sizeof(student));
            tmp->idNumber = id;
            fread(array, sizeof(student), pos, FILE_PTR);
            printf("What number Test score do you wish to enter: ");
            scanf("%d", &z);
            printf("What is score you are inputing to test score number %d :", &z);
            scanf("%s", chars);
            for(i =0; i<pos; i++){
                    if(array[i]->idNumber == tmp->idNumber){
                            array[i]->testScore[z] = chars;
                    }//end if statement
            }//end for loop
            fclose(FILE_PTR);
    }//end addTestScores
    addP.c (same as above except dealing with program scores instead)
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "student.h"
    
    void addProgramScore(char id[], int size){
            int found =0, i=0,z=0, pos=0;
            char chars[SCORE_PROGRAM];
            FILE* FILE_PTR;
            FILE_PTR = fopen(FILE_NAME, "rb+");
            fseek(FILE_PTR, 0, SEEK_END);
            pos = ftell(FILE_PTR);
            rewind(FILE_PTR);
            student *tmp, array[pos];
            tmp = malloc(sizeof(student));
            tmp->idNumber = id;
            fread(array, sizeof(student), pos, FILE_PTR);
            printf("What number Program score do you wish to enter: ");
            scanf("%d", &z);
            printf("What is score you are inputing to program score number %d :" &z);
            scanf("%s\n", chars);
            for(i =0; i<pos; i++){
                    if(array[i]->idNumber == tmp->idNumber){
                            array[i]->programScore[z] = chars;
                    }//end if statement
            }//end for loop
            fclose(FILE_PTR);
    }//end addProgramScore
    outputC.c (aka printing out the report card)

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "student.h"
    
    void outputClassReport(){
            int pos, i;
            FILE *FILE_PTR;
            FILE_PTR = fopen(FILE_NAME, "rb");
            student *tmp;
            tmp = malloc(sizeof(student));
            fseek(FILE_PTR, 0, SEEK_END);
            pos = ftell(FILE_PTR);
            student array[pos];
            rewind(FILE_PTR);
            fread(array, sizeof(student), pos, FILE_PTR);
            printf("\t\t\tCLASS \t\t TEST");
            printf("\tID \t NAME  \t LVL  GENDER  AGE  SCORES \t PROGRAM SCORES");
            printf("----------------------------------------------------------------------------");
            for(i=0; i<pos; i++)
                    printf("%9s %s %5s %2s %4s %2s %2s", array[i]->idNumber, array[i]->name,
                            array[i]->classLvl, array[i]->gender,array[i]->age, array[i]->testScore,
                            array[i]->programScore);
            }//end while loop
            fclose(FILE_PTR);
    }//end outputClassReport

  5. #5
    Registered User
    Join Date
    Oct 2008
    Posts
    21
    okay so i have fixed alot of errors in my code and it is much better, but i have seemed to stumble upon an error i cannot figure out maybe one of you could be of more assistance than me just starring at it all day.

    here is the script file showing the error...
    Code:
    Script started on Sun 09 Nov 2008 11:33:41 AM PST
    > gcc -c addS.c addT.c addP.c deleteS.c outputC.c
    > gcc -g *.o test.c
    addS.o(.text+0x6d): In function `addStudent':
    : warning: the `gets' function is dangerous and should not be used.
    > gdb a.out
    GNU gdb Red Hat Linux (6.3.0.0-1.159.el4rh)
    Copyright 2004 Free Software Foundation, Inc.
    GDB is free software, covered by the GNU General Public License, and you are
    welcome to change it and/or distribute copies of it under certain conditions.
    Type "show copying" to see the conditions.
    There is absolutely no warranty for GDB.  Type "show warranty" for details.
    This GDB was configured as "i386-redhat-linux-gnu"...Using host libthread_db library "/lib/tls/i686/nosegneg/libthread_db.so.1".
    
    (gdb) run a.out
    Starting program: /gaia/class/student/thronej/CSC60/lab5/a.out a.out
    Please enter the number of the option you wish to run:
    1. add student
    2. delete student
    3. add test score
    4. add program score
    5. output class status
    6. quit
    1
    Please enter their 9-digit id number: 11111111
    
    Program received signal SIGSEGV, Segmentation fault.
    0x00c16156 in _IO_vfscanf_internal () from /lib/tls/i686/nosegneg/libc.so.6
    (gdb) where
    #0  0x00c16156 in _IO_vfscanf_internal () from /lib/tls/i686/nosegneg/libc.so.6
    #1  0x00c1c6e6 in scanf () from /lib/tls/i686/nosegneg/libc.so.6
    #2  0x080487bc in addStudent ()
    #3  0x08048dad in main () at test.c:12
    (gdb) frame 2
    #2  0x080487bc in addStudent ()
    (gdb) x/i 0x080487bc
    0x80487bc <addStudent+56>:      add    $0x10,%esp
    (gdb) quit
    The program is running.  Exit anyway? (y or n) y
    > exit
    exit
    
    Script done on Sun 09 Nov 2008 11:35:29 AM PST
    here is the main method that is used to call the functions:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "student.h"
    
    int main(){
            int num = 0, id = 0;
            while(1){
                    printf("Please enter the number of the option you wish to run:\n"
                           "1. add student\n2. delete student\n3. add test score\n"
                           "4. add program score\n5. output class status\n6. quit\n");
                    scanf("%d", &num);
                    if(num == 1){addStudent();}
                    else if(num == 2){
                            printf("Please enter the 9-digit idNumber of the student");
                            scanf("%d\n", &id);
                            deleteStudent(id);
                    }//end elseif statement
                    else if(num == 3){
                            printf("Please enter the 9-digit idNumber of the student");
                            scanf("%d\n", &id);
                            addTestScore(id);
                    }//end else if statement
                    else if(num == 4){
                            printf("Please enter the 9-digit idNumber of the student");
                            scanf("%d\n", &id);
                            addProgramScore(id);
                    }//end else if statement
                    else if(num == 5){outputClassReport();}
                    else{
                            return 0;
                    }//end else statement
            }//end while loop
            return 0;
    }//end main
    here is the revised add student function...

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "student.h"
    
    void addStudent(){
            student *tmp;
            tmp = (student *)malloc(sizeof(student));
            rec r;
            char tmper, dummy[80];
            FILE *FILE_PTR;
            printf("Please enter their 9-digit id number: ");
            scanf("%d", tmp->idNumber); //here is where it will error 
            printf("\nPlease enter their name: ");
            fgets(dummy, sizeof(dummy), stdin);
            gets(tmp->name);
            printf("\nPlease enter their class level: ");
            fgets(dummy, sizeof(dummy), stdin);
            scanf("%c", &tmper);
            r.classLvl = tmper;
            printf("\nPlease enter their gender: ");
            scanf("%c", &tmper);
            r.gender = tmper;
            tmp->cLvl_gender = r.gender;
            tmp->cLvl_gender = r.classLvl;
            printf("\nPlease enter their age: ");
            scanf("%c", tmp->age);
            FILE_PTR = fopen(FILE_NAME, "ab+");
            fwrite(tmp, sizeof(tmp), 1, FILE_PTR);
            fclose(FILE_PTR);
    }//end addStudent
    here is the header file student.h

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #define FILE_NAME "~/CSC60/lab5/out.txt"
    #define MAX_SIZE 29
    #define SIZE 3
    
    typedef struct {
            int idNumber;
            char name[MAX_SIZE],testScore[SIZE], programScore[SIZE];
            char cLvl_gender, age;
    }student;
    
    typedef struct {
            unsigned int classLvl : 3;
            unsigned char gender : 1;
            unsigned : 4;
    } rec;
    
    void addStudent();
    
    void deleteStudent(int);
    
    void addTestScore(int);
    
    void addProgramScore(int);
    
    void outputClassReport();

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Try
    gcc -W -Wall -ansi -pedantic -c addS.c addT.c addP.c deleteS.c outputC.c

    It will (amongst other things) tell you that the scanf line in question is NOT a pointer to an int, as is expected.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  7. #7
    Registered User
    Join Date
    Oct 2008
    Posts
    21
    here is the code i get from addS.c:

    Code:
    In file included from addS.c:3:
    student.h:15: warning: type of bit-field `gender' is a GCC extension
    addS.c: In function `addStudent':
    addS.c:8: warning: ISO C90 forbids mixed declarations and code
    addS.c:10: warning: ISO C90 forbids mixed declarations and code
    addS.c: At top level:
    addS.c:31: error: syntax error before '/' token
    i don't understand the error ISO C90 forbids mixed declarations and code... the line 8 points to where i say: rec *r;

    here is a newer revised edition of addS.c I have got rid of some of the errors but as you can tell the others i don't understand them.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include "student.h"
    
    void addStudent(){
            student *tmp;
            tmp = (student *)malloc(sizeof(student));
            rec *r;
            r = (rec *)malloc (sizeof(rec));
            char tmper, dummy[80];
            FILE *FILE_PTR;
            printf("Please enter their 9-digit id number: ");
            scanf("%d", &tmp->idNumber);
            printf("\nPlease enter their name: ");
            fgets(dummy, sizeof(dummy), stdin);
            gets(tmp->name);
            printf("\nPlease enter their class level: ");
            fgets(dummy, sizeof(dummy), stdin);
            scanf("%c", &tmper);
            r->classLvl = tmper;
            printf("\nPlease enter their gender: ");
            scanf("%c", &tmper);
            r->gender = tmper;
            tmp->cLvl_gender = r->classLvl;
            tmp->cLvl_gender = r->gender;
            printf("\nPlease enter their age: ");
            scanf("%c", &tmp->age);
            FILE_PTR = fopen(FILE_NAME, "ab+");
            fwrite(tmp, sizeof(tmp), 1, FILE_PTR);
            fclose(FILE_PTR);
    }//end addStudent

  8. #8
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    It means just what it says -- in ISO C90, you can't mix declarations with code. All variables must appear at the beginning -- once you do a line of code, like say
    Code:
    tmp = (student *)malloc(sizeof(student));
    no more variables. There also aren't //-style comments in ISO C90.

  9. #9
    Registered User
    Join Date
    May 2008
    Posts
    28
    #define SCORE_TEST 3
    #define SCORE_PROGRAM 5
    #define ID 9
    #define SIZE 3
    I'm not sure why you're using CHARS where unsigned INTS and DWORDS would do ?

  10. #10
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > student.h:15: warning: type of bit-field `gender' is a GCC extension
    bit-fields are always 'int' or 'unsigned int', regardless of how many actual bits you've assigned to the field.

    Is the code working any better now?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  11. #11
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Further, why are you using bitfields in the first place? Unless you are writing code for something significantly smaller than a mobile phone AND you have thousands of these student records to store in your little device, the saving in memory is definitely not worth it (and if you have less than quite many (a few dozen or more) of the student records, you proably loose out on the code taking up more space, compared to the saving in space the field takes).

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  12. #12
    Registered User
    Join Date
    Oct 2008
    Posts
    21
    i have to make every structure under 44bytes!!!

    that is why i try to get the smallest allowed type to each variable without getting any overflow errors...

    idNumber can be up to 9 digits...name can be a string of up to 29 characters...

    age is 100 or less, class level is only...

    i will used unsigned ints instead of ints and unsigned chars instead of chars i figured that it will be less space but besides that everything else is there so i don't go over the allowed size of the student structure...

    i am also getting rid of the rec structure and putting it into the student structure as another member...

  13. #13
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    signed ints and unsigned ints take up the same storage only difference is that for a signed object the MSB is used for the sign bit.
    same goes for signed chars and unsigned chars.

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    9 digits: int = 4 bytes.
    29 characters = 30 bytes
    age: char = 1 byte.
    That's a total of 35 bytes. What do you have to fill the next 9 bytes with?

    Unsigned or signed integers take up exactly the same amount of space - the only diference is what branch instructions the compiler generates for >, <, >=, <= operators.

    Bitfields, unless they are packed together in a bunch, will take a byte anyways.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  15. #15
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    Quote Originally Posted by matsp View Post
    9 digits: int = 4 bytes.
    29 characters = 30 bytes
    age: char = 1 byte.
    That's a total of 35 bytes. What do you have to fill the next 9 bytes with?
    Looks like gender, class level, test score, and program score -- three chars and an int for seven bytes (assuming test score doesn't get over 255). Still two bytes to spare.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Data Structure Eror
    By prominababy in forum C Programming
    Replies: 3
    Last Post: 01-06-2009, 09:35 AM
  2. File I/O Assertion Failure in VS2008
    By clegs in forum C Programming
    Replies: 5
    Last Post: 12-25-2008, 04:47 AM
  3. Game Pointer Trouble?
    By Drahcir in forum C Programming
    Replies: 8
    Last Post: 02-04-2006, 02:53 AM
  4. 2 questions surrounding an I/O file
    By Guti14 in forum C Programming
    Replies: 2
    Last Post: 08-30-2004, 11:21 PM
  5. advice on file i/o
    By Unregistered in forum C Programming
    Replies: 1
    Last Post: 11-29-2001, 05:56 AM