Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

HiRez

macrumors 603
Original poster
Jan 6, 2004
6,265
2,630
Western US
OK so I'm taking a C class to sharpen up my C skills, but I'm having a real hard time with the input methods. First of all a lot of people say don't use gets(), ever. It's dangerous because it doesn't do bounds checking, use fgets() instead. Fine, but the problem with that is that for some reason fgets() stores the newline character in the string. Normally that's probably not what you'd want because now if you store someone's name, for example, and print it in a list or table, it's going to print that newline along with it. So I have no idea what they were thinking there, especially since that's supposed to be the file equivalent of gets(), which does not store the newline character in the string. And it turns out it's a real PITA to actually do all the checking you need to see if you got a string at all, if the length is the same as, less than, or more than the maximum you specified, and then manually figuring out how to manipulate the string, inserting and removing \n and \0 characters to get a proper string. Using %s in scanf()/fscanf() has all kinds of problems too, not the least of which is that it's going to stop when it hits a whitespace character, so you can't do something like just get someone's full name.

Then there's the problem of a lot of these functions leaving newlines and/or garbage in the input buffer, so while it might read something right the first time, the next time you go to read you get some really weird results. And there doesn't seem to be an easy way to clear out that buffer either (which these functions should probably optionally be able to do themselves, but they don't). There's the fflush() function, but it's supported in different ways (including not at all) on different platforms, and I've seen multiple people say never try to use it to flush input, even if the platform claims to support it.

Finally, I'm just specifically getting weird behavior using Xcode with the "Standard Tool" type and any of the ANSI options (trying to use C99) selected. fgetc(), for example, will work OK in one run of the program, then sometimes it will randomly send itself into an endless loop, pouring characters I'm not typing into the input and eventually crashing the app if I don't force-kill it.

The bottom line is all these C input functions just seem like a huge, unholy pile of crap. They're broken, buggy, unsafe, difficult to get what you want out of them when they do work (like, say, a single character typed on the keyboard), and have unpredictable behavior. When they wrote the C99 spec, wouldn't that have been a good place to fix all these things and implement newer, cleaner library functions? :rolleyes: Maybe it's just me, but I see a ton of people having the same types of issues online, not just in the Mac/Xcode/GCC implementation, but with all versions of ANSI C.

I guess my question is, what am I missing here? Are there replacement functions I'm not aware of? Am I just crazy? Is it really as bad as it looks to me?
 

pilotError

macrumors 68020
Apr 12, 2006
2,237
4
Long Island
OK so I'm taking a C class to sharpen up my C skills, but I'm having a real hard time with the input methods. First of all a lot of people say don't use gets(), ever. It's dangerous because it doesn't do bounds checking, use fgets() instead. Fine, but the problem with that is that for some reason fgets() stores the newline character in the string. Normally that's probably not what you'd want because now if you store someone's name, for example, and print it in a list or table, it's going to print that newline along with it. So I have no idea what they were thinking there, especially since that's supposed to be the file equivalent of gets(), which does not store the newline character in the string. And it turns out it's a real PITA to actually do all the checking you need to see if you got a string at all, if the length is the same as, less than, or more than the maximum you specified, and then manually figuring out how to manipulate the string, inserting and removing \n and \0 characters to get a proper string. Using %s in scanf()/fscanf() has all kinds of problems too, not the least of which is that it's going to stop when it hits a whitespace character, so you can't do something like just get someone's full name.

That was quite a ramble...

Welcome to C, where it all began...

Knowing that you will get a newline character at the end of the buffer, you can just null terminate the buffer. If you do this on a Pee Cee, you'll have to use a strlen -2 because you DOS / Windows uses a \r\n combination for end of line.

mystring[ (strlen(mystring) - 1) ] = 0;

Then there's the problem of a lot of these functions leaving newlines and/or garbage in the input buffer, so while it might read something right the first time, the next time you go to read you get some really weird results. And there doesn't seem to be an easy way to clear out that buffer either (which these functions should probably optionally be able to do themselves, but they don't). There's the fflush() function, but it's supported in different ways (including not at all) on different platforms, and I've seen multiple people say never try to use it to flush input, even if the platform claims to support it.

Unfortunately you need to figure it out. You can write a little wrapper function and do a getch to clear the buffer.

Finally, I'm just specifically getting weird behavior using Xcode with the "Standard Tool" type and any of the ANSI options (trying to use C99) selected. fgetc(), for example, will work OK in one run of the program, then sometimes it will randomly send itself into an endless loop, pouring characters I'm not typing into the input and eventually crashing the app if I don't force-kill it.

This does happen, there's a thread on here somewhere that talks about it.


The bottom line is all these C input functions just seem like a huge, unholy pile of crap. They're broken, buggy, unsafe, difficult to get what you want out of them when they do work (like, say, a single character typed on the keyboard), and have unpredictable behavior. When they wrote the C99 spec, wouldn't that have been a good place to fix all these things and implement newer, cleaner library functions? :rolleyes: Maybe it's just me, but I see a ton of people having the same types of issues online, not just in the Mac/Xcode/GCC implementation, but with all versions of ANSI C.

It gives you a real appreciation for C++ and Java input libraries...

I guess my question is, what am I missing here? Are there replacement functions I'm not aware of? Am I just crazy? Is it really as bad as it looks to me?

People have written input libraries. Check sourceforge for the various implementations. OS X does some weird stuff with command line input in a terminal window, you just need to work through it. It is much easier on the Unix / Linux variants (ie. works as expected).
 

ChrisA

macrumors G5
Jan 5, 2006
12,919
2,173
Redondo Beach, California
I guess my question is, what am I missing here? Are there replacement functions I'm not aware of? Am I just crazy? Is it really as bad as it looks to me?

You write a function called "GetFullName()" once and then never again in your entire life will you need to do it again. But it is hard. In yor rant you forgot about the need to handle backspaces and tabs. and that is just the beginning

I use the GNU "readline" library. This allows a user to edit the line, do a tab completion, up arrow key to recall the last thing he entered and so on and so on. I think most users who type at the prompt expect this now.
http://directory.fsf.org/project/readline/

If the input is complex I've even used flex/bison.
 

HiRez

macrumors 603
Original poster
Jan 6, 2004
6,265
2,630
Western US
Thanks for the thoughts guys, I appreciate it. I guess I'm just spoiled with all these modern languages and APIs like Objective-C and Python that make text input so painless, simple, accurate, stable, safe, and predictable. Maybe I will appreciate them more now because it's very frustrating in C.

Thank you for the input library suggestions, perhaps I will use them at some point. Unfortunately for this class I think I'm stuck with whatever is built-in or part of the ANSI library, so I cannot use those.
 

Cromulent

macrumors 604
Oct 2, 2006
6,817
1,102
The Land of Hope and Glory
Generally C programmers tend to develop their own libraries as they go that they can reuse in the future. Painful at first but you soon get a nice collection of useful functions you can use anywhere.
 

edenwaith

macrumors 6502a
Aug 7, 2001
689
90
Just call "chomp". Oh, wait, that's Perl. Heh-heh.

Similar principle, though, when Perl reads in a line from the command-line, it brings in the carriage return as well, so that is something you have to keep a close eye on.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.