Thread: What is the best example of obtaining a string from a user/filestream?

  1. #16
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Ah, that's because you "wait for user input" using getchar() at the end of the program, but if have entered 8000 characters, and fgets() accepted 149 of them, the first of the 7851 left overof will happily be received by getchar(), and your program finishes. So it's doing exactly what you expect.

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

  2. #17
    Registered User
    Join Date
    Sep 2008
    Location
    Nort East of Great Britain!
    Posts
    8
    Blimey! I never thought of that.

    Stdin is a strange creature, isn't it?

    Thanks for clearing that up.

  3. #18
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    If your problem here is all about buffer length, I think you should stop trying to solve a problem that may not exist in practice.

    Do correct me if I'm wrong but there are three possibilities: 1) the input already exists in a file, so you can get the size that way.
    3) the input is coming thru a pipe, etc., in which case it will/can be bufferered to a specific length and you use that 2) the input doesn't exist yet and will be entered by the user, in which case you use a TEMPORARY giant buffer and strlen.

    I very much doubt it would ever be necessary to realloc() one character at a time, etc. Remember char buffer[8192] is still only 8k of memory, 5-10 pages of actual text.
    Last edited by MK27; 09-17-2008 at 08:06 AM.
    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

  4. #19
    Registered User
    Join Date
    Sep 2008
    Location
    Nort East of Great Britain!
    Posts
    8
    My main concern, at the beginning, was with file/user input. In the form of strings.

    I don't want to just declare a huge array, and hog that memory 'in case' the user puts loads of characters in - neither did I want to limit the amount of characters.

    The whole concept of a temporary "giant buffer" didn't occur in any form. But its seems the most robust system to use.

    Again, thanks for all the info. Its been a big help.

    Its just an odd transition from Academic programming, and trying to find solutions for problems based in reality. It seems for every titbit I learn, I realize just how much more I didn't even realize I didn't know.

    User input, here, being a prime example.

    Clint

  5. #20
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    If, for some reason, you think that a huge buffer isn't the right solution, another method that does work is to check the last character of the input you got from fgets() - if it's a newline, then you got the whole line. If it's not a newline, there is more of that line sitting around waiting to be read [or you got to the end of the file and there was no newline on the final bit of text, in the case of reading text files]. How you handle this depends on what your application is actually trying to achieve - does it NEED to cope with 8000+ character long lines, or is it expected to have only short lines, so we can output an error message and say "Sorry, can't read this line at line number X, it's too long" and quit?

    In some cases, it may also not matter if you take the input as two or more chunks. Just keep calling fgets() until you have processes all of the lines...

    A program should not CRASH from abnormal input, so if your application is reading from stdin, a good test to see that it doesn't crash is to feed the program with itself:
    Code:
    $ myprog < myprog
    or
    Code:
    c:\>myprog < myprog.exe
    .

    --
    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. #21
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by matsp View Post
    If, for some reason, you think that a huge buffer isn't the right solution, another method that does work is to check the last character of the input you got from fgets() - if it's a newline, then you got the whole line.
    Where did you put all the characters you fgot before the newline?
    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

  7. #22
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by MK27 View Post
    Where did you put all the characters you fgot before the newline?
    Eh? if NORMAL behaviour is relative short lines, then you can deal with the problem in this way:
    Code:
    while(fgets(str, ...) != NULL)
    {
        if (strrchr(str, '\n') == NULL)
        {
          // didn't get a whole line. 
          int ch;
          printf("Very long line, skipping it.\n");
          while((ch = fgetc(...)) != '\n' && ch != EOF) ; 
        }
    }
    If you EXPECT to get very long lines [or at least can sort of guess that it MAY happen], then you may need to deal with arbitrary length lines and have to gather it all up in one big lump, something like this:
    Code:
    int uselongline = 0;
    char *longline = NULL;
    while(fgets(str, ...) != NULL)
    {
        char *newline = strrchr(str, '\n');
        if (newline || uselongline)
        {
           longline = realloc(verylongline, strlen(longline) + strlen(str) + 1);
           strncat(longline, str);
           if (newline)  // We've got the whole line
           {      
              dosomething(longline);
              free(longline);
              longline = NULL;
              uselongline = 0;
            } else {
              uselongline = 1;
            }
        }
        else
        {
            dosoemthing(str);
        }
    }
    Note that 8192 may not be sufficient for some purposes. We had an example of badly written software that read a symbol file. When using templates in C++, you can get pretty long symbols. The software was happy with symbols up to about 1500 characters, anything longer would crash(!), but our symbol file had some 9000 character long strings.

    The important point here is that we (sometimes) need to recognize that we get input beyond what we have space for, and we need to do SOMETHING about it. What is right in one case may be wrong in another.

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

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. C++ ini file reader problems
    By guitarist809 in forum C++ Programming
    Replies: 7
    Last Post: 09-04-2008, 06:02 AM
  2. Replies: 4
    Last Post: 03-03-2006, 02:11 AM
  3. Classes inheretance problem...
    By NANO in forum C++ Programming
    Replies: 12
    Last Post: 12-09-2002, 03:23 PM
  4. creating class, and linking files
    By JCK in forum C++ Programming
    Replies: 12
    Last Post: 12-08-2002, 02:45 PM
  5. Warnings, warnings, warnings?
    By spentdome in forum C Programming
    Replies: 25
    Last Post: 05-27-2002, 06:49 PM

Tags for this Thread