Happy christmas

Discussion in 'C Programming' started by jacob navia, Dec 24, 2007.

  1. jacob navia

    jacob navia Guest

    Why are C interfaces so low level?

    We discussed a bit about this in the thread about getting an URL from
    the internet.

    Take, for instance, we all some day needed to read an entire
    file into RAM to process it. Why there isn't

    char *strfromfile(const char *file_name,const char *mode);

    As a holidays present, here it is.

    #include <string.h>
    #include >errno.h>
    #include <stdio.h>
    #include <stdlib.h>
    char *strfromfile(const char *fname,const char *mode)
    {
    if (fname == NULL || mode == NULL) {
    errno = EINVAL;
    return NULL;
    }
    FILE *f = fopen(fname,"rb");
    if (f == NULL) {
    errno = ENOENT;
    return NULL;
    }
    if (fseek(f,0,SEEK_END) != 0) {
    ioerror:
    errno = EIO; // IO error
    fclose(f);
    return NULL;
    }
    long l = ftell(f);
    if (l < 0) goto ioerror;
    if (fseek(f,0,SEEK_SET) != 0)
    goto ioerror;
    char *result = malloc(l+1);
    if (result == NULL) {
    errno = ENOMEM;
    fclose(f);
    return NULL;
    }
    if (fread(result,1,l,f) <= 0)
    goto ioerror;
    result[l] = 0;
    fclose(f);
    if (strchr(mode,'b') == NULL) {
    char *src = result,*dst = result;
    while ((src - result) < l) {
    if (*src != '\r')
    *dst++ = *src;
    src++;
    }
    *dst = 0;
    }
    return result;
    }

    Argument "mode" should be either "r" or "rb" for binary or text mode.
    This can be omitted in Unix systems, where this stupid distinction
    doesn't exist.

    If I do not find a "b" in the "mode" string I eliminate CRs from the
    string.

    NOTE: This function will not run in the DS9000
    --
    jacob navia
    jacob at jacob point remcomp point fr
    logiciels/informatique
    http://www.cs.virginia.edu/~lcc-win32
     
    jacob navia, Dec 24, 2007
    #1
    1. Advertising

  2. jacob navia

    jacob navia Guest

    jacob navia wrote:
    > #include >errno.h>


    That should have been
    #include <errno.h>

    obviously.

    --
    jacob navia
    jacob at jacob point remcomp point fr
    logiciels/informatique
    http://www.cs.virginia.edu/~lcc-win32
     
    jacob navia, Dec 24, 2007
    #2
    1. Advertising

  3. jacob navia

    Joe Wright Guest

    jacob navia wrote:
    > Why are C interfaces so low level?
    >
    > We discussed a bit about this in the thread about getting an URL from
    > the internet.
    >
    > Take, for instance, we all some day needed to read an entire
    > file into RAM to process it. Why there isn't
    >
    > char *strfromfile(const char *file_name,const char *mode);
    >
    > As a holidays present, here it is.
    >
    > #include <string.h>
    > #include >errno.h>
    > #include <stdio.h>
    > #include <stdlib.h>
    > char *strfromfile(const char *fname,const char *mode)
    > {
    > if (fname == NULL || mode == NULL) {
    > errno = EINVAL;
    > return NULL;
    > }
    > FILE *f = fopen(fname,"rb");
    > if (f == NULL) {
    > errno = ENOENT;
    > return NULL;
    > }
    > if (fseek(f,0,SEEK_END) != 0) {
    > ioerror:
    > errno = EIO; // IO error
    > fclose(f);
    > return NULL;
    > }
    > long l = ftell(f);
    > if (l < 0) goto ioerror;
    > if (fseek(f,0,SEEK_SET) != 0)
    > goto ioerror;
    > char *result = malloc(l+1);
    > if (result == NULL) {
    > errno = ENOMEM;
    > fclose(f);
    > return NULL;
    > }
    > if (fread(result,1,l,f) <= 0)
    > goto ioerror;
    > result[l] = 0;
    > fclose(f);
    > if (strchr(mode,'b') == NULL) {
    > char *src = result,*dst = result;
    > while ((src - result) < l) {
    > if (*src != '\r')
    > *dst++ = *src;
    > src++;
    > }
    > *dst = 0;
    > }
    > return result;
    > }
    >
    > Argument "mode" should be either "r" or "rb" for binary or text mode.
    > This can be omitted in Unix systems, where this stupid distinction
    > doesn't exist.
    >
    > If I do not find a "b" in the "mode" string I eliminate CRs from the
    > string.
    >

    What string? Files don't (usually) have strings. They have lines.

    What do you do about the SUB character (if you find one) ?

    Merry Christmas.

    --
    Joe Wright
    "Everything should be made as simple as possible, but not simpler."
    --- Albert Einstein ---
     
    Joe Wright, Dec 25, 2007
    #3
  4. jacob navia

    Flash Gordon Guest

    jacob navia wrote, On 24/12/07 23:37:
    > Why are C interfaces so low level?
    >
    > We discussed a bit about this in the thread about getting an URL from
    > the internet.


    In general the more flexible the library the more complex the interface.

    > Take, for instance, we all some day needed to read an entire
    > file into RAM to process it.


    I haven't so far. At least, not in to one string.

    > Why there isn't
    >
    > char *strfromfile(const char *file_name,const char *mode);
    >
    > As a holidays present, here it is.
    >
    > #include <string.h>
    > #include >errno.h>


    You corrected this mistake in a follow up.

    > #include <stdio.h>
    > #include <stdlib.h>
    > char *strfromfile(const char *fname,const char *mode)
    > {
    > if (fname == NULL || mode == NULL) {
    > errno = EINVAL;
    > return NULL;
    > }
    > FILE *f = fopen(fname,"rb");


    Wouldn't it be more sensible to use the mode the user passes in?

    > if (f == NULL) {
    > errno = ENOENT;
    > return NULL;
    > }
    > if (fseek(f,0,SEEK_END) != 0) {
    > ioerror:
    > errno = EIO; // IO error
    > fclose(f);
    > return NULL;
    > }
    > long l = ftell(f);
    > if (l < 0) goto ioerror;
    > if (fseek(f,0,SEEK_SET) != 0)


    This is not a portable method of determining file size. Mainly because
    there is o portable method. You should at least comment the
    non-portabilities.

    > goto ioerror;
    > char *result = malloc(l+1);
    > if (result == NULL) {
    > errno = ENOMEM;
    > fclose(f);
    > return NULL;
    > }
    > if (fread(result,1,l,f) <= 0)


    Using l as a variable name was a bad idea because it makes it harder to
    read the above line, or easier to miss-read it.

    Also you fail to allow for it reading fewer then the number of 1 byte
    members you specify. This can happen for a number of reasons.

    > goto ioerror;
    > result[l] = 0;
    > fclose(f);
    > if (strchr(mode,'b') == NULL) {
    > char *src = result,*dst = result;
    > while ((src - result) < l) {


    Hmm. You have an initialisation, a test, and an increment, wouldn't a
    for loop have been more natural?

    > if (*src != '\r')
    > *dst++ = *src;
    > src++;


    Since you have opened the file in binary mode and MacOS 9.x and earlier
    use '\r' as the line terminator you have just converted the file to one
    long line on some systems.

    > }
    > *dst = 0;
    > }
    > return result;
    > }
    >
    > Argument "mode" should be either "r" or "rb" for binary or text mode.
    > This can be omitted in Unix systems, where this stupid distinction
    > doesn't exist.
    >
    > If I do not find a "b" in the "mode" string I eliminate CRs from the
    > string.
    >
    > NOTE: This function will not run in the DS9000


    You don't need a system that exotic for it to fail.
    --
    Flash Gordon
     
    Flash Gordon, Dec 25, 2007
    #4
  5. jacob navia

    Guest

    On Dec 25, 1:37 am, jacob navia <> wrote:
    > Why are C interfaces so low level?
    >
    > We discussed a bit about this in the thread about getting an URL from
    > the internet.
    >
    > Take, for instance, we all some day needed to read an entire
    > file into RAM to process it. Why there isn't
    >
    > char *strfromfile(const char *file_name,const char *mode);
    >
    > As a holidays present, here it is.
    >
    > [ snip ]
    > Argument "mode" should be either "r" or "rb" for binary or text mode.
    > This can be omitted in Unix systems, where this stupid distinction
    > doesn't exist.
    >
    > If I do not find a "b" in the "mode" string I eliminate CRs from the
    > string.
    >
    > NOTE: This function will not run in the DS9000


    Why you never free() what you allocate?
    I am talking about this

    > ioerror:
    > errno = EIO; // IO error
    > fclose(f);
    > return NULL;
    > /* other stuff */
    > char *result = malloc(l+1);
    > if (result == NULL) {
    > errno = ENOMEM;
    > fclose(f);
    > return NULL;
    > }
    > if (fread(result,1,l,f) <= 0)
    > goto ioerror;

    ^^^^^^^^^^^^^ At this point memory is allocated and
    not freed.

    Merry Christmas to the collective of c.l.c!
     
    , Dec 25, 2007
    #5
  6. jacob navia

    santosh Guest

    wrote:

    > On Dec 25, 1:37 am, jacob navia <> wrote:
    >> Why are C interfaces so low level?
    >>
    >> We discussed a bit about this in the thread about getting an URL from
    >> the internet.
    >>
    >> Take, for instance, we all some day needed to read an entire
    >> file into RAM to process it. Why there isn't
    >>
    >> char *strfromfile(const char *file_name,const char *mode);
    >>
    >> As a holidays present, here it is.
    >>
    >> [ snip ]
    >> Argument "mode" should be either "r" or "rb" for binary or text mode.
    >> This can be omitted in Unix systems, where this stupid distinction
    >> doesn't exist.
    >>
    >> If I do not find a "b" in the "mode" string I eliminate CRs from the
    >> string.
    >>
    >> NOTE: This function will not run in the DS9000

    >
    > Why you never free() what you allocate?


    <snip>

    Because jacob almost always assumes a modern OS like Windows or a UNIX
    variant will clean up after the program.

    In general, even if the OS may recover the memory, I still prefer
    explicitly deallocating them. It better practise and stands up well to
    porting to other systems.
     
    santosh, Dec 25, 2007
    #6
  7. jacob navia

    Guest

    On Dec 25, 5:35 am, santosh <> wrote:
    > wrote:
    > > On Dec 25, 1:37 am, jacob navia <> wrote:
    > >> Why are C interfaces so low level?

    >
    > >> We discussed a bit about this in the thread about getting an URL from
    > >> the internet.

    >
    > >> Take, for instance, we all some day needed to read an entire
    > >> file into RAM to process it. Why there isn't

    >
    > >> char *strfromfile(const char *file_name,const char *mode);

    >
    > >> As a holidays present, here it is.

    >
    > >> [ snip ]
    > >> Argument "mode" should be either "r" or "rb" for binary or text mode.
    > >> This can be omitted in Unix systems, where this stupid distinction
    > >> doesn't exist.

    >
    > >> If I do not find a "b" in the "mode" string I eliminate CRs from the
    > >> string.

    >
    > >> NOTE: This function will not run in the DS9000

    >
    > > Why you never free() what you allocate?

    >
    > <snip>
    >
    > Because jacob almost always assumes a modern OS like Windows or a UNIX
    > variant will clean up after the program.
    >
    > In general, even if the OS may recover the memory, I still prefer
    > explicitly deallocating them. It better practise and stands up well to
    > porting to other systems.



    That is silly, Jacob does not care to free his memory but he cares to
    close his file streams?
     
    , Dec 25, 2007
    #7
  8. jacob navia

    santosh Guest

    wrote:

    > On Dec 25, 5:35 am, santosh <> wrote:
    >> wrote:
    >> > On Dec 25, 1:37 am, jacob navia <> wrote:
    >> >> Why are C interfaces so low level?

    >>
    >> >> We discussed a bit about this in the thread about getting an URL
    >> >> from the internet.

    >>
    >> >> Take, for instance, we all some day needed to read an entire
    >> >> file into RAM to process it. Why there isn't

    >>
    >> >> char *strfromfile(const char *file_name,const char *mode);

    >>
    >> >> As a holidays present, here it is.

    >>
    >> >> [ snip ]
    >> >> Argument "mode" should be either "r" or "rb" for binary or text
    >> >> mode. This can be omitted in Unix systems, where this stupid
    >> >> distinction doesn't exist.

    >>
    >> >> If I do not find a "b" in the "mode" string I eliminate CRs from
    >> >> the string.

    >>
    >> >> NOTE: This function will not run in the DS9000

    >>
    >> > Why you never free() what you allocate?

    >>
    >> <snip>
    >>
    >> Because jacob almost always assumes a modern OS like Windows or a
    >> UNIX variant will clean up after the program.
    >>
    >> In general, even if the OS may recover the memory, I still prefer
    >> explicitly deallocating them. It better practise and stands up well
    >> to porting to other systems.

    >
    >
    > That is silly, Jacob does not care to free his memory but he cares to
    > close his file streams?


    I agree. He should treat memory with the same care given to other
    resources. Presumably, he feels that data corruption may occur if he
    did not explicitly close the streams. That may or may not be true.
     
    santosh, Dec 25, 2007
    #8
  9. jacob navia

    Ian Collins Guest

    jacob navia wrote:
    > Why are C interfaces so low level?
    >
    > We discussed a bit about this in the thread about getting an URL from
    > the internet.
    >
    > Take, for instance, we all some day needed to read an entire
    > file into RAM to process it. Why there isn't
    >

    Because any half decent OS provides a simple means of doing it. C also
    runs on plenty of platforms that done have files.

    > char *strfromfile(const char *file_name,const char *mode);
    >
    > As a holidays present, here it is.
    >

    Been and gone here...

    --
    Ian Collins.
     
    Ian Collins, Dec 25, 2007
    #9
  10. jacob navia

    santosh Guest

    Ian Collins wrote:

    > jacob navia wrote:
    >> Why are C interfaces so low level?
    >>
    >> We discussed a bit about this in the thread about getting an URL from
    >> the internet.
    >>
    >> Take, for instance, we all some day needed to read an entire
    >> file into RAM to process it. Why there isn't
    >>

    > Because any half decent OS provides a simple means of doing it. C
    > also runs on plenty of platforms that done have files.


    And this particular task is also doable in standard C with no loss in
    functionality or efficiency. I understand that the Committee had an
    overall policy to include only those new functions in the Standard
    library that would be impossible or difficult to replicate in user
    code. This is opposite to the philosophy of the C++ Committee.
     
    santosh, Dec 25, 2007
    #10
  11. jacob navia

    Old Wolf Guest

    On Dec 25, 12:37 pm, jacob navia <> wrote:
    >
    > Take, for instance, we all some day needed to read an entire
    > file into RAM to process it. Why there isn't
    >
    > char *strfromfile(const char *file_name,const char *mode);
    >
    > As a holidays present, here it is.


    Your code doesn't even work properly in anything except Windows

    Great present!

    > errno = ENOENT;
    > errno = ENOMEM;


    ENOENT and ENOMEM are not defined (it is implementation-specific
    whether such things exist)

    > if (strchr(mode,'b') == NULL) {
    > char *src = result,*dst = result;
    > while ((src - result) < l) {
    > if (*src != '\r')
    > *dst++ = *src;
    > src++;
    > }
    > *dst = 0;


    This code is Windows-specific.

    This has got to be the dumbest snippet I've seen in a
    while. If you open the file in text mode then the
    implementation performs this newline conversion and
    any other such conversions for you. Why reinvent
    the wheel?
     
    Old Wolf, Dec 25, 2007
    #11
  12. "santosh" <> wrote in message
    >
    > And this particular task is also doable in standard C with no loss in
    > functionality or efficiency. I understand that the Committee had an
    > overall policy to include only those new functions in the Standard
    > library that would be impossible or difficult to replicate in user
    > code. This is opposite to the philosophy of the C++ Committee.
    >

    It's not a good policy.
    For instance everyone can knock up a strcpy() in a matter of minutes. You
    can even improve the ANSI version somewhat.
    But if you are reading standard, workaday code, that is maybe manipulating a
    user report in a protein program, its a big help if the calls are familiar
    with you. You don't want to be distracted by

    if( str_lsetsafe(fred, FREDLEN, jim, 0, -1) == ERRVAL)
    goto genbufferror;

    when all we're doing is setting fred equal to jim.


    --
    Free games and programming goodies.
    http://www.personal.leeds.ac.uk/~bgy1mm
     
    Malcolm McLean, Dec 25, 2007
    #12
  13. jacob navia

    jacob navia Guest

    Flash Gordon wrote:
    > Wouldn't it be more sensible to use the mode the user passes in?
    >


    No, because in text mode the standard doesn't guarantee that ftell and
    fseek will work correctly!

    >
    > Using l as a variable name was a bad idea because it makes it harder to
    > read the above line, or easier to miss-read it.
    >


    Yes, will change that to len

    > Also you fail to allow for it reading fewer then the number of 1 byte
    > members you specify. This can happen for a number of reasons.
    >
    >> goto ioerror;
    >> result[l] = 0;
    >> fclose(f);
    >> if (strchr(mode,'b') == NULL) {
    >> char *src = result,*dst = result;
    >> while ((src - result) < l) {

    >
    > Hmm. You have an initialisation, a test, and an increment, wouldn't a
    > for loop have been more natural?
    >
    >> if (*src != '\r')
    >> *dst++ = *src;
    >> src++;

    >
    > Since you have opened the file in binary mode and MacOS 9.x and earlier
    > use '\r' as the line terminator you have just converted the file to one
    > long line on some systems.
    >


    Yes, will not work in DS9000 and MAC os9.x Easy to change though.
    There is no portable way to know what line separator the system uses.


    --
    jacob navia
    jacob at jacob point remcomp point fr
    logiciels/informatique
    http://www.cs.virginia.edu/~lcc-win32
     
    jacob navia, Dec 25, 2007
    #13
  14. jacob navia

    jacob navia Guest

    jacob navia, Dec 25, 2007
    #14
  15. jacob navia

    jacob navia Guest

    santosh wrote:
    > wrote:
    >
    >> On Dec 25, 1:37 am, jacob navia <> wrote:
    >>> Why are C interfaces so low level?
    >>>
    >>> We discussed a bit about this in the thread about getting an URL from
    >>> the internet.
    >>>
    >>> Take, for instance, we all some day needed to read an entire
    >>> file into RAM to process it. Why there isn't
    >>>
    >>> char *strfromfile(const char *file_name,const char *mode);
    >>>
    >>> As a holidays present, here it is.
    >>>
    >>> [ snip ]
    >>> Argument "mode" should be either "r" or "rb" for binary or text mode.
    >>> This can be omitted in Unix systems, where this stupid distinction
    >>> doesn't exist.
    >>>
    >>> If I do not find a "b" in the "mode" string I eliminate CRs from the
    >>> string.
    >>>
    >>> NOTE: This function will not run in the DS9000

    >> Why you never free() what you allocate?

    >
    > <snip>
    >
    > Because jacob almost always assumes a modern OS like Windows or a UNIX
    > variant will clean up after the program.
    >
    > In general, even if the OS may recover the memory, I still prefer
    > explicitly deallocating them. It better practise and stands up well to
    > porting to other systems.
    >


    It was just a memory leak santosh...


    --
    jacob navia
    jacob at jacob point remcomp point fr
    logiciels/informatique
    http://www.cs.virginia.edu/~lcc-win32
     
    jacob navia, Dec 25, 2007
    #15
  16. jacob navia

    santosh Guest

    Malcolm McLean wrote:

    > "santosh" <> wrote in message
    >>
    >> And this particular task is also doable in standard C with no loss in
    >> functionality or efficiency. I understand that the Committee had an
    >> overall policy to include only those new functions in the Standard
    >> library that would be impossible or difficult to replicate in user
    >> code. This is opposite to the philosophy of the C++ Committee.
    >>

    > It's not a good policy.


    It depends. Going the other way and including everything except the
    Kitchen sink, as the C++ people have done might also be criticised by
    some.

    > For instance everyone can knock up a strcpy() in a matter of minutes.
    > You can even improve the ANSI version somewhat.


    If my program would significantly benefit from the improvement in
    functionality or speed, then I'd use the platform specific version,
    over the stock one supplied with the library.

    But this is somewhat rare. Usually if a function is available as a part
    of a Standard library, you'd do well to use it.

    > But if you are reading standard, workaday code, that is maybe
    > manipulating a user report in a protein program, its a big help if the
    > calls are familiar with you. You don't want to be distracted by
    >
    > if( str_lsetsafe(fred, FREDLEN, jim, 0, -1) == ERRVAL)
    > goto genbufferror;
    >
    > when all we're doing is setting fred equal to jim.


    True. Nevertheless the overall philosophy of C is for it to supply
    minimal functionality and thereby preserve ease of portability and
    efficiency. If you want an extensive Standard library, try C++, Java,
    Perl, Python, Tcl and others.
     
    santosh, Dec 25, 2007
    #16
  17. jacob navia

    Guest

    merry Christmas too.
     
    , Dec 25, 2007
    #17
  18. jacob navia

    Ian Collins Guest

    santosh wrote:
    > Malcolm McLean wrote:
    >
    >> "santosh" <> wrote in message
    >>> And this particular task is also doable in standard C with no loss in
    >>> functionality or efficiency. I understand that the Committee had an
    >>> overall policy to include only those new functions in the Standard
    >>> library that would be impossible or difficult to replicate in user
    >>> code. This is opposite to the philosophy of the C++ Committee.
    >>>

    >> It's not a good policy.

    >
    > It depends. Going the other way and including everything except the
    > Kitchen sink, as the C++ people have done might also be criticised by
    > some.
    >

    They didn't, they took the sensible path of standardising a container
    and algorithms library that was in widespread use.

    The next version will do much the same with the most widely used parts
    of boot. It's a natural process of library evolution that the C
    standard appears to have lost sight of.

    If you want a true kitchen sink approach, try Java...

    --
    Ian Collins.
     
    Ian Collins, Dec 25, 2007
    #18
  19. jacob navia

    CBFalconer Guest

    jacob navia wrote:
    > Flash Gordon wrote:
    >

    .... snip ...
    >
    >> Since you have opened the file in binary mode and MacOS 9.x and
    >> earlier use '\r' as the line terminator you have just converted
    >> the file to one long line on some systems.> >

    >
    > Yes, will not work in DS9000 and MAC os9.x Easy to change though.
    > There is no portable way to know what line separator the system
    > uses.


    Yes there is. Just open the file in text mode (i.e. without the
    "rb") and wait until you detect a '\n' in the stream. That is
    exactly where a line separator occured.

    --
    Merry Christmas, Happy Hanukah, Happy New Year
    Joyeux Noel, Bonne Annee, Frohe Weihnachten
    Chuck F (cbfalconer at maineline dot net)
    <http://cbfalconer.home.att.net>



    --
    Posted via a free Usenet account from http://www.teranews.com
     
    CBFalconer, Dec 25, 2007
    #19
  20. jacob navia

    jacob navia Guest

    CBFalconer wrote:
    > jacob navia wrote:
    >> Flash Gordon wrote:
    >>

    > ... snip ...
    >>> Since you have opened the file in binary mode and MacOS 9.x and
    >>> earlier use '\r' as the line terminator you have just converted
    >>> the file to one long line on some systems.> >

    >> Yes, will not work in DS9000 and MAC os9.x Easy to change though.
    >> There is no portable way to know what line separator the system
    >> uses.

    >
    > Yes there is. Just open the file in text mode (i.e. without the
    > "rb") and wait until you detect a '\n' in the stream. That is
    > exactly where a line separator occured.
    >

    So What?

    You think the function should discover each time
    it is called the line separator?


    --
    jacob navia
    jacob at jacob point remcomp point fr
    logiciels/informatique
    http://www.cs.virginia.edu/~lcc-win32
     
    jacob navia, Dec 25, 2007
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Thomas Ploch

    Merry Christmas and a happy new year!

    Thomas Ploch, Dec 24, 2006, in forum: Python
    Replies:
    0
    Views:
    330
    Thomas Ploch
    Dec 24, 2006
  2. _cin_

    Happy New Year and Merry Christmas!

    _cin_, Dec 31, 2005, in forum: C Programming
    Replies:
    0
    Views:
    360
    _cin_
    Dec 31, 2005
  3. _cin_
    Replies:
    5
    Views:
    993
  4. Paddy

    Happy Christmas Pythoneers

    Paddy, Dec 24, 2007, in forum: Python
    Replies:
    14
    Views:
    474
    Marc 'BlackJack' Rintsch
    Dec 28, 2007
  5. ilogic consulting
    Replies:
    0
    Views:
    422
    ilogic consulting
    Dec 25, 2008
Loading...

Share This Page