Simple example to use fscanf?

New to FreeBASIC? Post your questions here.
Post Reply
dkr
Posts: 40
Joined: Nov 20, 2015 15:17
Location: Alabama, USA

Simple example to use fscanf?

Post by dkr »

Hello,
Is there an existing simple example of how to use fscanf from the standard C library. Is the library part of the standard stuff included with FreeBASIC for Windows? Do I need to download a library? or just use an #include "******"

Thanks,
Darren
bcohio2001
Posts: 556
Joined: Mar 10, 2007 15:44
Location: Ohio, USA
Contact:

Re: Simple example to use fscanf?

Post by bcohio2001 »

fscanf is part of the C run time library, part of Freebasic.

Code: Select all

#include "crt/stdio.bi"
As for an example .... ????
dodicat
Posts: 7976
Joined: Jan 10, 2006 20:30
Location: Scotland

Re: Simple example to use fscanf?

Post by dodicat »

I have never used fscanf, but this seems to work

Code: Select all


#include "crt.bi"
#include "file.bi"

dim as string txt="abcdefghijklmnopqrstuvwxyz"
dim as file ptr fp

fp=fopen("testfile.txt","w+")              'open a new file for writing to
fputs(txt,fp)                              'write txt to the new file
fclose(fp)                                  'close the file

 
 dim as long size=filelen("testfile.txt")   'get the number of characters in the file
 dim as zstring ptr  str1=allocate(size*sizeof(string))    'allocate memory of this size 
 
 fp=fopen("testfile.txt","r")                'open the file for reading          
fscanf(fp, "%s", str1)                       'read the file into the zstring ptr
fclose(fp)

puts *str1                                   'print the string 
kill "testfile.txt"                           'delete the file
sleep
 
I am sure some C experts will correct this if necessary.
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: Simple example to use fscanf?

Post by counting_pine »

Here's an example translated from https://www.tutorialspoint.com/c_standa ... fscanf.htm:

Code: Select all

#include "crt/stdio.bi"
#include "crt/stdlib.bi"

dim as string str1, str2, str3
dim year as long
dim fp as FILE ptr

str1 = space(20): str2 = str1: str3 = str1

fp = fopen ("file.txt", "w+")
fputs("We are in 2012", fp)

rewind(fp)
fscanf(fp, "%s %s %s %d", strptr(str1), strptr(str2), strptr(str3), @year)

printf(!"Read String1 |%s|\n", strptr(str1) )
printf(!"Read String2 |%s|\n", strptr(str2) )
printf(!"Read String3 |%s|\n", strptr(str3) )
printf(!"Read Integer |%d|\n", year )

fclose(fp)
Note that fscanf() is not a safe function, and will happily try to write beyond the memory allocated for the string if it's too long.
dkr
Posts: 40
Joined: Nov 20, 2015 15:17
Location: Alabama, USA

Re: Simple example to use fscanf?

Post by dkr »

Thanks Dodicat & Counting Pine,
Your help got me started, but I am stuck again. I was able to read part of the header file, but reading the bottom table is not working. fscanf seems to ignore the width of the string %ws or an integer %wd. Any suggestions??
The forum seems to delete many of the spaces in the 2.hdr file ??
Thanks Darren

Code: Select all

'test to read *.hdr file
'
#include "crt/stdio.bi"
#include "crt/stdlib.bi"
#include "file.bi"
dim fp as FILE ptr
Const nch = 16
dim as string*2 tmp2
dim as string*32 msidt
dim as string*9 unitt,tmp1
dim as string*32 rmenu
dim as string smon,sday,sdate,stim,syear
dim as string*46 dfn,owner,testid,timedate
dim as integer npts,i,cht,rchs
dim as single st,sr,tt,r1,r2,r3,r4,r5,r6,r7,r8,r9,r10
dim as single calt,gaint
dim chs(1 to nch) As integer
dim msid(1 to nch) As String
dim unit(1 to nch) As String
dim cal(1 to nch) As double
dim gain(1 to nch) As double

smon = space(4): sday = space(3): sdate = space(3): stim = space(9): syear = space(5)
rmenu = space(32): msidt = space(32): tmp1 = space(9): tmp2 = space(2)

fp = fopen ("E:\PXI_5057506_checkout\2.hdr", "r")
    'Print "Successfully opened file"
	fscanf(fp,"%s %*s %*s %*s %*s %*s",strptr(dfn)) 
    fscanf(fp,"%s %*s %*s %*s %*s",strptr(owner))
	fscanf(fp,"%s %*s %*s %*s %*s",strptr(testid))
	fscanf(fp,"%s %s %s %s %s %*s %*s %*s %*s %*s",strptr(sday),strptr(smon),strptr(sdate),strptr(stim),strptr(syear))
	fscanf(fp,"%d %*s %*s %*s %*s %*s",@npts)
	fscanf(fp,"%d %*s %*s %*s %*s %*s %*s",@rchs)
	fscanf(fp,"%f %*s %*s %*s %*s %*s %*s",@st)
	fscanf(fp,"%f %*s %*s %*s %*s %*s",@sr)
	fscanf(fp,"%f %*s %*s %*s %*s %*s",@tt)
	fscanf(fp,"%*s %*s")    'skip rmenu title line
	fscanf(fp,"%f %f %f %f %f %*s",@r1,@r2,@r3,@r4,@r5)
	fscanf(fp,"%f %f %f %f %f %*s",@r6,@r7,@r8,@r9,@r10)
	fscanf(fp,"%2s %*s %*s %*s %*s %s",strptr(tmp1),strptr(tmp2))    'skip table headers
    print "tmp1=";tmp1;"|"
    print "tmp2 =";tmp2;"|"
    For i = 1 to 16
        fscanf(fp,"%2d %32s %9s %f %f %*s",@cht,strptr(msidt),strptr(unitt),_ 'PROBLEM??
        @calt,@gaint)
        chs(i) = cht     
        msid(i) = msidt 
        unit(i) = unitt 
        cal(i) = calt   
        gain(i) = gaint 
        'printf(!"Ch# %d|\n",cht)
        Print "|";cht;"|";msidt;"|";unitt;"|";calt;"|";gaint;"|"  'just for debugging
    Next
  
	fclose(fp)

print "data file name: ";dfn
print "owner: ";owner
print "testid: ";testid
print "Day Month Date Time Year: ";sday;"|";smon;"|";sdate;"|";stim;"|";syear
print "No. of points: ";npts
print "No. of channels: ";rchs
print "Start Time: ";st
print "Sample Rate: ";sr
print "Total Time Recorded: ";tt
print "Rmenu line: "
print "Rmenu 1-5: ";r1,r2,r3,r4,r5
print "Rmenu 6-10: ";r6,r7,r8,r9,r10

for i = 1 to 16
    print chs(i),msid(i),unit(i),cal(i),gain(i)
next i
---------- 2.hdr ------------
2.dat /* data file name */
Darren /* data owner */
1 /* test identification */
Wed Oct 04 14:31:03 2017 /* date data acquired */
1638400 /* number of data points*/
16 /* number of data chans */
0.00000000 /* start time of data */
102400.0000000 /* rate in samples/sec */
5.60000000 /* seconds of data */
rmenu(1-10)(this linelength=31)
1.100000 2.200000 3.100000 4.100000 5.100000 */
1.200000 2.200000 3.200000 4.200000 5.200000 */
Ch MSID Units Cal Gain */
1 Channel 1 V 2.733556305 1 */
2 Channel 2 V 2.733556305 1 */
3 Channel 3 V 2.733556305 1 */
4 Channel 4 V 2.733556305 1 */
5 Channel 5 V 2.733556305 1 */
6 Channel 6 V 2.733556305 1 */
7 Channel 7 V 2.733556305 1 */
8 Channel 8 V 2.733556305 1 */
9 Channel 9 V 2.733556305 1 */
10 Channel 10 V 2.733556305 1 */
11 Channel 11 V 2.733556305 1 */
12 Channel 12 V 2.733556305 1 */
13 Channel 13 V 2.733556305 1 */
14 Channel 14 V 2.733556305 1 */
15 Channel 15 V 2.733556305 1 */
16 Channel 16 V 2.733556305 1 */
dkr
Posts: 40
Joined: Nov 20, 2015 15:17
Location: Alabama, USA

Re: Simple example to use fscanf?

Post by dkr »

Here is the header using the /code/ 2.hdr /code/ formatting - sorry about that

Code: Select all

2.dat                                        /* data file name       */
Darren                                       /* data owner           */
1                                            /* test identification  */
Wed Oct 04 14:31:03 2017                     /* date data acquired   */
1638400                                      /* number of data points*/
16                                           /* number of data chans */
0.00000000                                   /* start time of data   */
102400.0000000                               /* rate in samples/sec  */
5.60000000                                   /* seconds of data      */
rmenu(1-10)(this linelength=31)
1.100000      2.200000      3.100000      4.100000      5.100000     */
1.200000      2.200000      3.200000      4.200000      5.200000     */
Ch MSID                             Units    Cal         Gain        */
1  Channel 1                        V        2.733556305  1          */
2  Channel 2                        V        2.733556305  1          */
3  Channel 3                        V        2.733556305  1          */
4  Channel 4                        V        2.733556305  1          */
5  Channel 5                        V        2.733556305  1          */
6  Channel 6                        V        2.733556305  1          */
7  Channel 7                        V        2.733556305  1          */
8  Channel 8                        V        2.733556305  1          */
9  Channel 9                        V        2.733556305  1          */
10 Channel 10                       V        2.733556305  1          */
11 Channel 11                       V        2.733556305  1          */
12 Channel 12                       V        2.733556305  1          */
13 Channel 13                       V        2.733556305  1          */
14 Channel 14                       V        2.733556305  1          */
15 Channel 15                       V        2.733556305  1          */
16 Channel 16                       V        2.733556305  1          */
sancho3
Posts: 358
Joined: Sep 30, 2017 3:22

Re: Simple example to use fscanf?

Post by sancho3 »

%s is defined as

s String of characters. This will read subsequent characters until a whitespace is found (whitespace characters are considered to be blank, newline and tab).

So it stops reading at the first blank after channel.

Out of curiosity, why are you using fscanf? Are the FB file functions inadequate?
dkr
Posts: 40
Joined: Nov 20, 2015 15:17
Location: Alabama, USA

Re: Simple example to use fscanf?

Post by dkr »

Sancho
Thanks for the reply. Input # does the same thing, it stops reading with a blank space. I thought fscanf might not do that. Is there any Basic input that would input a fixed length string? or a standard C function that will input a fixed string length? I was hoping to not have to do string (mid, left, right and others) to pick out the strings and values.

Darren
sancho3
Posts: 358
Joined: Sep 30, 2017 3:22

Re: Simple example to use fscanf?

Post by sancho3 »

If the stream is from a file there are the built in file commands which should get around it.

I don't know very much about fscanf.

You are faced with a couple of other issues with fscanf.
The floating point is limited in size. 2.733556 is the most I could get out of it where the actual value was 2.733556305. I think that it reads the entire value and then rounds it.

You could roll your own function and still use fscanf. It seems that %s scans until it finds the first non-whitespace character and then reads. So the function has to do the same. I don't kow how fscanf deals with an end of stream/file so I just threw in an end if fscanf doesn't return a character:

Code: Select all

sub read_string(byval file_num as FILE ptr, byval n as integer = 0, byref s as string, byval test as integer= 0)
	dim as string * 1 c
	dim as string result
	dim as integer e, x

	if n = 0 then n = len(s)
	do
		e = fscanf(file_num, "%c", strptr(c))
	loop while c=" " and e = 1
	
	if e <>1 then
		' this is an error condition
		end
	endif
	x = 1
	do
		s[x-1] = asc(c)
		fscanf(file_num, "%c", strptr(c))
		x += 1
	loop while x < n 
end sub
You call it like this:

Code: Select all

...
    For i = 1 to 16
        fscanf(fp,"%2d",@cht)
        read_string(fp,,msidt)
        ...
Note that you have not initialized the string unitt. That has to happen before you send it to this function.

Because of the floating point problem I mention earlier, you will have to read those in as strings and then convert them to doubles.

I get the feeling there is a better way than what I am doing here.
grindstone
Posts: 862
Joined: May 05, 2015 5:35
Location: Germany

Re: Simple example to use fscanf?

Post by grindstone »

dkr wrote: Is there any Basic input that would input a fixed length string?
FBWiki : KeyPgInputnum
Post Reply