Thread: reading a file

  1. #1
    Registered User
    Join Date
    Sep 2012
    Posts
    21

    reading a file

    hi,
    i have a struct that holds variables of different data types. i am trying to read the first character of data from a data file and store the data into the struct..

    the file holds data like this:
    interger 5
    real 6.4
    character c

    so here is my code:
    Code:
    /* testCommand.h */
    
    
    typedef struct {
        char mycom[10];
        int integer;
        double real;
        char character;
    }command;
    Code:
    /* testCommand.c */
    
    
    
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    
    #include "testCommand.h"
    
    
    FILE *f;
    int main(int argc, char* argv[]){
        int lenght, i;
        char ch;
        command *mycommand = (command*)malloc(sizeof(command));
    
    
        f = fopen(argv[1], "r+");
        if( f != NULL){
            lenght = numLine(f);
            printf("Number of Lines: %d\n", lenght);
        
            for(i=0; i<(lenght); i++){
                ch = fgetc(f);    // get the forst character of the command
                if (ch == 'i'){
                    fscanf(f, "%s %i", &(mycommand->mycom), &(mycommand->integer));
                    printf("%s %i\n", (mycommand->mycom), (mycommand->integer));    
                }
                else if (ch == 'r'){
                    fscanf(f, "%s %lf", &(mycommand->mycom), &(mycommand->real));
                    printf("%s %i\n", (mycommand->mycom), (mycommand->real));    
                }
                else if (ch == 'c'){
                    fscanf(f, "%s %c", &(mycommand->mycom), &(mycommand->character));
                    printf("%s %i\n", mycommand->mycom, mycommand->character);    
                }
                
                else {
                    printf("Invalid!\n");    
                }        
    
    
            }
    
    
        }
        
        else{
            perror("couldnt open");    
        }
    
    
            return 0;
    }
    
    
    int numLine(FILE* fileNames){
        int numLines=0;
        char ch;
            do{
                ch = fgetc(fileNames);
                if(ch == '\n')
                numLines++;
            } while (ch != EOF);
    
    
            if(ch != '\n' && (numLines) != 0){ 
                numLines++;
            }
        return numLines;
    }

    the program always outputs "Invalid!".

    SORRY IF THE QUESTION IS WORDED BADLY.. :/

  2. #2
    Registered User
    Join Date
    Sep 2012
    Posts
    357
    After numLines finished with the file, the file pointer is at the "end of file" position.
    The input functions in the main() function all fail because they have nothing left to read.

    You need to either close and re-open the file
    or rewind() it back to the beginning (you can also use fseek()).

  3. #3
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    One of your problems is that you read to the end of the file in your numLine() function, then you never reset the file back to the beginning. Also in numLine() if you use a large enough character buffer you could get the entire line at a time using fgets().

    Jim

  4. #4
    Registered User
    Join Date
    Sep 2012
    Posts
    21
    @qny, thanks that worked... but nowww when i run the program with a file like this:
    real 5.5
    integer 2
    character c

    i get an output something like this:
    Number of Lines: 3
    eal 0
    Invalid!
    nteger 2

  5. #5
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    You may want to start by turning up your warnings. When I compiled your code I received these messages:
    main.c||In function ‘main’:|
    main.c|38|warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘char (*)[10]’ [-Wformat]|
    main.c|42|warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘char (*)[10]’ [-Wformat]|
    main.c|43|warning: format ‘%i’ expects argument of type ‘int’, but argument 3 has type ‘double’ [-Wformat]|
    main.c|46|warning: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘char (*)[10]’ [-Wformat]|
    main.c|23|warning: unused parameter ‘argc’ [-Wunused-parameter]|

    Jim

  6. #6
    Registered User
    Join Date
    Sep 2012
    Posts
    21
    so i fixed those errors,, but i still get the following outputs for an input file that contains the data:
    real 5.5
    integer 2
    character c

    OUTPUT:
    Number of Lines: 3
    eal 5.500000
    Invalid!
    nteger 2

  7. #7
    Registered User
    Join Date
    Sep 2012
    Posts
    357
    Quote Originally Posted by m_programmer View Post
    @qny, thanks that worked... but nowww when i run the program with a file like this:
    real 5.5
    integer 2
    character c

    i get an output something like this:
    Number of Lines: 3
    eal 0
    Invalid!
    nteger 2
    This is a similar problem.
    In the main() function you first read a character into ch; then, based on that, you read the rest of the command.
    You can solve it easily by also printing ch.

    You're going to have problems with the ENTERs on every line.
    The best option to deal with them (using fgets()) is going to force you to make lots of changes to your code. A fast solution is to ignore them right before the instruction that reads the first letter of the command.

  8. #8
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    Why not just read the entire command string with scanf() instead of just reading the first letter? Then compare the first letter of command to your desired character. Also for any further question please post the modified code.

    Jim

  9. #9
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Code:
    char ch;
    do{
        ch = fgetc(fileNames);
        if(ch == '\n')
            numLines++;
    } while (ch != EOF);
    The fgetc function returns an int, not a char. This is very important when comparing against a value such as EOF.




    Code:
    command *mycommand = (command*)malloc(sizeof(command));
    You should avoid casting the return value from the malloc call when programming in C. It is unnecessary and in certain cases can hide problems. The void pointer result returned by the malloc call can be safely assigned to the mycommand pointer without need of a cast.

    Also, from a maintenance standpoint it's usually best to use the pointer's type to determine the size needed rather than using the sizeof operator on the type directly. If the type changes in the course of your program's development, you would need to track down each such statement to change the type in the sizeof operator. If however you use the type pointed to by the pointer then this is taken care of for you automatically:

    Code:
    struct foo
    {
       ...
    };
    
    ...
    
    struct foo * bar1, * bar2;
    
    // If bar1 changes from struct foo to something else,
    // all lines such as this need to be found and changed
    bar1 = malloc(sizeof(struct foo));
    
    // If bar2 changes from struct foo to something else,
    // nothing else needs to be done here, less work and
    // less chance of you making a mistake
    bar2 = malloc(sizeof(*bar2));



    Code:
    typedef struct {
        char mycom[10];
        int integer;
        double real;
        char character;
    }command;
    
    ...
    
    fscanf(f, "%s %i", &(mycommand->mycom), &(mycommand->integer));
    mycommand->mycom itself represents the address of the first character of the array in question. As such you should not be using the address-of operator (&) for the %s arguments since they already are an address. jim makes mention of this fact when he posted his list of warnings when he compiled your code.

    Also, since you've already read a single character, the remaining string will always appear to have had the first character removed when it comes time to print. This can be dealt with as jim stated in the post above mine. The second argument does require the address-of operator however.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 07-17-2011, 03:51 AM
  2. File I/O..Reading a file and printing contents
    By eeengenious in forum C Programming
    Replies: 2
    Last Post: 03-14-2011, 05:58 PM
  3. Replies: 13
    Last Post: 05-31-2009, 11:30 AM
  4. Reading flat file and generating tagged file
    By AngKar in forum C# Programming
    Replies: 4
    Last Post: 03-24-2006, 08:29 AM
  5. reading from file and writing in a nother file
    By undisputed007 in forum C++ Programming
    Replies: 4
    Last Post: 02-27-2004, 02:17 PM