CompuServe Thread

#C problems

24 messages in this thread
#8026From: Henry WilliamsMar 1, 1991 3:16 PM
Hi Amiga folk! I have 2 puzzles on my mind right now and would appreciate any help. 1) I can compile this without errors on my Aztec 3.6a but when I link I get this message: Undefined symbol _printf it is in reference to the default: choice of the switch however it looks clean to me and when I put it in remarks I can link normally. Problem 2) after starting the program, getchar() accepts the choice ok however, the next time through it is bypassed and goes to the default choice. It then stops on the third time through and accepts a choice normally again. Thanks for any help………….Henry #include <stdio.h> main() { int go = 0; char c; while (go == 0){ printf ("\t (V)iew File (C)hange Record (A)dd Record\n"); printf ("\t (H)ard Copy (D)elete Record (Q)uit program\n"); c = 0; c = getchar(); switch (c) { case 'v': /* Note irrelevant code removed */ break; case 'c': break; case 'a': break; case 'd': break; case 'h': break; case 'q': go = 1; break; default: printf ("something to print\n"); break; } /*end of switch*/ } /*end of while loop*/ } /*end of main function*/
#8028From: Greg Comeau@Comeau CmptgMar 1, 1991 7:13 PM
Are you saying that even though there are printf's up higher that you get an unresolved printf until you comment out the printf associated with the default?? Re the alternative getchar() every other time though, do you by any chance do something like:d<return>? That is, is the other time the <return>? BTW, why c = 0; immediately followed by c = getchar()? Also, although it may not be obvious, you should make 'c' and int rather than a char, as getchar() "returns" an int, not a char (since it's gotta handle EOF being -1).
#8099From: Henry WilliamsMar 4, 1991 1:23 PM
Hello Greg. Thanks for the help. Yes, that is right. I had other printf's in the other cases but when I got to the default choice the linker came back with the message… undefined symbol: _printf. I put it in /* */ and the program linked normally. I copied the switch segment right from a book and it should work right? I was aware that the getchar() returns an integer, it's just that I am using it just for the purpose of receiving one of the six letters of my menu so I felt it should pass ok. I know I could have used a scanf to do the same thing but I'm learning and want to understand all possible uses for everything. As far as a return goes, I had a printf in all the cases, and all is inside the while loop in main. What you saw was just about all there was. I was just starting the program (and didn't get too far<smile>), and was testing the starting menu when I had this happen. Regards Henry…..thanks again!
#8037From: Don Curtis/SYSOPMar 2, 1991 1:10 AM
Henry, In reference to the printf error…re-type the line. You may have a hidden character in there (such as a control character) that your editor doesn't display. In reference to the getchar() call, you should always flush standard input before using getchar() since the default is buffered i/o. Don
#8043From: Greg Comeau@Comeau CmptgMar 2, 1991 8:41 AM
>In reference to the getchar() call, you should always flush standard >input before using getchar() since the default is buffered i/o. I must take issue with that: flushing standard input should only be something contemplated in respect to the logic of a *specific* program and not all programs. Also, flushing the stream will not give him unbuffered abilities (unless Aztec is not standard), he'll have to use a set*buf() function for that if he deems it desirable.
#8063From: Don Curtis/SYSOPMar 3, 1991 12:12 AM
Greg, No, flushing the buffer won't give you the equivalent of unbuffered input, but it will clear any extraneous characters from the input buffer. Failing to flush the buffer prior to the read ends up causing the exact problem that started this thread. I would say it's the exception, rather than the rule where you wouldn't want to flush stdin prior to using getchar(). Don
#8091From: Greg Comeau@Comeau CmptgMar 4, 1991 9:27 AM
>No, flushing the buffer won't give you the equivalent of unbuffered >input, but it will clear any extraneous characters from the input buffer. Although input stream fflush's may appear to work in that manner, it is very non-portable for a few reasons. I've mentioned some below. >Failing to flush the buffer prior to the read ends up causing the exact >problem that started this thread. I'm not convinced it is. Being require to do a flush (fflush()) could be too strong a requirement and is an indication to me that the program perhaps didn't do something it should have done or that the users didn't do something they should have done. >I would say it's the exception, rather than the rule where you >wouldn't want to flush stdin prior to using getchar(). Disagree. It should be up to the logic of the program at hand. Furthermore as mentioned above, this is not what fflush() is for. Fflush() is for *output* streams ONLY. A fflush() that works ok for input is not standard. Furthermore, even if fflush() did work on stdin (and it does for many compiler systems) it only buys you a bit … as then you are assuming a number of things like line-buffering and tty input and that needn't be the case at all.
#8100From: Henry WilliamsMar 4, 1991 1:26 PM
Hi Don. I'll check on that hidden control character possibility. I put #ifdef debug statements in the program and what happened was that the first time through the while loop c was == to the chosen option by the getchar(). But the second time through it printed nothing. Don't know if it was a null, space or what. I put the c = 0 there trying to satisfy the getchar try for the next char but it didn't help. This flushbuffer thing. The only flush anything I have found in my manual is FlushCList (cList). As you may recall, I'm teaching myself C at home as a hobby, so I may not understand some of your lingo <smile>. I appreciate the help all the same. Thanks Henry
#8137From: Robert HayesMar 5, 1991 8:42 PM
When you defined c as a char, but then set it as an int (c=0), I'm surprised there were not any compiler errors (var vs. return mismatch). Also, I think that when you surrond a switch choice e.g. 'd', the switch integer is checked against the numeric value of d. Have you defined c as an int and tried to compile that way? Robert 8)
#8142From: Greg Comeau@Comeau CmptgMar 5, 1991 10:17 PM
If I recall his program there were probably no errors as a char *is* an integer of sorts….
#8157From: Robert HayesMar 6, 1991 6:20 PM
True enough, but beauty is only skin deep. If _everybody_ would learn how to program in _assembly_, we wouldn't have these type of problems. However, after looking the program over, I feel humbled by the root of the problem. I use Manx, and you must link with the -lc32 library as: ln program.o -lc32 Also, delete the c = 0, it is not needed. But of course, you will find that now you have two "responses" every time you "enter" a keystroke. The getchar() is not really suited to reading from the keyboard. What now happens is that the correct choice he made is printed to screen first, then the default choice is printed because getchar() also accepts and sends his program the "enter" key (that is '\r', I believe). The programmer , would be better off defining a char string of 2 char long, and just compare the first char in the string with the case statement. I felt humbled because it took me 1.5 hours of "ferocious" programming to remember about the -lc32 thing and the printf for Manx. Robert (when it rains, I get wet)
#8164From: Greg Comeau@Comeau CmptgMar 6, 1991 10:40 PM
>you will find that now you have two "responses" every time you "enter" a >keystroke. The getchar() is not really suited to reading from the keyboard. Sorta… It is if you let it. Also, many C compiler do have strict console oriented I/O routines, whether this one does I do not know. >What now happens is that the correct choice he made is printed to screen >first, then the default choice is printed because getchar() also accepts and >sends his program the "enter" key (that is '\r', I believe). No. <enter> is a character in its own right, so there is not two responses, but two characters (I mentioned the fact that the original poster may have been hitting the <enter> key in my original reply to the message, but I do not believe that the poster has addressed this yet). >The programmer , would be better off defining a char string of 2 char long, >and just compare the first char in the string with the case statement. But then he wouldn't be doing getchar() but something like gets()'s. That would work if he only wanted to pull in the first character of every line. There are numerous other programmable alternatives as well.
#8189From: Robert HayesMar 7, 1991 8:35 PM
It sounds like you agree somewhat. But I did find out the enter key is the newline character. That *is* the second response he is referring to. Also, looking at his program, it is plain he only wants the _first_ char typed in. Either way, the computer is not a smart machine, just fast. He must find a way to deal with newline since he is dealing with a buffered input. Either go to a char string input, or do the dreaded unbuffered input routine (fear of the unknown, there). Of course, "there should be a call to fflush() between input and output calls. The call ensures that any input or output collected in intermediary buffers is sent on…….." This is a direct quote from my C manual. I do use this on the DOS machines at work, but I'm not doing anything dealing with console currently on the Amiga. For me, it usually winds up being easier to just use a char string. I'm not looking for eloquence, I'm looking for sturdiness and the easy way to do things (as long as it doesn't resemble spaghetti). We both agree, and I've born it out by a small program, the second time his program responds it is due to the newline character as you mentioned in your first message. I've never been able to read from the unbuffered console, of course I haven't really _tried_ to either. BTW, IMHO, the char string is best (for me), I need to check inputs some of the time and manipulate the string itself. Robert 8)
#8206From: Greg Comeau@Comeau CmptgMar 8, 1991 2:09 AM
>or do the dreaded unbuffered input routine And what would that be? Don't Ami C compiler support setbuf/setvbuf()?? >Of course "there should be a call to fflush() between input and output >calls. The call ensure that any input or output collected in >intermediate buffers is sent on…" This is a direct quote from my >C manual. Your C manual is wrong from both a C standard perspective and a logistic one (input buffers can't be "sent on", that makes no sense). A direct quote from ANSI C tell us: "If 'stream' points to an output stream or an update stream in which the most recent operation was not input, the fflush function causes any unwritten date for that stream to be delivered to the host environment to be written to the file; otherwise, the behavior is undefined." So like I said earlier, fflush() is for output even though many C compiler do support fflush()ing input streams. Why standard doesn't allow the input stream this capabilility is because the fflush() can become quite futile given that the host environment has input mechanisms that occur before that hit into the stdio subsytem with the effect that the fflush() becomes innocuous in some cases and logically detrimental in other cases.
#8222From: Robert HayesMar 8, 1991 6:57 PM
Well, it won't be the first time I ever read something that was wrong! On the other hand, with Aztec 3.6a I couldn't find a setvbuf function. There is a setbuf function. If he needs to use setvbuf, he will need to upgrade to 5.0d. The dreaded unbuffered is a misnomer. I really meant to refer to reading a keystroke as it occurrs, without waiting for return or enter. I played with that a while today, and I think I'll just wait until I return from vacation prior to playing with it anymore. It's against the law to do anything that looks like work on vacation time. I suppose this means you'll want me to clean up my dos code for the fflush stuff? If you insist (I was working on a GUI anyway) <g>…….. Robert Life is too much fun for any foolish seriousness…..
#8241From: Greg Comeau@Comeau CmptgMar 9, 1991 9:55 AM
>with Aztec I couldn't find a setvbuf function setvbuf() is a superset of setbuf(), the former being ANSI and the latter being a UNIXism. >I suppose this means you'll want me to clean up my dos code for the >fflush stuff? So long as you brought it up, yes! Ya see, what the compiler vendors are probably doing is just resetting the buffer pointer and some other stuff which becomes innocuous for something like stdin, so it *appears* that the “input buffer'' has been cleared. What's at issue is exactly what this input buffer is as well as where it is. In that light input is different from output since you may have type a 20 character line but under most environments stdio won't know anything about it until you hit the return (and then there are all sort of other idiosyncrasies like your stdio buffering requests as well as you environments buffering settings. And of course it gets even more confusing when the input then comes from a file rather than an “interactive device'').
#8342From: Robert HayesMar 12, 1991 7:33 PM
Vacation already over, some vacation. Well, as far as this input and output stuff is concerned, bear in mind that an "input" is really an "output", and vice versa. You are only guided by common sense, e.g. you wouldn't want to open the printer and try to get "input" from it. The input and output names attached to streams are purely to assist in the art of programming them, IMHO. As I said before, if everybody programmed in _assembly_ you wouldn't have these problems. You'd have better, *bigger* problems (think of the challenge). It does not surprise me that most compilers might handle things different. The reason Manx 3.6a seems to lack setvbuf compared to Manx 5.0d is due to the ANSI compliance of Manx Aztec C. K&R left C vague in places, to allow for flexibility ( I *hope* ), and now some committee wants to standardize to Cobol or Pascal type restrictions. Then you wouldn't be able to get away with a statement like char is a type of int, in reality. IMHO, C grew so fast, comparatively speaking, due to the enormous flexibility (and hence responsibilities) of the syntax; and now some committee is going to kill this flexibility for programmers that can only live in a nonflexible environment where exacting rules have to be followed. I will suffer with it as long as I can, and then revert back to pure assembly programming since the only reason I took up C several years ago was because other technical friends insisted it wasn't the same old syntax restructured/relabeled. I actually have assembly printouts several years old that I can still follow (due to comments and structure). I just *hope* the committee doesn't butcher C, but sometimes these guys are worse than congress. BTW, that is not to say they haven't done _some_ excellent work, I just don't remember any. 8) 8) 8) Robert (back and mean as ever)
#8356From: Greg Comeau@Comeau CmptgMar 12, 1991 11:06 PM
Actually, the ANSI C committe killed although no flexibility and left the language relatively intact. Also, I'd rather have some things lost rather than the sad state of affairs that the "portability" of C was in when the committee was formed (and for C, the sad state was a direct effect of irresponsible vendors IMO). Anyway, it wasn't butchered…
#8217From: Henry WilliamsMar 8, 1991 3:33 PM
Hi Robert. I'm aware that I didn't really need the c = 0. It was just done in frustration in not working out the bug <smile>. I don't understand why I need to link in the -lc32 library though. Would it have to do with portability? There is one problem I have been trying to figure out that you might be able to help me with… If I wanted to print some text to the screen for a period of time and then let it clear I see UNIX has the function sleep(number); where number is a # of seconds. Have you seen the same effective function in MANX? I have the 3.6a and haven't seen anything like it. Another way would be is to have the user -Hit any key- and the program continues. If it isn't to long an explanation, could you tell me how to get that to work WITHOUT having to hit the return key? Or at least tell me what section to read up on. Thanks for your time! Henry = Henry;
#8223From: Robert HayesMar 8, 1991 7:06 PM
All I can say is that printf must be a 32 bit implementation, necessitating (scooze my spelling) the linkage with the 32 bit library. There is a function called Delay() in the Amiga. 50 ticks is a second, so to wait for 10 seconds your line would look like: Delay(50*10); /* wait 10 seconds */ Delay() is in the dos.library. Robert 8)
#8249From: Henry WilliamsMar 9, 1991 1:49 PM
Okie dokie! Thanks again Robert. Henry;
#8248From: Steve AhlstromMar 9, 1991 12:32 PM
Henry, You might try using the timer.device to time how long your message will stay on screen or use the AmigaDOS function Delay(). By using the timer.device your program can continue running while it's waiting for timer event. If you use Delay() your program will not continue running during the waiting period (but other tasks/programs will). -sja
#8250From: Henry WilliamsMar 9, 1991 1:52 PM
OK thank you Steve. It sounds like what I want. Henry;
#8216From: Henry WilliamsMar 8, 1991 3:13 PM
Hi Robert. I'll give the int declaration a try. Thanks for the suggestion. { Henry };