Thread: From File To Memory

  1. #1
    Registered User
    Join Date
    Jul 2006
    Location
    Philippines
    Posts
    27

    Unhappy From File To Memory

    what i'm trying to basically do is copy a txt file to the memory but it's not working and i aint sure why..pls help me. thanx a lot.

    here is my struct:
    Code:
    typedef char string7[8];
    typedef char string15[16];
    typedef char string50[51];
    
    typedef struct //structure of the word
    {
           string7 strWord;
           string15 strType;
           int nLetters;
           int nDefinitions;
           string50 strDefinitions[5];
    }structWord;
    here is the code:
    Code:
    void loadDictionary(structWord aWords[], int nWordNumber, FILE *pFile)
    {
         int i, nChoice, j, k;
         char *p;
         string50 strTemp;
         
         for(i = 0; i < nWordNumber; i++)
         {
               fgets(aWords[i].strWord, sizeof(aWords[i].strWord), pFile);
               for(k=0; k<8; k++) if (aWords[i].strWord[k]=='\n')aWords[i].strWord[k]='\0';
               
               fgets(aWords[i].strType, sizeof(aWords[i].strType), pFile);
               for(k=0; k<15; k++) if (aWords[i].strWord[k]=='\n')aWords[i].strWord[k]='\0';
               
               fscanf(pFile, "%d", &aWords[i].nLetters);
               fscanf(pFile, "%d", &aWords[i].nDefinitions);
               
               for(j = 0; j < aWords[i].nDefinitions; j++)
               {
                     fgets(aWords[i].strDefinitions[j], sizeof(string50), pFile);
                     for(k=0; k<50; k++) if (aWords[i].strWord[k]=='\n')aWords[i].strWord[k]='\0';
               }
         }
    }
    here is a part of the dictionary and the supposed screen ouptut:
    Code:
    History
    Noun
    7
    2
    a telling of events
    a written report of past events
    Disband
    Verb
    7
    1
    to break up and stop being a group
    but when i try to print them out, the screen ouput is this!
    Code:
    //the code
              puts(aWords[0].strWord);
              puts(aWords[0].strType);
              printf("%d", aWords[0].nLetters);
              printf("%d", aWords[0].nDefinitions);
              puts(aWords[0].strDefinitions[0]);
              puts(aWords[0].strDefinitions[1]);
              puts(aWords[1].strWord);
              puts(aWords[1].strType);
              printf("%d", aWords[0].nLetters);
              printf("%d", aWords[0].nDefinitions);
              puts(aWords[1].strDefinitions[0]);  
    //the ouput
    History
    
    00
    
    Noun
    7
    00
    why is it?!
    Last edited by jarvis; 11-25-2006 at 12:40 AM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > fscanf(pFile, "%d", &aWords[i].nLetters);
    Mixing fscanf and fgets is the problem.

    Use something like
    char temp[BUFSIZ];
    fgets( temp, sizeof temp, pFile );
    sscanf( temp, "%d", &aWords[i].nLetters);

    > for(k=0; k<8; k++) if (aWords[i].strWord[k]=='\n')aWords[i].strWord[k]='\0';
    This is awfully specific to each line, as you have a different loop count for each line.
    Change the array size, and this becomes very error prone.

    char *p = strchr( aWords[i].strWord, '\n' ); // find the newline, if there is one
    if ( p != NULL ) *p = '\0'; // erase the one and only newline which fgets can return.
    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
    Jul 2006
    Location
    Philippines
    Posts
    27
    thanx a lot! i'll try to understand the code you gave!thanx again!

  4. #4
    Registered User
    Join Date
    Jul 2006
    Location
    Philippines
    Posts
    27
    Code:
    void loadDictionary(structWord aWords[], int nWordNumber, FILE *pFile)
    {
         int i, nChoice, j, k;
         char *p, temp[BUFSIZ];
         string50 strTemp;
         
         for(i = 0; i < nWordNumber; i++)
         {
               fgets(aWords[i].strWord, sizeof(aWords[i].strWord), pFile);
               if ((p = strchr(aWords[i].strWord, '\n')) != NULL)
                  *p = '\0';
               
               fgets(aWords[i].strType, sizeof(aWords[i].strType), pFile);
               if ((p = strchr(aWords[i].strWord, '\n')) != NULL)
                  *p = '\0';
               
               fgets(temp, sizeof(temp), pFile );
               sscanf( temp, "%d", &aWords[i].nLetters);
               fgets( temp, sizeof(temp), pFile );
               sscanf( temp, "%d", &aWords[i].nDefinitions);
               
               for(j = 0; j < aWords[i].nDefinitions; j++)
               {
                     fgets(aWords[i].strDefinitions[j], sizeof(aWords[i].strDefinitions[j]), pFile);
                     if ((p = strchr(aWords[i].strWord, '\n')) != NULL)
                        *p = '\0';
               }
         }
    }
    here is the code now, but the screen output is still not what i expected!this is much trouble.

    i have to mix fscanf, and fgets because i need to copy a string, and then an integer, so you see i have to get into that trouble. i do not know what sscanf does, but from your code, it is still not working..

  5. #5
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    You don't have to mix them.

    Read the data in with fgets(), then convert the things you need into numbers. Then you use the "breakpoint", which the converting function (strtol()) gave you and do something with the word that comes after the number.
    "The Internet treats censorship as damage and routes around it." - John Gilmore

  6. #6
    Registered User
    Join Date
    Jul 2006
    Location
    Philippines
    Posts
    27
    i really think i'm getting close in solving this now..
    i really don't know what u meant by breakpoint but anyway, here is the code"
    Code:
               fgets(cNum, sizeof(cNum), pFile); //line 1005
               aWords[i].nLetters = atoi(cNum);
               
               fgets(cNum, sizeof(cNum), pFile); //line 1008
               aWords[i].nDefinitions = atoi(cNum);
    from what i read, atoi is dangerous but i used anyway because i am not going to ask an input from a user and it is certain that the line from the file it is supposed to read is an integer, so there. cNum is declared as char. but there's an error:

    Code:
    1005 and 1008 D:\JarvB's Documents\JarvB's Files\DLSU\Compiler\Text Twist\10618384--PHASE2.c [Warning] passing arg 1 of `fgets' makes pointer from integer without a cast
    cNum was declared as char so what integer is this error talkin about?

  7. #7
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    Could you show your declaration of cNum? And use strtol(), not atoi().
    "The Internet treats censorship as damage and routes around it." - John Gilmore

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > typedef char string7[8];
    But "History\n\0" (as returned by fgets()) is 9 characters, not 8

    So my first set of results look like this
    Code:
    $ cat new.txt && ./a.exe
    History
    Noun
    7
    2
    a telling of events
    a written report of past events
    Disband
    Verb
    7
    1
    to break up and stop being a group
    
    0
    word=History
    type=
    Num string=Noun, val=0
    Num string=7, val=7
    1
    word=to brea
    type=k up and stop b
    Num string=eing a group, val=2089872920
    Num string=, val=2089878896
    It's already gone wrong by the time the first type is read, so after that everything is out of sync.

    By allowing an extra space in the strings, I get
    Code:
    0
    word=History
    type=Noun
    Num string=7, val=7
    Num string=2, val=2
    1
    word=Disband
    type=Verb
    Num string=7, val=7
    Num string=1, val=1
    Here's the full code - note that your newline clearing code always used the same array (more copy/paste errors).
    Code:
    #include <stdio.h>
    #include <string.h>
    
    // +1 for the \n fgets() returns, which we eliminate
    // +1 for the \0 at the end of every string
    typedef char string7[8+1+1];
    typedef char string15[16+1+1];
    typedef char string50[51+1+1];
    
    typedef struct                  //structure of the word
    {
        string7 strWord;
        string15 strType;
        int nLetters;
        int nDefinitions;
        string50 strDefinitions[5];
    } structWord;
    
    char *fgetsNoNewline(char *buff, size_t bufsiz, FILE * fp)
    {
        char *result;
        result = fgets(buff, bufsiz, fp);
        if (result != NULL) {
            char *p = strchr(buff, '\n');
            if (p != NULL)
                *p = '\0';
        }
        return result;
    }
    
    void loadDictionary(structWord aWords[], int nWordNumber, FILE * pFile)
    {
        int i, j;
        char temp[BUFSIZ];
    
        for (i = 0; i < nWordNumber; i++) {
            printf("%d\n", i);
    
            fgetsNoNewline(aWords[i].strWord, sizeof(aWords[i].strWord), pFile);
            printf("word=%s\n", aWords[i].strWord);
    
            fgetsNoNewline(aWords[i].strType, sizeof(aWords[i].strType), pFile);
            printf("type=%s\n", aWords[i].strType);
    
            fgetsNoNewline(temp, sizeof(temp), pFile);
            sscanf(temp, "%d", &aWords[i].nLetters);
            printf("Num string=%s, val=%d\n", temp, aWords[i].nLetters);
    
            fgetsNoNewline(temp, sizeof(temp), pFile);
            sscanf(temp, "%d", &aWords[i].nDefinitions);
            printf("Num string=%s, val=%d\n", temp, aWords[i].nDefinitions);
    
            for (j = 0; j < aWords[i].nDefinitions; j++) {
                fgetsNoNewline(aWords[i].strDefinitions[j], sizeof(aWords[i].strDefinitions[j]), pFile);
            }
        }
    }
    
    int main()
    {
        structWord arr[2];
        FILE *fp = fopen("new.txt", "r");
        if (fp != NULL) {
            loadDictionary(arr, 2, fp);
            fclose(fp);
            // print a couple of samples
            printf("%s\n", arr[0].strWord);
            printf("%s\n", arr[1].strDefinitions[0]);
        }
        return 0;
    }
    Actually, because you allocate such small space, your code is very vunerable to minor formatting mistakes in the input file.
    So where you have
    fgetsNoNewline(aWords[i].strWord, sizeof(aWords[i].strWord), pFile);

    It should really be
    fgetsNoNewline(temp,sizeof temp, pFile);
    temp[ sizeof(aWords[i].strWord) - 1] = '\0'; // make sure the string is always short enough
    strcpy( aWords[i].strWord, temp ); // and copy it.

    This truncate and copy should be done as a separate function as well.

    Also, sscanf returns a result as well, which you should check before trying to use the converted answer.
    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.

  9. #9
    Registered User
    Join Date
    Jul 2006
    Location
    Philippines
    Posts
    27
    i originally declared it as

    Code:
    char cNum;
    
    //but then i changed it to:
    char *cNum;
    
    //then there are no more syntax errors
    but then the program suddenly crashes when i call the function

    i am quite confused with the parameters with strtol(), i am just trying to learn it now.
    this is my code:
    Code:
    void loadDictionary(structWord aWords[], int nWordNumber, FILE *pFile)
    {
         int i, nChoice, j;
         char *p, *q;
         char *cNum;
         string50 strTemp;
         
         for(i = 0; i < nWordNumber; i++)
         {
               fgets(aWords[i].strWord, sizeof(aWords[i].strWord), pFile);
               if ((p = strchr(aWords[i].strWord, '\n')) != NULL)
                  *p = '\0';
               
               fgets(aWords[i].strType, sizeof(aWords[i].strType), pFile);
               if ((p = strchr(aWords[i].strWord, '\n')) != NULL)
                  *p = '\0';
               
               fgets(cNum, sizeof(cNum), pFile);
               aWords[i].nLetters = strtol(cNum, &q, 10);
               
               fgets(cNum, sizeof(cNum), pFile);
               aWords[i].nDefinitions = strtol(cNum, &q, 10);
               
               for(j = 0; j < aWords[i].nDefinitions; j++)
               {
                     fgets(aWords[i].strDefinitions[j], sizeof(aWords[i].strDefinitions[j]), pFile);
                     if ((p = strchr(aWords[i].strWord, '\n')) != NULL)
                        *p = '\0';
               }
         }
    the program crashes due to the cNum declaration

  10. #10
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    You do not allocate memory to it!
    "The Internet treats censorship as damage and routes around it." - John Gilmore

  11. #11
    Registered User
    Join Date
    Jul 2006
    Location
    Philippines
    Posts
    27
    what's that suppose to mean?

  12. #12
    Reverse Engineer maxorator's Avatar
    Join Date
    Aug 2005
    Location
    Estonia
    Posts
    2,318
    Go back and start learning the basics if you don't know what that means. Noone is going to explain you the whole thing of pointers and memory here.
    "The Internet treats censorship as damage and routes around it." - John Gilmore

  13. #13
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Tsk. Don't discourage people out of laziness.

    char *cNum;

    //then there are no more syntax errors
    But syntax errors aren't the end of the world. Right now, as you've declared it cNum doesn't point to memory or another object, making it "wild." You cannot dereference a wild pointer because it points to an undefined location.

  14. #14
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    *shrug*
    You're not going anwhere until you figure out that 9 bytes won't fit into 8.
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 7
    Last Post: 02-06-2009, 12:27 PM
  2. Data Structure Eror
    By prominababy in forum C Programming
    Replies: 3
    Last Post: 01-06-2009, 09:35 AM
  3. Inventory records
    By jsbeckton in forum C Programming
    Replies: 23
    Last Post: 06-28-2007, 04:14 AM
  4. Writing input from a file into shared memory
    By RazielX in forum C Programming
    Replies: 2
    Last Post: 09-23-2004, 12:34 PM
  5. Unknown Memory Leak in Init() Function
    By CodeHacker in forum Windows Programming
    Replies: 3
    Last Post: 07-09-2004, 09:54 AM