Thread: My C Programming Files I/O are not working

  1. #1
    Registered User
    Join Date
    Dec 2017
    Posts
    20

    My C Programming Files I/O are not working

    I am new to c programming language so bare with me.
    I have written a database that stores products using a struct. This database inserts new products (product number, product name and product balance), prints out the stored products and etc. in my program i have two functions. one saves my inputs in a text file the other function is suppose to read back from my text file into my program.

    he two functions are

    savetofile- save my inputs in a text file
    readfromfile- read back my text file into my program

    the problem is that my program is able to save files but not read them back. the objection is so that i can save and read back my inputs for further use.

    below i will attach my int main and my two functions:


    Code:
    int main (void)
    {
        struct storagemanipulation inventory[MAX_ANTAL];
        int antal_varor=0;
        char file[30];
        readFromFile(file, antal_varor, inventory);
        
        for (;;)
        {
            char kod;
            printf("Meny kod 'r'= lδgga till varor\n");
            printf("Meny kod 'p'= skriva ut innehεllet\n");
            printf("Meny kod 'u'= uppdatera lagersaldo\n");
            printf("Meny kod 's'= sφka efter en vara\n");
            printf("Meny kod 't'= Avsluta programmet\n");
            printf("Meny kod 'w'= radera varunummer\n");
            printf("Meny kod 'a'= varning\n");
            printf("Meny kod 'h'= sortera\n");
            printf("Meny kod 'z'= sparafilnamn\n");
            
            printf("Ange meny kod: ");
            scanf("%c", &kod);
            
            while (getchar() != '\n') //hoppar φver fram till sutet
                ;
            switch (kod)
            {
                case 'r': insert(&antal_varor, inventory); break;
                case 'p': skrivutres(antal_varor, inventory); break;
                case 'u': uppdatera(antal_varor, inventory);break;
                case 's': soka(antal_varor, inventory);break;
                case 'w': radera(&antal_varor, inventory);break;
                case 'a': varning(antal_varor, inventory);break;
                case 'h': sort(antal_varor, inventory);break;
                case 'z': sparafil(file, antal_varor, inventory);break;
                case 't': printf("avsluta");
                    saveToFile(file, antal_varor, inventory); return 0;
                     break;
                default: printf("OGILTIG INPUT\n");
    Code:
    void readFromFile(char file[], int antal_varor, struct storagemanipulation *inventory)
    {
        printf("Enter the name of the file that you would like to open: \n");
        scanf("%s", file);
        FILE *fp;
        fp=fopen(file,"r");
        char singleline[150];
        
        file=singleline;
            if (fp==NULL)
    
    
            {printf("no access to the File\n");}
    else
            for (int i = 0; i < antal_varor; i++)
            {
                fscanf(fp,file,"%s %d %d",inventory[i].namn, &inventory[i].lagersaldo, &inventory[i].varunummer);
            }
            fclose(fp);
    }
    void saveToFile(char file[], int antal_varor, struct storagemanipulation *inventory)
    {
        FILE *fp;
        fp = fopen("vara.txt", "w");
        if (fp != NULL)
        {
            for (int i = 0; i < antal_varor; i++)
            {
                fprintf(fp, "%s %d %d\n", inventory[i].namn, inventory[i].varunummer, inventory[i].lagersaldo);
            }
            
        } fclose(fp);
    }

  2. #2
    Registered User
    Join Date
    Dec 2017
    Posts
    1,626
    If you are using a "hard-coded" filename (e.g., vara.txt) then you don't need the "file" parameter at all. Get rid of it.

    If you need to have the user specify a file name, then don't pass in the "file" parameter. Instead, declare the array in the save and read functions.

    Also, only pass fp, not file, to the fscanf function.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  3. #3
    Registered User
    Join Date
    Dec 2017
    Posts
    20
    John i declared the array as you said in the two functions. and i got rid of my file parameter but i still cant read back my saved inputs.

    do you mind posting an example using my program?

    Thanks

  4. #4
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by john.c
    If you are using a "hard-coded" filename (e.g., vara.txt) then you don't need the "file" parameter at all. Get rid of it.
    True, but instead of getting rid of it, call saveToFile with that hard-coded filename in main. This makes it easier to change your code to have a more flexible filename later. Note that char file[] should then be changed to const char file[] or equivalently const char *file

    Quote Originally Posted by john.c
    If you need to have the user specify a file name, then don't pass in the "file" parameter. Instead, declare the array in the save and read functions.
    Agreed, but instead of trying to do both interactive I/O (to request the user to specify a filename) and the actual writing to/reading from the file in a single function, it may be better to split them into two functions, e.g.,
    Code:
    int readFromFile(FILE *fp, int antal_varor, struct storagemanipulation *inventory)
    {
        int i = 0;
        for (; i < antal_varor; i++)
        {
            if (fscanf(fp, file, "%s %d %d", inventory[i].namn, &inventory[i].lagersaldo, &inventory[i].varunummer) != 3)
            {
                break;
            }
        }
        return i;
    }
    
    void interactiveReadFromFile(int antal_varor, struct storagemanipulation *inventory)
    {
        char filename[150];
        FILE *fp;
        int num_entries;
    
        printf("Enter the name of the file that you would like to open: \n");
        if (scanf("%149s", filename) != 1)
        {
            /* print some error message
               .... */
            return;
        }
    
        fp = fopen(file, "r");
        if (fp == NULL)
        {
            printf("no access to the File\n");
            return;
        }
    
        num_entries = readFromFile(fp, antal_varor, inventory);
        fclose(fp);
    
        printf("%d entries were read from '%s'\n", num_entries, filename);
    }
    This allows the nitty gritty of reading to be tested separately from the interactive I/O to obtain information from the user and provide feedback to the user, e.g., readFromFile could be easily tested with a battery of automated tests. Likewise, this approach can be used for saveToFile.

    abmoh: a few things to note:
    • I changed your code to check the return value of fscanf, and to return the number of successfully read entries. This allows for easier checking of how many successfully read entries were there, instead of just proceeding even if a read failed.
    • There are generally two approaches to structuring error checking with if statements: you could check for success in the if branch, then have the else branch handle the failure, or you could check for failure in the if branch, then return from the function early (after doing cleanup, if necessary). Since you chose to check if fopen returns a null pointer, I decided to restructure your code according to the latter.
    • Besides checking the return value of scanf, you should impose a field width when reading into a string with %s in order to avoid buffer overflow.


    Quote Originally Posted by abmoh
    i declared the array as you said in the two functions. and i got rid of my file parameter but i still cant read back my saved inputs.
    What is your current code? You may wish to look at my example in this post and see if you can integrate the ideas here into your current code.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  5. #5
    Registered User
    Join Date
    Dec 2017
    Posts
    20
    Quote Originally Posted by laserlight View Post
    abmoh: a few things to note:
    • I changed your code to check the return value of fscanf, and to return the number of successfully read entries. This allows for easier checking of how many successfully read entries were there, instead of just proceeding even if a read failed.
    • There are generally two approaches to structuring error checking with if statements: you could check for success in the if branch, then have the else branch handle the failure, or you could check for failure in the if branch, then return from the function early (after doing cleanup, if necessary). Since you chose to check if fopen returns a null pointer, I decided to restructure your code according to the latter.
    • Besides checking the return value of scanf, you should impose a field width when reading into a string with %s in order to avoid buffer overflow.



    What is your current code? You may wish to look at my example in this post and see if you can integrate the ideas here into your current code.

    Thank you for helping. this is my current code.
    it is still not working and i am stuck. Dont know what to do to fix this problem


    Code:
    void readFromFile(char file[], int *antal_varor, struct storagemanipulation *inventory)
    {
        int i;
        printf("Enter the name of the file that you would like to open: \n");
        scanf("%s", file);
        FILE *fp;
        fp=fopen(file,"r");
        printf("prva\n");
            if (fp==NULL)
            {printf("no access to the File\n");}
            else
            {
                printf("test\n");
                
                
                for (; i <*antal_varor; i++)
                        {
                            if (fscanf(fp, file, "%s %d %d", inventory[i].namn, &inventory[i].lagersaldo, &inventory[i].varunummer) != 3)
                            {
                                break;
                            }
                            
                            fscanf(fp,"%s %d %d",inventory[i].namn, &inventory[i].lagersaldo, &inventory[i].varunummer);
                            
                        }
            }
            fclose(fp);
    }
    

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Um, why are you calling fscanf twice in the body of the for loop? You failed to initialise the variable i to 0.

    How does it not work? For example, how do you know that you are not correctly reading the input? It doesn't look like you have any way of checking if the input has actually been correctly read.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Registered User
    Join Date
    Dec 2017
    Posts
    20
    What should i insert into my while loop to insure that it does not loop more than required?


    Code:
    void readFromFile(char file[], int *antal_varor, struct storagemanipulation *inventory)
    {
        int i;
        printf("Enter the name of the file that you would like to open: \n");
        scanf("%s", file);
        FILE *fp;
        fp=fopen(file,"r");
        printf("prva\n");
        if (fp!=NULL)
        {
            printf("test\n");
            
            
            while ()
            {
                fscanf(fp, file, "%s %d %d", inventory[i].namn, &inventory[i].lagersaldo, &inventory[i].varunummer);
                printf("test123");
                (*antal_varor)++;
                
            }
    }
        else
        {
            printf("no access to the File\n");
                }
        fclose(fp);
    }

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by abmoh
    What should i insert into my while loop to insure that it does not loop more than required?
    You were doing that correctly in your post #1, assuming that antal_varor is the maximum number of entries that you wish to read. Looking at your main function again along with the changes you made in post #5, I see that this is not the case: antal_varor appears to be the number of entries read.

    As such, you could adapt my example in post #4:
    Code:
    int readFromFile(FILE *fp, struct storagemanipulation *inventory)
    {
        int i = 0;
        while (/* fscanf call that checks the return value */);
        return i;
    }
    then in interactiveReadFromFile:
    Code:
    *antal_varor = readFromFile(fp, inventory);
    EDIT:
    Actually, my suggested implementation for readFromFile is a poor one as it does not account for possible buffer overflow, and then I neglected to show the increment of i. What you should have is:
    Code:
    while (i < MAX_ANTAL && /* fscanf call that checks the return value */)
    {
        i++;
    }
    Last edited by laserlight; 12-15-2017 at 07:08 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Dec 2017
    Posts
    20
    I will as good as possible try to explain the issue that i have with my program. in my int main () i have declared that int antal_varor=0.
    so when my readfromfile function is called upon

    Code:
    void readFromFile(char file[], int *antal_varor, struct storagemanipulation *inventory)
    {
        int i;
        printf("Enter the name of the file that you would like to open: \n");
        scanf("%s", file);
        FILE *fp;
        fp=fopen(file,"r");
        printf("prva\n");
        if (fp!=NULL)
        {
            printf("test\n");
            
            
            for (i=0; i <*antal_varor; i++)
            {
                
                fscanf(fp, file, "%s %d %d", inventory[i].namn, &inventory[i].lagersaldo, &inventory[i].varunummer);
                printf("%s %d %d", inventory[i].namn, inventory[i].lagersaldo, inventory[i].varunummer);
                
                printf("test123");
                
            }
    }
        else
        {
            printf("no access to the File\n");
                }
        fclose(fp);
    }
    
    it loops thru the for loop (but here is the problem) antal_varor is still equal to zero. so the loop never happens. so how do i change the code that i inserted in this post to make sure that my function loops correctly.

    Laserlight i am extremly thankful for your help but as a beginner i don't fully understand the function void interactivereadfromfile So i would rather find a solution to my readfromfile function.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by abmoh
    it loops thru the for loop (but here is the problem) antal_varor is still equal to zero. so the loop never happens. so how do i change the code that i inserted in this post to make sure that my function loops correctly.
    Yeah, that's what I meant when I said I realised that "antal_varor appears to be the number of entries read".

    You're right to think about switching from a for loop to a while loop: a for loop tends to be used when you have a certain number of entries to read, whereas a while loop tends to be used when the looping is more indefinite.

    In your case, this means:
    Code:
    i = 0;
    while (i < MAX_ANTAL && fscanf(fp, file, "%s %d %d", inventory[i].namn, &inventory[i].lagersaldo, &inventory[i].varunummer) == 3)
    {
        i++;
    }
    *antal_varor = i;
    Of course, you can still write a for loop for this, one with an empty body (or whose body prints out what was just read).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Dec 2017
    Posts
    20
    Quote Originally Posted by laserlight View Post
    Yeah, that's what I meant when I said I realised that "antal_varor appears to be the number of entries read".

    You're right to think about switching from a for loop to a while loop: a for loop tends to be used when you have a certain number of entries to read, whereas a while loop tends to be used when the looping is more indefinite.

    I was able to change so that my savetofile inserts antal_varor
    so that when it comes around to readfromfile it already contains the the right nr of antal_varor

    but the new issue is that my output is still printing out zeros


    Varunummer: Namn Lagersaldo
    ——————————————————————————————————————————————————
    0 0
    0 0
    0 0
    0 0
    0 0
    0 0

    how do i make sure that my code prints out this

    Varunummer: Namn Lagersaldo
    ——————————————————————————————————————————————————
    123 majs 12
    234 banan 45
    432 klossar 32
    654 klas 32
    435 soppa 32
    121 granat 23


    Code:
    void readFromFile(char file[], int *antal_varor, struct storagemanipulation *inventory)
    {
        int i;
        printf("Enter the name of the file that you would like to open: \n");
        scanf("%s", file);
        char namn[30];
        int lagersaldo, varunummer;
        FILE *fp;
        fp=fopen(file,"r");
        if (fp!=NULL)
        {
            
            fscanf(fp, "%d", antal_varor);
            
            for (int i = 0; i < *antal_varor; i++)
            {
                if(fscanf(fp, file, "%s %d %d", inventory[i].namn, &inventory[i].lagersaldo, &inventory[i].varunummer) == 3)
                {
                    inventory[varunummer].varunummer = varunummer;
                    strcpy(inventory[i].namn, namn);
                    inventory[i].lagersaldo = lagersaldo;
                }
            }
    }
        else
        {
            printf("no access to the File\n");
                }
        fclose(fp);
    }

  12. #12
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Have you tried taking removing these?
    Code:
                    inventory[varunummer].varunummer = varunummer;
                    strcpy(inventory[i].namn, namn);
                    inventory[i].lagersaldo = lagersaldo;
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  13. #13
    Registered User
    Join Date
    Dec 2017
    Posts
    20
    Quote Originally Posted by laserlight View Post
    Have you tried taking removing these?
    Code:
                    inventory[varunummer].varunummer = varunummer;
                    strcpy(inventory[i].namn, namn);
                    inventory[i].lagersaldo = lagersaldo;
    i just tried to remove these three lines but still nothing

  14. #14
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I would debug:
    Code:
    void readFromFile(char file[], int *antal_varor, struct storagemanipulation *inventory)
    {
        int i;
        printf("Enter the name of the file that you would like to open: \n");
        scanf("%s", file);
        char namn[30];
        int lagersaldo, varunummer;
        FILE *fp;
        fp = fopen(file, "r");
        if (fp != NULL)
        {
            if (fscanf(fp, "%d", antal_varor) == 1)
            {
                for (int i = 0; i < MAX_ANTAL && i < *antal_varor; i++)
                {
                    if (fscanf(fp, file, "%s %d %d", inventory[i].namn, &inventory[i].varunummer, &inventory[i].lagersaldo) == 3)
                    {
                        printf("%s %d %d\n", inventory[i].namn, inventory[i].varunummer, inventory[i].lagersaldo);
                    }
                    else
                    {
                        printf("error reading an entry\n");
                    }
                }
            }
            else
            {
                printf("error reading the number of entries\n");
            }
            fclose(fp);
        }
        else
        {
            printf("no access to the File\n");
        }
    }
    Actually, you can debug with a debugger instead, but you might as go with this for now. By the way, it looks like you mixed up varunummer and lagersaldo in reading versus writing. I fixed the reading to match the writing. There's another thing wrong with your fscanf call that I missed earlier, but I think it may be instructive for you to run the above code snippet to find out. Pay attention to compiler warnings, if any. You should find that you have quite a few unexpected read errors.
    Last edited by laserlight; 12-15-2017 at 08:41 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  15. #15
    Banned
    Join Date
    Aug 2017
    Posts
    861
    here is something I was playing with last night, it shows an added feature for first time files. It is still work in progress, but it opens or creates a new file to the users specifications takes in data, then stores it and prints it out. It needs work but I think thier is enough to show you a few different ways this too can be done. It is just a simple open/create file, add data, store data, print data to screen.

    it is possible to incorporate everything in here ( code in this thread ) into your program keeping what is needed and discarding what is not to get yourself a "complete" set of instructions. I say that because I see some error checking in some of the code already posted in here, and that is a valuable thing to do with coding. SO i'd hate to see you lose that.

    Code:
    #include <stdio.h>
    #include <string.h>
    
    struct storagemanipulation
    {
        char namn[100];
        int lagersaldo;
        int varunummer;
        
    };
    void readFromFile(FILE *fp, int antal_varor, struct storagemanipulation *inventory)
    {
         for (int i = 0; i < antal_varor; i++)
            fscanf(fp,"%s %d %d",inventory[i].namn, &inventory[i].lagersaldo, &inventory[i].varunummer);
    }
      
    void saveToFile(FILE *fp, int antal_varor, struct storagemanipulation *inventory)
    { // the file should already be open for writting as well
    // so is there an actually needed to open it again?
    //
    // 
    // your data should be stored in your struct array
    // just pass that and its size to write the data 
    //into the file 
    
          fseek(fp,0,SEEK_SET); // just to be sure it at the start of file
          
        // which ever order they are suppose to go, it needs to match the file
        for (int i = 0; i < antal_varor; i++)
        {
            fprintf(fp, "%s %d %d\n", inventory[i].namn, inventory[i].lagersaldo, inventory[i].varunummer);
         }
    }
    
    
    int main (void)
    {
        struct storagemanipulation inventory[4];
        char file[30], buffer[1024], name[100];
        int count = 0, size;
        FILE *fp;
        
          
        printf("Enter filename\n");
        scanf(" %s", file);
        
        
         //Open for append; open 
         //(or create if the file does not exist) 
         //for update at the end of the file.
        if ((fp=fopen(file,"a+") ) == NULL )
             
             {
                printf("cannot create file\n");
                return -1;
            }
             
            // check to see if file is empty
            // for first open if it is a fresh file. 
            // just to play it safe.
            
            fseek (fp, 0, SEEK_END); // go to end of file
            size = ftell(fp); // get size
    
    
            // put back to front of file just in case
            // that part all depends on how your file is, if it is a new file,
            //already has information in it, and you do not want to over write it
            // then you'll need to set it accordingly. 
    
                    fseek(fp,0,SEEK_SET);
            
            if ( size == 0 )
            {
                printf("File is empty\n"
                "please add data to file\n");
                            
                while ( count < 4)
                {    
                    
                    printf("enter name, item nuber, and number\n");
                    
                    
                    fgets(buffer, sizeof buffer, stdin);
                    scanf(" %s%d%d", strcpy(inventory[count].namn,name), &inventory[count].lagersaldo,
                        &inventory[count].varunummer);
                    count++;
                 
                }        
             
            }
            else
            readFromFile(fp, 4, inventory);
            
            saveToFile(fp, 4, inventory);
              
     
         
         for ( int f = 0; f < 4; f++)
            printf("%s %d %d\n",  inventory[f].namn, inventory[f].lagersaldo,
                        inventory[f].varunummer);
            
         
           fclose(fp);
            return 0;
     }
    Last edited by userxbw; 12-15-2017 at 09:06 AM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Working with files v2
    By Khabz in forum C++ Programming
    Replies: 5
    Last Post: 04-20-2013, 02:22 PM
  2. Working with files
    By Khabz in forum C++ Programming
    Replies: 15
    Last Post: 04-14-2013, 06:22 AM
  3. Replies: 4
    Last Post: 12-11-2011, 04:25 PM
  4. working with C files
    By Max^Power in forum C Programming
    Replies: 5
    Last Post: 07-07-2006, 06:02 PM
  5. Working with files in C
    By fmchrist in forum C++ Programming
    Replies: 2
    Last Post: 12-27-2005, 02:28 PM

Tags for this Thread