FILE ACCESS - C programming

Discussion in 'Mac Programming' started by ojb13004, Nov 26, 2013.

  1. ojb13004, Nov 26, 2013
    Last edited by a moderator: Nov 26, 2013

    ojb13004 macrumors newbie

    Joined:
    Nov 26, 2013
    #1
    Code:
    #include <stdio.h>
    int main() {
        FILE *inf;
        float myData;
        inf=fopen("Users/oliverburns/Documents/Document1.txt","r");
        fscanf(inf,"%f",&myData);
        printf("Read from file: myData=%f\n",myData);
             
               fclose(inf);
               return(0); }
    
    I'm an engineering student who needs to be able to program on my Mac. I can get the basic functions of C to work but the function 'fopen()' doesn't seem to work. File access is very fundamental to what I need to do. This is the output I get for the above code when I run it;

    (lldb)


    Can anyone tell me where I am going wrong? The file exists and there is text in it.


    Thanks in advance.

    #confused
     
  2. balamw Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #2
    Looks like you're just missing a leading slash from the file name.

    Code:
    inf=fopen("[COLOR="Red"][B]/[/B][/COLOR]Users/oliverburns/Documents/Document1.txt","r");
    Are you adapting code from Windows and removed a "C:\"

    B
     
  3. ojb13004 thread starter macrumors newbie

    Joined:
    Nov 26, 2013
    #3
    See screenshot attached, this is what I get. I haven't converted it from Windows so that shouldn't be the problem.

    Thanks.
     

    Attached Files:

  4. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #4
    You need to check whether inf == NULL. That's what's going to happen if the file couldn't be opened, and then fread will crash.

    And you just _might_ have got a warning from the compiler telling you that passing myData to fread isn't a good idea. Can you figure out yourself why that is?
     
  5. balamw Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #5
    Several things could still be wrong.

    As gnasher said, checking for success in fopen is always a good idea.

    Code:
    include <stdio.h>
    int main() {
    FILE *inf;
    float myData;
    
    inf=fopen("./Document1.txt","r");
    if (NULL != inf) {	
    	fscanf(inf,"%f",&myData);
    	printf("Read from file: myData=%f\n",myData);
    	fclose(inf);
    else
    	printf("Could not open file \n\r");
    
    return(0); }
    
    Works fine for me for most contents of ./Document1.txt (in the same folder), but if the file you are looking for does not exist or you don't have permissions to it, it will bomb.

    Please note that Unix filenames are case sensitive. document1.txt is not the same as Document1.TXT.

    B
     
  6. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #6
    The only way you are going to get that error is if 'inf' is NULL, which it will be if the file doesn't exist at the given path or failed to open for some other reason.

    You need to check if 'inf' is NULL before attempting to use it, you can use perror which will print the reason for it not opening, then abort like this for example.

    Code:
        inf = fopen(path, "r");
        if(inf == NULL) {
            perror(path);
            return 1;
        }
    
    That would depend on the file system, in case of HFS+ case insensitive should be the default.
     
  7. lloyddean macrumors 6502a

    Joined:
    May 10, 2009
    Location:
    Des Moines, WA
    #7
    Product -> Scheme -> Edit Scheme

    Left list, select "Run"

    Right list, "Working Directory" check "Using custom working directoy" and then select your working directy

    "OK"

    Run/Debug your program.
     
  8. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #8
    In addition to a check for fopen() returning NULL, you must also check that fscanf() returns 1 here.

    If a float value isn't converted by fscanf(), then the myData variable is uninitialized, and attempts to print it can fail. The returned value from fscanf() tells you how many items were actually converted, or EOF if the input has been exhausted.

    https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/fscanf.3.html

    RETURN VALUES
    These functions return the number of input items assigned. This can be fewer than provided for, or
    even zero, in the event of a matching failure. Zero indicates that, although there was input available,
    no conversions were assigned; typically this is due to an invalid input character, such as an
    alphabetic character for a `%d' conversion. The value EOF is returned if an input failure occurs
    before any conversion such as an end-of-file occurs. If an error or end-of-file occurs after conversion
    has begun, the number of conversions which were successfully completed is returned.


    To find out what's actually in your input file, open a Terminal window, then copy and paste this line into it:
    Code:
    hexdump -C /Users/oliverburns/Documents/Document1.txt | head -n 5
    
    Then copy and paste the complete output and post it here.
    If an error message is produced, copy and paste that in its entirety.

    It's possible that the file exists and is named "Document1.txt", but it's not actually a plain text file. This would almost certainly cause fscanf() to fail its conversion.


    Finally, if you're following a tutorial or book, please tell us exactly which one. That is, the URL of an online tutorial, or the title, author and edition of a book.

    If you're not following a tutorial, you probably should be, because the posted code shows a lot of mistakes that a decent step-by-step tutorial will cover.

    If might also help to tell us exactly which engineering field you're a student in.
     
  9. balamw, Nov 26, 2013
    Last edited: Nov 26, 2013

    balamw Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #9
    Interesting. I took the code I posted earlier and tried to reproduce the failure you expected here and didn't see it.

    I got:

    Code:
    $ rm Document1.txt 
    [B]$ ./test [/B]
    Could not open file 
    [B]$ dd if=/dev/random of=./Document1.txt bs=1024b count=1
    [/B]1+0 records in
    1+0 records out
    524288 bytes transferred in 0.051044 secs (10271298 bytes/sec)
    [B]$ hexdump -C ./Document1.txt | head -n 5 [/B]
    00000000  4e 15 97 fc d0 de ba dc  db 12 a8 1e 29 33 5d b8  |N...........)3].|
    00000010  8b 89 6c 41 9c 21 d6 ee  2b b4 aa 2f b1 ff 8e 55  |..lA.!..+../...U|
    00000020  3f 70 a8 d9 4c 77 27 45  1a 5b 5f ce 22 22 b0 bb  |?p..Lw'E.[_.""..|
    00000030  99 2a 39 a6 13 d0 c0 93  4b 3c 74 41 9a 30 ec a4  |.*9.....K<tA.0..|
    00000040  24 ef 68 0e eb b9 3c e4  df ea df f3 48 1e 09 d5  |$.h...<.....H...|
    [B]$ ./test [/B]
    Read from file: myData=0.000000
    [B]$ mv Document1.txt document1.TxT
    $ ./test 
    [/B]Read from file: myData=0.000000 
    
    Of course, if I modify the code to check the return from fscanf, it tells me it could not read a float from the file.

    EDIT: Oh, and I confirmed that by default it's case insensitive. Old habits die hard.

    B
     
  10. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #10
    If I recall correctly, when fscanf() fails a conversion, the referenced storage area (&myData) is not written to at all. Since the float in question (myData) is uninitialized, then its value after fscanf() doesn't convert is undetermined. It's possible that the undetermined bit-pattern is a valid float representation. It's also possible the value is an invalid float representation. There's really no way to predict what the value will be, nor how printf will handle it.

    So it's not that I expected a failure, it's that the potentially undetermined value of myData may or may not cause a failure. There's no way to predict what will happen.
     
  11. robvas macrumors 68020

    Joined:
    Mar 29, 2009
    Location:
    USA
    #11
    Why aren't you using something like Python? Much easier than C....
     
  12. subsonix macrumors 68040

    Joined:
    Feb 2, 2008
    #12
    Pretty sure printf will print all of them but for reserved float values produces 'nan' or 'inf'.

    ----------

    It may be a good advice to follow anyway, that way it should work on case sensitive filesystems as well. Probably nothing to worry about here though.
     
  13. balamw Moderator

    balamw

    Staff Member

    Joined:
    Aug 16, 2005
    Location:
    New England
    #13
    Yeah, I think there must be an implicit
    Code:
    float myData=0;
    in there somehow. I put that in explicitly in the version I did with checking scanf's output.

    Note that I'm using the command line tools and not Xcode.

    Yeah, I only brought it up as I didn't know where the OP was going with this.

    I ran into this on an embedded Linux project I was working on last year where some Windows code we were porting was using two distinct case sensitive files because the person we inherited the code from assumed case insensitivity.

    B
     

Share This Page