Thread: scanf for strings?

  1. #1
    Registered User
    Join Date
    May 2008
    Location
    Australia
    Posts
    230

    scanf for strings?

    Hi, I'm just wondering, what's so bad about using scanf for strings. Like every person I speak to says don't do it, I'd like to know why . Also, as a replacement, if I'm needing to read strings from standard in, can I use something like this?:

    Code:
    strcopy(cArray,"%s", stdin);
    Which, if I'm right, will copy the users input from standard in into the cArray character array. Not sure if my use of strcopy is 100% accurate in the above example though. Thanks.

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Reading strings from stdin can be done with scanf(), although there are plenty of pitfalls in that method. The two most common problems are that the limitation of the string size and that whitespace causes string to be terminated. There are workarounds for both of these, but they are not terribly trivial.

    A better way is (usually) reading an entire line with fgets().

    For further advice, it would be good if you explain further what it is you are attempting to do.

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

  3. #3
    Registered User
    Join Date
    May 2008
    Location
    Australia
    Posts
    230
    Well, as an example, say I wanted to make an encryption program that encrypts a user inputted string by shifting it's ASCII values depending on a 'key' integer variable set by the user.

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Sounds like a typical case for using fgets(), as you are just after reading lines of text. An alternative approach would be to read one character at a time, since you will need to process each character of the input individually anyways.

    Just bear in mind that you will want to either:
    1. Store the output as a binary file.
    or
    2. Not translate newlines (or discard newlines and reformat the input into a new format, e.g. fixed lines of 60 or 75 characters to each line, for example - this is a common trick in cryptography to avoid making the formatting reveal anything about the content).

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

  5. #5
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    The biggest flaw of scanf is that it the default way of doing it means you don't specify the size of your buffer, which means in the user enters a too long string, you get a buffer overrun, which is very bad™.
    You can specify buffer size to scanf, BUT is has to be encoded in the string. So you'll probably have to mess around with creating a proper string from piecing together the format and the buffer size.
    On the other hand, fgets does all this for you. It reads from the specified file as you tell it, you can pass the buffer size as an argument (which means you can pass something such as sizeof(mybuffer)), plus it takes a char* argument IIRC, which means you'll get a warning if you pass an incompatible pointer (in C).

    So all in all, fgets is superior to scanf when reading strings.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  6. #6
    Registered User
    Join Date
    May 2008
    Location
    Australia
    Posts
    230
    Quote Originally Posted by Elysia View Post
    The biggest flaw of scanf is that it the default way of doing it means you don't specify the size of your buffer, which means in the user enters a too long string, you get a buffer overrun, which is very bad™.
    You can specify buffer size to scanf, BUT is has to be encoded in the string. So you'll probably have to mess around with creating a proper string from piecing together the format and the buffer size.
    On the other hand, fgets does all this for you. It reads from the specified file as you tell it, you can pass the buffer size as an argument (which means you can pass something such as sizeof(mybuffer)), plus it takes a char* argument IIRC, which means you'll get a warning if you pass an incompatible pointer (in C).

    So all in all, fgets is superior to scanf when reading strings.
    I thought fgets was for reading strings in a file, and gets was for reading strings from standard in? What's the go.

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by pobri19 View Post
    I thought fgets was for reading strings in a file, and gets was for reading strings from standard in? What's the go.
    Never ever use gets() - it is even worse than scanf(), as you can not avoid buffer overruns in that function (other than having an INFINITELY large buffer, but since that in itself is impossible, that's not an option).

    Use fgets() with stdin as a parameter if you want to read from stdin.

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

  8. #8
    Registered User
    Join Date
    May 2008
    Posts
    53
    Quote Originally Posted by pobri19 View Post
    I thought fgets was for reading strings in a file, and gets was for reading strings from standard in? What's the go.
    You would think that, wouldn't you. Unfortunately, gets() doesn't only default the FILE* to stdin, it also removes the buffer size parameter. This is a historical mistake we'll have to live with.

    --
    Computer Programming: An Introduction for the Scientifically Inclined

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. scanf() consideres useless
    By Snafuist in forum C Programming
    Replies: 15
    Last Post: 02-18-2009, 08:35 AM
  2. Help with a basic scanf procedure.
    By killpoppop in forum C Programming
    Replies: 9
    Last Post: 11-03-2008, 04:39 PM
  3. Replies: 2
    Last Post: 02-20-2005, 01:48 PM
  4. Scanf and integer...
    By penny in forum C Programming
    Replies: 3
    Last Post: 04-24-2003, 06:36 AM
  5. scanf - data is "put back" - screws up next scanf
    By voltson in forum C Programming
    Replies: 10
    Last Post: 10-14-2002, 04:34 AM