Thread: Reading from a text file

  1. #1
    Registered User
    Join Date
    Mar 2009
    Posts
    8

    Unhappy Reading from a text file

    Basically what i'm trying to do (sorry if this has already been answered; i haven't found anything like what i need.) is read in a file (text based) and have 3 variables. 1) Name, 2) Another name, 3) Unknown length of a message. It is in a C program and fscanf just isn't cutting it for me. I have tried using tokens and so forth and cannot achieve what I'm after. The one time I was able to read it in properly, I couldn't get the data that was read in to copy to a single variable. What will essentially happen is i'll have the data read in to some variables and then copy them to an array/structure. When i try to copy the data from the variables to another single variable, it either overwrites the existing data or will not add spaces (runsthemtogether). I have somehow deleted all the code that worked in attempts to get it working properly so I really don't have anything useful to go on. Does anyone know of a page i can reference or know how to do what i'm wanting to do? Thanks for reading.

    Also: The file has an unknown amount of lines. The names are only going to be 1 word each (no spaces or anything). The message may or may not be seperated by spaces and can be one word or many words.

  2. #2
    Registered User carrotcake1029's Avatar
    Join Date
    Apr 2008
    Posts
    404
    From what it sounds like, you might want to read the file into memory ahead of time, maybe with one line corresponding to one element of an array. Then you could probably use fscanf on every element of the array and it should come out nicely.

    Show some code and maybe what you were trying was on the right track, but you may have overlooked something.

  3. #3
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Are you saying you have a record with three fields:

    Code:
    struct Record {
      char Name1[];
      char Name2[];
      char *Message[]
    }records;
    Maybe you could use an array of such records?

    If you have an unknown amount of lines, then you'll have to deal with a finite amount of lines, first, and then bring in more lines from the file. Obviously the resources of the computer are finite, so the size of the input is always an issue.

  4. #4
    Registered User
    Join Date
    Mar 2009
    Posts
    8
    I have already created the structure and it works fine. I'm just trying to read in from the file. carrotcake: i'll hunt down an older version of the file where i haven't completely fubar'd the code to post here. i appreciate the help from you guys..

  5. #5
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Usign fgets() instead of fscanf() may help.

    --
    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.

  6. #6
    Registered User
    Join Date
    Mar 2009
    Posts
    8

    Unhappy

    Sorry it's taken so long to reply; Been keeping myself busy. Anyway, for the sake of argument, i've created a test program and a test file. The following is the code of the test file in which I've tried two approaches without successfully doing what I want.

    Code:
    #include <stdio.h>
    
    #define file "test.txt"
    
    main()
    {
    	FILE *fp = fopen(file, "r");
    	char *word1, *word2, *phrase[256], *rest;
    
    /*	while(fgets(phrase, 256, fp) != NULL) {
    		*word1 = strtok(phrase, ";");
    		*word2 = strtok(phrase, ";");
    		*rest = strtok(phrase, ";");
    		printf("%s - %s - %s", word1, word2, rest);
    	}
    */
    	while(fscanf(fp, "%s ;", word1) != EOF && fscanf(fp, "%s ;", word2) != NULL && fscanf(fp, "%s ;", phrase) != NULL)
    		printf("word: %s, word2: %s, phrase: %s", word1, word2, phrase);
    
    	fclose(fp);
    }
    And here's the test file's contents:
    Code:
    test1 ; test2 ; this is a test ;
    I have attempted with and without semicolons as seperators (both in the test file and in the while loops).

  7. #7
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    %s reads till the whitespace

    to read till the ;
    you need different format
    %[^;]
    something like
    Code:
    char word1[20],word2[20],word3[20];
    fscanf("%19[^;]; %19[^;]; %19[^;];", word1,word2,word3);
    if you want the strtok approach - only the first call to strtok should receive pointer to the string, all subsequent calls need the NULL-pointer as the first argument
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  8. #8
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    You've done a couple of weird things here:
    Quote Originally Posted by chevyman2002 View Post
    Code:
    	char *word1, *word2, *phrase[256], *rest;
    
    /*	while(fgets(phrase, 256, fp) != NULL) {
    		*word1 = strtok(phrase, ";");
    		*word2 = strtok(phrase, ";");
    That's an array of 256 char pointers, which you probably want "phrase[256]" instead.
    That's dereferencing the pointer (inappropriate), get rid of the asterisk.
    After you submit the pointer to a string once to strtok, don't do it again until you want to use a different string -- use strtok(NULL,";"). Also, strtok destroys the string so you may have problems assigning pointers this way, and you definitely will get a truncated string the next time you use "phrase". So you at least need to use a copy of phrase and not phrase itself, using one for strtok and one for the final fscanf.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  9. #9
    Registered User
    Join Date
    Mar 2009
    Posts
    8

    Talking [resolved]

    Quote Originally Posted by vart View Post
    %s reads till the whitespace

    to read till the ;
    you need different format
    %[^;]
    something like
    Code:
    char word1[20],word2[20],word3[20];
    fscanf("%19[^;]; %19[^;]; %19[^;];", word1,word2,word3);
    if you want the strtok approach - only the first call to strtok should receive pointer to the string, all subsequent calls need the NULL-pointer as the first argument
    Took me a minute to realize the fscanf() line was missing the file pointer ;P -- Using something like this worked beautifully. I never knew you could use those types of formats (only knew of %s %d, etc....).

    You've done a couple of weird things here:

    Quote:
    Originally Posted by chevyman2002
    Code:
    char *word1, *word2, *phrase[256], *rest;

    /* while(fgets(phrase, 256, fp) != NULL) {
    *word1 = strtok(phrase, ";");
    *word2 = strtok(phrase, ";");

    That's an array of 256 char pointers, which you probably want "phrase[256]" instead.
    That's dereferencing the pointer (inappropriate), get rid of the asterisk.
    After you submit the pointer to a string once to strtok, don't do it again until you want to use a different string -- use strtok(NULL,";"). Also, strtok destroys the string so you may have problems assigning pointers this way, and you definitely will get a truncated string the next time you use "phrase". So you at least need to use a copy of phrase and not phrase itself, using one for strtok and one for the final fscanf.
    Thanks for your input! That actually helps me understand strtok a bit better.

    The final [working] example/testing program (to avoid recompiling my real project everytime):

    Code:
    #include <stdio.h>
    
    #define file "test.txt"
    
    main()
    {
    	FILE *fp = fopen(file, "r");
    	char *word1[32], *word2[32], *phrase[50];
    
    	while(fscanf(fp, "%s %s %50[^;];", word1, word2, phrase) != EOF) {
    		printf("w1: %s\n", word1);
    		printf("w2: %s\n", word2);
    		printf("p: %s\n", phrase);
    	}
    
    	fclose(fp);
    }
    Thanks a lot for all the help, you guys. I hope that people are able to benefit from this post; I never could find something like this listed anywhere..

  10. #10
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    word1 should be

    char word1[32]

    as well as word2 and phrase

    %s format should be used with the width specifier as well
    %31s

    because the phrase is (should be) array of 50 chars - width specifier should be 1 less - 49 to leave space for nul-terminator which scanf will add after it reads 49 chars (if no ; occured before it)
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  11. #11
    Registered User
    Join Date
    Mar 2009
    Posts
    8

    Talking

    Quote Originally Posted by vart View Post
    word1 should be

    char word1[32]

    as well as word2 and phrase

    %s format should be used with the width specifier as well
    %31s

    because the phrase is (should be) array of 50 chars - width specifier should be 1 less - 49 to leave space for nul-terminator which scanf will add after it reads 49 chars (if no ; occured before it)
    Good point.. I'll change it as necessary.. Thanks a lot for the help!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Formatting the contents of a text file
    By dagorsul in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2008, 12:36 PM
  2. Inventory records
    By jsbeckton in forum C Programming
    Replies: 23
    Last Post: 06-28-2007, 04:14 AM
  3. C++ std routines
    By siavoshkc in forum C++ Programming
    Replies: 33
    Last Post: 07-28-2006, 12:13 AM
  4. Reading Character at a time from a text file
    By Giania in forum C Programming
    Replies: 8
    Last Post: 02-25-2006, 03:17 PM
  5. A bunch of Linker Errors...
    By Junior89 in forum Windows Programming
    Replies: 4
    Last Post: 01-06-2006, 02:59 PM