How to read specific characters with fscanf

  • (2 Pages)
  • +
  • 1
  • 2

19 Replies - 5823 Views - Last Post: 04 March 2010 - 05:45 PM Rate Topic: -----

#1 ge0rge007  Icon User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 33
  • Joined: 05-June 09

How to read specific characters with fscanf

Posted 08 February 2010 - 12:54 PM

Hello all -.-
I need some help with fscanf.
I have a txt file and every line looks like this : aas,d2d,sgh
I have to read this text file and separate each word like "aas" etc. I have read the manual page here.It says the following for the "c" type specifier :

Quote

Single character: Reads the next character. If a width different from 1 is specified, the function reads width characters and stores them in the successive locations of the array passed as argument. No null character is appended at the end.

I can not find how to change the width so i could read the first 3 letters for the first word etc.
Here is the code with the default value of width (1) :
#include <stdio.h>

int main() {
  FILE *file;
  char word1;
  file = fopen("fscanf.txt", "r");

  while(!feof(file)) { 
     fscanf(file,"%c", &word1);
   }

    fclose(file);
    return 0;
  }



Thanks in advance :tup:

Is This A Good Question/Topic? 0
  • +

Replies To: How to read specific characters with fscanf

#2 Martyn.Rae  Icon User is offline

  • The programming dinosaur
  • member icon

Reputation: 540
  • View blog
  • Posts: 1,406
  • Joined: 22-August 09

Re: How to read specific characters with fscanf

Posted 08 February 2010 - 01:05 PM

If you want to read more than one character using fscanf, then you need to specify a width. So

  word1[3];

  fscanf(fscanf(file,"%3c", word1);



would read three characters into word1. Notice that I have redefined word1 as an array of 3 characters, and dropped the address-of operator (&) from the 'word1' parameter in the fscanf call.

Hope that helps.
Was This Post Helpful? 0
  • +
  • -

#3 Guest_c.user*


Reputation:

Re: How to read specific characters with fscanf

Posted 08 February 2010 - 06:36 PM

    while (fscanf(file, "%3c,", word1) == 1)
        ;


This post has been edited by c.user: 08 February 2010 - 06:38 PM

Was This Post Helpful? 0

#4 David W  Icon User is offline

  • DIC supporter
  • member icon

Reputation: 281
  • View blog
  • Posts: 1,788
  • Joined: 20-September 08

Re: How to read specific characters with fscanf

Posted 08 February 2010 - 10:12 PM

You will need to skip over the comma's some how ... and you may like to have each 'word' terminated by a '\0' char ... so that you can print the words out as a C string. So, you may need more than just 3 char's to hold each word. Two examples follow:


#include <stdio.h>

int main()
{
    char word[4]; /* leave space for '\0' char ... at end */
    FILE *file;
    file = fopen( "fscanf.txt", "r" );

    while( fscanf( file, "%3c %*c", word) == 1 ) /* Note: %*c to skip 1 char */
    {
        word[3] = '\0'; /* terminate word  ... so can print C string */
        printf( "%s\n", word );
    }
    fclose( file );
    getchar();
    return 0;
}

/*
will read ok ... a one line file with no coma at the end

abd,def,ghi,jkl,abd,def,ghi,jkl,xxx,yyy,zzz

BUT NOT: (with extra spaces)

abd,def, ghi,jkl, abd,def,ghi,jkl

NOR: (trailing comma)

abc,def,ghi,

NOR: (on different lines)

abd,def,ghi,jkl
abd,def,ghi,jkl
abd,def,ghi,jkl
*/





Or ... if you need to get 'words' in a file and skip over any combination of delimiter characters, like '\n', '\t', space, ',' etc. ... you might like to use this:

/* readWord.c // test program needs test file in same folder as .exe file // */

/* readWord.h */

#ifndef _READ_WORD_
#define _READ_WORD_

/*  http://developers-heaven.net/forum/index.php/topic,46.0.html  */

#include <stdio.h>
#include <stdlib.h>

/*
    Safe string data entry from file ... BUT free new memory ... when done!
    Don't forget that C strings are pointers to a block of char, with a '\0'
    char at the terminal end ... Call like this:

    char* word = readWord( fp, 32, "\n\t ,.;:" ); // note ex. delimiter string
    
    or ...
    
    while( (word = readWord( FILEp, startChunkSize, delimitersStr ) )
    {
        //
    }
*/

/* used by readWord ... returns 1 if char in str, otherwise returns 0 */
int charInStr( char c, char str[] ); 

/* returns a string in new memory holding each word ... or NULL if EOF */
char* readWord( FILE* fp, int chunk_len, char delimits[] )
{
    char* strData;
    int c, i = 0; /* c to hold each char, i for index in string ... */
    if( chunk_len < 1 ) chunk_len = 3; /* set to min. starting chunk size */
    strData = (char*) calloc( chunk_len+1, 1 );

    while( (c = fgetc( fp )) != EOF && charInStr(c, delimits) ) ; /* advance */
    
    if( c != EOF ) strData[i++] = c; /* ok ... get this first char in the str */
    
    while( (c = fgetc( fp )) != EOF && !charInStr(c, delimits) ) 
    {
        if( i == chunk_len-1 ) /*  get more memory now ... (for word or line) */
        {
            chunk_len += chunk_len; /* double memory ...*/
            realloc( strData, chunk_len+1 );
        }
        strData[i] = c;
        ++i;
    }
    strData[i] = 0; /* confirm termination */

    if( strData[0] != 0 ) return (char*) realloc( strData, i+1 );
    if( c == EOF ) { free( strData); return NULL; } /* 'free' thanks to c.user */
    return (char*) realloc( strData, i+1 );
}

int charInStr( char c, char str[] )
{
    for( ; *str != 0; ++str )
        if( c == *str ) return 1;
    return 0;
}

#endif


/* readWord.c // test program // */

/* #include "readWord.h" */

#define TEST_FILE "readWord.txt"

int main()
{
    FILE* fp = fopen( TEST_FILE, "r" );
    char* word;
    char delimits[] = "\n\t ,.;:";
    
    puts( " === " TEST_FILE " ===" );
    while( (word = readWord(fp, 31, delimits)) )
    {
        printf( "%s\n", word );
        free( word );
    }
    puts( "===" );
    
    fclose( fp );
    getchar();
    return 0;
}

/*  file name: "readWord.txt" */

/*
abd def
ghi,jkl

mn,    opqrst     uv;wxyz,
mn,    opqrst    ;   ;    uv,

wxyz
,


,
*/

/* output ... */

/*
 === readWord.txt ===
abd
def
ghi
jkl
mn
opqrst
uv
wxyz
mn
opqrst
uv
wxyz
===
*/

Attached File(s)


This post has been edited by David W: 09 February 2010 - 08:08 PM

Was This Post Helpful? 0
  • +
  • -

#5 David W  Icon User is offline

  • DIC supporter
  • member icon

Reputation: 281
  • View blog
  • Posts: 1,788
  • Joined: 20-September 08

Re: How to read specific characters with fscanf

Posted 09 February 2010 - 02:45 AM

You may like to see the edit above ...
Was This Post Helpful? 0
  • +
  • -

#6 Guest_c.user*


Reputation:

Re: How to read specific characters with fscanf

Posted 09 February 2010 - 07:32 PM

    if( c == EOF ) return NULL;


this is a memory leak
for
strData = (char*) calloc( chunk_len+1, 1 );



int charInStr( char c, char str[] )


strchr(str, c);

every allocation should be checked for a NULL pointer (malloc, calloc, realloc)
it is a good practice to check an fopen call for a NULL pointer too (if a file wasn't opened, you may waste your time to know, why the OPENED file is not reading correctly and spend your time by switching modes of the opening and changing reading methods when the cause is so simple)

but I liked a clear algorithm, I see it, hence it is good

This post has been edited by c.user: 09 February 2010 - 07:36 PM

Was This Post Helpful? 0

#7 David W  Icon User is offline

  • DIC supporter
  • member icon

Reputation: 281
  • View blog
  • Posts: 1,788
  • Joined: 20-September 08

Re: How to read specific characters with fscanf

Posted 09 February 2010 - 08:23 PM

View Postc.user, on 09 February 2010 - 08:32 PM, said:

    if( c == EOF ) return NULL;


this is a memory leak
for
strData = (char*) calloc( chunk_len+1, 1 );



int charInStr( char c, char str[] )


strchr(str, c);

every allocation should be checked for a NULL pointer (malloc, calloc, realloc)
it is a good practice to check an fopen call for a NULL pointer too (if a file wasn't opened, you may waste your time to know, why the OPENED file is not reading correctly and spend your time by switching modes of the opening and changing reading methods when the cause is so simple)

but I liked a clear algorithm, I see it, hence it is good


Thanks ... especially for pointing out the memory leak. What do you suggest for students in C to do, after allocating memory ... or attempting to open a file? (I miss the exception handling available in HLA ... what comes to mind just now is an assert function.)

My concern for students, so far, has been on getting valid/crash free data input from keyboard ... and I have sort of overlooked the other validation/crash proofing.

This post has been edited by David W: 09 February 2010 - 08:30 PM

Was This Post Helpful? 0
  • +
  • -

#8 David W  Icon User is offline

  • DIC supporter
  • member icon

Reputation: 281
  • View blog
  • Posts: 1,788
  • Joined: 20-September 08

Re: How to read specific characters with fscanf

Posted 09 February 2010 - 10:33 PM

C students may like to use something like this, instead of fscanf or scanf

(now with asserts, thanks to c.user)

/* readWord.c // test program needs test file in same folder as .exe file // */

/* readWord.h */

#ifndef _READ_WORD_
#define _READ_WORD_

/*  http://developers-heaven.net/forum/index.php/topic,46.0.html  */

#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* re. strchr */

/*
    Safe string data entry from file ... BUT free new memory ... when done!
    Don't forget that C strings are pointers to a block of char, with a '\0'
    char at the terminal end ... Call like this:

    char* word = readWord( fp, 32, "\n\t ,.;:" ); // note ex. delimiter string
    
    or ...
    
    while( (word = readWord( FILEp, startChunkSize, delimitersStr )) )
    {
        //
    }
*/

void myAssert( int condition, char text[] );

/* returns a string in new memory holding each word ... or NULL if EOF */
char* readWord( FILE* fp, int chunk_len, char delimits[] )
{
    char* strData;
    int c, i = 0; /* c to hold each char, i for index in string ... */
    if( chunk_len < 1 ) chunk_len = 3; /* set to min. starting chunk size */
    strData = (char*) calloc( chunk_len+1, 1 );
    myAssert( (strData != NULL), "Error getting memory ..." );

    while( (c = fgetc( fp )) != EOF && strchr(delimits, c) ) ; /* advance */
    
    if( c != EOF ) strData[i++] = c; /* ok ... get this first char in the str */
    
    while( (c = fgetc( fp )) != EOF && !strchr(delimits, c) )
    {
        if( i == chunk_len-1 ) /*  get more memory now ... (for word or line) */
        {
            chunk_len += chunk_len; /* double memory ...*/
            realloc( strData, chunk_len+1 );
            myAssert( (strData != NULL), "Error getting memory ..." );
        }
        strData[i] = c;
        ++i;
    }
    strData[i] = 0; /* confirm termination */

    /* if EOF and empty line ... quit reading file ... */
    if( c == EOF && strData[0] == 0 ) { free( strData); return NULL; }
    
    /* else ... */
    realloc( strData, i+1 );
    myAssert( (strData != NULL), "Error getting memory ..." );
    return strData;
}

void myAssert( int condition, char text[] )
{
    if( !condition )
    {
        puts( text );
        fputs( "Press 'Enter' to exit program ... ", stdout );
        getchar();
        exit(1);
    }
}

#endif


/* readWord.c // test program // */

/* #include "readWord.h" */

#define TEST_FILE "readWord.txt"

int main()
{
    FILE* fp;
    char* word;
    char delimits[] = "\n\t ,.;:";
    fp = fopen( TEST_FILE, "r" );
    myAssert( (fp != NULL), "ERROR opening File ..."  );

    puts( " === " TEST_FILE " ===" );
    while( (word = readWord(fp, 31, delimits)) )
    {
        printf( "%s\n", word );
        free( word );
    }
    puts( "===" );
    
    fclose( fp );

    puts( "\n === KEY BOARD ... 'Ctrl C to exit' ... ===" );
    while
    (
        printf( "Enter 'words' : " ) &&
        (word = readWord(stdin, 31, delimits))
    )
    {
        printf( "%s\n", word );
        free( word );
    }
    puts( " ===> Press 'Enter' to exit ===> " );
    getchar();
    return 0;
}

/*  file name: "readWord.txt" */

/*
abd def
ghi,jkl

mn,    opqrst     uv;wxyz,
mn,    opqrst    ;   ;    uv,

wxyz
,


,
*/

/* output ... */

/*
 === readWord.txt ===
abd
def
ghi
jkl
mn
opqrst
uv
wxyz
mn
opqrst
uv
wxyz
===
*/


This post has been edited by David W: 14 February 2010 - 03:24 AM

Was This Post Helpful? 0
  • +
  • -

#9 Guest_c.user*


Reputation:

Re: How to read specific characters with fscanf

Posted 10 February 2010 - 12:35 AM

    realloc( strData, i+1 );
    myAssert( (strData != NULL), "Error getting memory ..." );


realloc will not change strData in error case

Quote

4.10.3.4 The realloc function

Synopsis

#include <stdlib.h>
void *realloc(void *ptr, size_t size);

Description

The realloc function changes the size of the object pointed to by
ptr to the size specified by size . The contents of the object shall
be unchanged up to the lesser of the new and old sizes. If the new
size is larger, the value of the newly allocated portion of the object
is indeterminate. If ptr is a null pointer, the realloc function
behaves like the malloc function for the specified size. Otherwise,
if ptr does not match a pointer earlier returned by the calloc ,
malloc , or realloc function, or if the space has been deallocated by
a call to the free or realloc function, the behavior is undefined. If
the space cannot be allocated, the object pointed to by ptr is
unchanged.
If size is zero and ptr is not a null pointer, the object
it points to is freed.

Returns

The realloc function returns either a null pointer or a pointer to
the possibly moved allocated space.


an assert macro (which is embedded) prints to stderr also

    if( !condition )
    {
        puts( text );
        fputs( "Press 'Enter' to exit program ... ", stdout );
        getchar();
        exit(1);
    }


then there is one moment when you print an error message to stdout instead of stderr

This post has been edited by c.user: 10 February 2010 - 03:45 AM

Was This Post Helpful? 0

#10 ge0rge007  Icon User is offline

  • New D.I.C Head

Reputation: 2
  • View blog
  • Posts: 33
  • Joined: 05-June 09

Re: How to read specific characters with fscanf

Posted 11 February 2010 - 12:06 PM

Guys you are really amazing!:)
Thank you very much for your answers!
I will check all the solutions now :look:
Was This Post Helpful? 0
  • +
  • -

#11 David W  Icon User is offline

  • DIC supporter
  • member icon

Reputation: 281
  • View blog
  • Posts: 1,788
  • Joined: 20-September 08

Re: How to read specific characters with fscanf

Posted 14 February 2010 - 01:26 AM

View Postge0rge007, on 11 February 2010 - 01:06 PM, said:

Guys you are really amazing!:) Thank you very much for your answers! I will check all the solutions now :look:


You are welcome ... and with thanks to c.user ... an update that attempts to incorporate his C insights ...

/* readWord.c // test program needs test file in same folder as .exe file // */

/* readWord.h */

#ifndef _READ_WORD_
#define _READ_WORD_

#define MEM_ERROR "ERROR allocating memory ..."

/*  http://developers-heaven.net/forum/index.php/topic,46.0.html  */

#include <stdio.h>
#include <stdlib.h>
#include <string.h> /* re. strchr */

/*
    Safe string data entry from file ... BUT free new memory when done with it!
    Don't forget that C strings are pointers to a block of char, with a '\0'
    char at the terminal end ... Call like this:

    char* word = readWord(stdin, 31, "\n\t ,.;:", &lastChr);//note delimiter str
    
    or ...
    
    while((word = readWord(FILEp, startChunkSize, delimiterStr, &lastCharRead)))
    {
        // do stuff ...
    }

    Note 1: select your initial word chunk size to minimize calls to realloc
    Note 2: address of last char passed in/out so can flush stdin or file line
*/

void myAssert( int condition, char text[] );

/* returns a string in new memory holding each word ... or NULL if EOF */
char* readWord( FILE* fp, int chunk_len, char delimits[], char* c)
{
    char * strData, * tmp;
    int i = 0; /* ... *c to hold each char, i for index in string ... */
    if( chunk_len < 1 ) chunk_len = 3; /* set to min. starting chunk size */
    
    strData = (char*) calloc( chunk_len+1, 1 ); /* cast added for C++ compilers */
    myAssert( (strData != NULL), MEM_ERROR " at '1' with calloc" );

    while( (*c = fgetc( fp )) != EOF && strchr(delimits, *c) ) ; /* advance */
    
    if( *c != EOF ) strData[i++] = *c; /* ok ... get this first char in the str */
    
    while( (*c = fgetc( fp )) != EOF && !strchr(delimits, *c) )
    {
        if( i == chunk_len-1 ) /*  get more memory now ... (for word or line) */
        {
            chunk_len += chunk_len; /* double memory ...*/
            tmp = strData;
            realloc( strData, chunk_len+1 );
            if( !strData ) free( tmp );
            myAssert( (strData != NULL), MEM_ERROR " at '2' with realloc" );
        }
        strData[i] = *c;
        ++i;
    }
    strData[i] = 0; /* confirm termination */

    /* if EOF and empty line ... quit reading file ... */
    if( *c == EOF && strData[0] == 0 ) { free( strData); return NULL; }
    
    // else ...
    tmp = strData;
    realloc( strData, i+1 ); /* since i is index of '\0' ... need size i+1 */
    if( !strData ) free( tmp );
    myAssert( (strData != NULL), MEM_ERROR " at '3' with realloc" );
    return strData;
}

void myAssert( int condition, char text[] )
{
    if( !condition )
    {
        fprintf(stderr, "%s\n", text );
        fputs( "Press 'Enter' to exit program ... ", stderr );
        getchar();
        exit(1);
    }
}

#endif


/* readWord.c // test program // */

/* #include "readWord.h" */

#define TEST_FILE "readWord.txt"
#define FILE_ERROR "ERROR opening File "
#define LEN 10

int main()
{
    int i, j;
    char last;
    char* word;
    char* raggedAry[LEN];
    char delimits[] = "\n\t ,.;:";
    FILE* fp = fopen( TEST_FILE, "r" );
    myAssert( (fp != NULL), FILE_ERROR TEST_FILE " at '4' in main function" );

    puts( " === FROM FILE '" TEST_FILE "' ===" );
    while( (word = readWord(fp, 31, delimits, &last)) )
    {
        printf( "%s\n", word );
        free( word );
    }
    puts( "===" );
    
    fclose( fp );

    i = 0;
    printf( "\n === VIA KEY BOARD enter up to %d words ===", LEN );
    printf( "\nEnter words (Enter q to quit)  : " );
    while
    (
        i < LEN &&
        (word = readWord(stdin, 31, delimits, &last))
    )
    {
        if( ((word[0] == 'q' || word[0] == 'Q') && word[1] == 0) )
        {
            free( word );
            break;
        }
        raggedAry[i++] = word;
    }

    puts( "\nYou entered ..." );
    for( j = 0; j < i; ++j )
    {
        printf( "%2d: %s\n", j+1, raggedAry[j] );
        free( raggedAry[j] );
    }

    fputs( " ===> Press 'Enter' to exit ===> ", stdout );
    /* flush stdin buffer ... */
    while( last != '\n' && last != EOF ) last = getchar();
    getchar();
    return 0;
}

/*  file name: "readWord.txt" */

/*
abd def
ghi,jkl

mn,    opqrst     uv;wxyz,
mn,    opqrst    ;   ;    uv,

wxyz
,


,
*/

/* output ... */

/*
 === readWord.txt ===
abd
def
ghi
jkl
mn
opqrst
uv
wxyz
mn
opqrst
uv
wxyz
===
*/




Also ... you may like to scan this reference:

Quote

http://en.wikipedia....tandard_streams

Standard error (stderr)

Standard error is another output stream typically used by programs to output error messages or diagnostics. It is a stream independent of standard output and can be redirected separately. The usual destination is the text terminal which started the program to provide the best chance of being seen even if standard output is redirected (so not readily observed). For example, output of a program in a pipeline is redirected to input of the next program, but errors from each program still go directly to the text terminal.

It is acceptable—and normal—for standard output and standard error to be directed to the same destination, such as the text terminal.



http://en.wikipedia.org/wiki/Malloc

Casting and type safety

malloc returns a void pointer (void *), which indicates that it is a pointer to a region of unknown data type. One may "cast" (see type conversion) this pointer to a specific type, as in

int *ptr = (int*)malloc(10 * sizeof (int));

When using C, this is considered bad practice; it is redundant under the C standard. Moreover, putting in a cast may mask failure to include the header stdlib.h, in which the prototype for malloc is found. In the absence of a prototype for malloc, the C compiler will assume that malloc returns an int, and will issue a warning in a context such as the above, provided the error is not masked by a cast.

The returned pointer need not be explicitly cast to a more specific pointer type, since ANSI C defines an implicit conversion between the void pointer type and other pointers to objects. An explicit cast of malloc's return value is sometimes performed because malloc originally returned a char *, but this cast is unnecessary in standard C code.[4][5] Omitting the cast, however, creates an incompatibility with C++, which does require it.

The lack of a specific pointer type returned from malloc is type-unsafe behaviour: malloc allocates based on byte count but not on type. This distinguishes it from the C++ new operator that returns a pointer whose type relies on the operand. The latter is closer to type-safe behaviour, though neither are type-safe since the pointer type can be overridden (see C Type Safety).

Attached File(s)


Was This Post Helpful? 0
  • +
  • -

#12 Guest_c.user*


Reputation:

Re: How to read specific characters with fscanf

Posted 14 February 2010 - 06:46 PM

    realloc( strData, chunk_len+1 );
    if( !strData ) free( tmp );


http://www.dreaminco...ndpost&p=921240
I even bolded the sentence in the stanard description of realloc

realloc will return a value, but if it will return NULL, strData will not be changed
it will not write NULL to strData

    p = (char *) realloc(strData, chunk_len+1);
    if (p == NULL) {
        free(strData);
        myAssert(0, "error: realloc can't allocate (1)");
    }
    /* you even can do strData = p; then
       but it is not necessary because
       if p != NULL, then strData is already increased */


Was This Post Helpful? 0

#13 David W  Icon User is offline

  • DIC supporter
  • member icon

Reputation: 281
  • View blog
  • Posts: 1,788
  • Joined: 20-September 08

Re: How to read specific characters with fscanf

Posted 15 February 2010 - 12:16 AM

View Postc.user, on 14 February 2010 - 07:46 PM, said:

    realloc( strData, chunk_len+1 );
    if( !strData ) free( tmp );


http://www.dreaminco...ndpost&p=921240
I even bolded the sentence in the stanard description of realloc

realloc will return a value, but if it will return NULL, strData will not be changed
it will not write NULL to strData

    p = (char *) realloc(strData, chunk_len+1);
    if (p == NULL) {
        free(strData);
        myAssert(0, "error: realloc can't allocate (1)");
    }
    /* you even can do strData = p; then
       but it is not necessary because
       if p != NULL, then strData is already increased */



Thanks again 'c.user' ... and for your patient perseverance with all these necessary details to get the validation tests here with 'realloc' ... and thus the program to function as desired ... just right.

So here is a further revision, that attempts to use this validation property of 'realloc', that I had missed above ...

Quote

realloc will return a value, but if it will return NULL, strData will not be changed
it will not write NULL to strData



/* readWord.c // test program needs test file in same folder as .exe file // */

/* readWord.h */

#ifndef _READ_WORD_
#define _READ_WORD_

/*  http://developers-heaven.net/forum/index.php/topic,46.0.html  */

#include <stdio.h>
#include <stdlib.h>

#include <string.h> /* re. strchr */
/*
    Safe string data entry from file ... BUT free new memory when done with it!
    Don't forget that C strings are pointers to a block of char, with a '\0'
    char at the terminal end ... Call like this:

    char* word = readWord(stdin, 31, "\n\t ,.;:", &lastChr);//note delimiter str
    
    or ...
    
    while((word = readWord(FILEp, startChunkSize, delimiterStr, &lastCharRead)))
    {
        // do stuff ...
    }

    Note 1: select your initial word chunk size to minimize calls to realloc
    Note 2: address of last char passed in/out so can flush stdin or file line
*/

void myAssert( int condition, char text[] );

/* returns a string in new memory holding each word ... or NULL if EOF */
char* readWord( FILE* fp, int chunk_len, char delimits[], char* c)
{
    char* strData;
    int i = 0; /* ... *c to hold each char, i for index in string ... */
    if( chunk_len < 1 ) chunk_len = 3; /* set to min. starting chunk size */
    
    strData = (char*) calloc( chunk_len+1, 1 ); /* cast added for C++ compilers */
    myAssert( (strData != NULL), "Error: calloc can't allocate (1)" );

    while( (*c = fgetc( fp )) != EOF && strchr(delimits, *c) ) ; /* advance */
    
    if( *c != EOF ) strData[i++] = *c; /* ok ... get this first char in the str */
    
    while( (*c = fgetc( fp )) != EOF && !strchr(delimits, *c) )
    {
        if( i == chunk_len-1 ) /* get more memory now ... (for word or line) */
        {
            chunk_len += chunk_len; /* double memory ...*/
            if( !realloc( strData, chunk_len+1 ) ) /* call/test returned value */
            {
                /* Note: strData was NOT changed above if null pointer returned */
                free( strData ); 
                myAssert( 0, "Error: realloc can't allocate (1)" );
            }
            /* if reach here, realloc above was a success & strData updated */
        }
        /* now can ... */
        strData[i] = *c;
        ++i;
    }
    strData[i] = 0; /* confirm termination */

    /* if EOF and empty line, quit reading file, BUT FIRST, free this strData */
    if( *c == EOF && strData[0] == 0 ) { free( strData); return NULL; }
    
    /* else ... */
    if( !realloc( strData, i+1 ) ) /* since i is index of '\0' we need size i+1 */
    {
        free( strData ); /* strData NOT changed above, if null pointer returned */
        myAssert( 0, "Error: realloc can't allocate (2)" );
    }

    /* if reach here, realloc above was a success ... and program NOT aborted */
    /* So ... */
    return strData;
}

void myAssert( int condition, char text[] )
{
    if( !condition )
    {
        fprintf(stderr, "%s\n", text );
        fputs( "Press 'Enter' to exit program ... ", stderr );
        getchar();
        exit(1);
    }
}

#endif


/* readWord.c // test program // */

/* #include "readWord.h" */

#define TEST_FILE "readWord.txt"
#define FILE_ERROR "ERROR opening File "
#define MAX_SIZE 10

int main()
{
    int i, j;
    char last;
    char* word;
    char* raggedAry[MAX_SIZE];
    char delimits[] = "\n\t ,.;:";
    FILE* fp = fopen( TEST_FILE, "r" );
    myAssert( (fp != NULL), FILE_ERROR TEST_FILE " at '4' in main function" );

    puts( " === FROM FILE '" TEST_FILE "' ===" );
    while( (word = readWord(fp, 31, delimits, &last)) )
    {
        printf( "%s\n", word );
        free( word );
    }
    puts( "===" );
    
    fclose( fp );

    i = 0;
    printf( "\n === VIA KEY BOARD enter up to %d words ===", MAX_SIZE );
    printf( "\nEnter words (Enter q to quit)  : " );
    while
    (
        i < MAX_SIZE &&
        (word = readWord(stdin, 31, delimits, &last))
    )
    {
        if( ((word[0] == 'q' || word[0] == 'Q') && word[1] == 0) )
        {
            free( word );
            break;
        }
        raggedAry[i++] = word;
    }

    puts( "\nYou entered ..." );
    for( j = 0; j < i; ++j )
    {
        printf( "%2d: %s\n", j+1, raggedAry[j] );
        free( raggedAry[j] );
    }

    fputs( " ===> Press 'Enter' to exit ===> ", stdout );
    /* flush stdin buffer ... */
    while( last != '\n' && last != EOF ) last = getchar();
    getchar();
    return 0;
}

/*  file name: "readWord.txt" */

/*
abd def
ghi,jkl

mn,    opqrst     uv;wxyz,
mn,    opqrst    ;   ;    uv,

wxyz
,


,
*/

/* output ... */

/*
 === readWord.txt ===
abd
def
ghi
jkl
mn
opqrst
uv
wxyz
mn
opqrst
uv
wxyz
===
*/


Was This Post Helpful? 0
  • +
  • -

#14 Guest_c.user*


Reputation:

Re: How to read specific characters with fscanf

Posted 15 February 2010 - 06:26 PM

yeah, the words are under control now :)
Was This Post Helpful? 0

#15 David W  Icon User is offline

  • DIC supporter
  • member icon

Reputation: 281
  • View blog
  • Posts: 1,788
  • Joined: 20-September 08

Re: How to read specific characters with fscanf

Posted 15 February 2010 - 07:17 PM

View Postc.user, on 15 February 2010 - 07:26 PM, said:

yeah, the words are under control now :)


Thank you for your help here, c.user ... Such a wonderful thing it is to have my words under control. If only that could be the case in all parts of my life.

Oh Lord, please hasten that day.

Quote

... be not many masters, knowing that we shall receive the greater condemnation. For in many things we offend all. If any man offend not in word, the same is a perfect man, and able also to bridle the whole body.

Behold, we put bits in the horses’ mouths, that they may obey us; and we turn about their whole body.

Behold also the ships, which though they be so great, and are driven of fierce winds, yet are they turned about with a very small helm, whithersoever the governor listeth.

Even so the tongue is a little member, and boasteth great things. Behold, how great a matter a little fire kindleth! And the tongue is a fire, a world of iniquity: so is the tongue among our members, that it defileth the whole body, and setteth on fire the course of nature; and it is set on fire of hell.

For every kind of beasts, and of birds, and of serpents, and of things in the sea, is tamed, and hath been tamed of mankind:

But the tongue can no man tame; it is an unruly evil, full of deadly poison.

Therewith bless we God, even the Father; and therewith curse we men, which are made after the similitude of God. Out of the same mouth proceedeth blessing and cursing.

My brethren, these things ought not so to be. Doth a fountain send forth at the same place sweet water and bitter? Can the fig tree, my brethren, bear olive berries? either a vine, figs? so can no fountain both yield salt water and fresh.

Who is a wise man and endued with knowledge among you? let him shew out of a good conversation his works with meekness of wisdom.

But if ye have bitter envying and strife in your hearts, glory not, and lie not against the truth. This wisdom descendeth not from above, but is earthly, sensual, devilish. For where envying and strife is, there is confusion and every evil work.

But the wisdom that is from above is first pure, then peaceable, gentle, and easy to be intreated, full of mercy and good fruits, without partiality, and without hypocrisy.

And the fruit of righteousness is sown in peace of them that make peace.

(James chapter 3)


Shalom,
David

This post has been edited by David W: 16 February 2010 - 12:08 AM

Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2