Darned scanf function

From Visual Basic to GNU C, this is the place to talk programming.

Moderators: SecretSquirrel, just brew it!

Darned scanf function

Postposted on Mon May 12, 2003 2:56 pm

Ok this is probably the first post of many :-D

I'm trying to make hex-integer converter, since it's an exercise in this book of mine that I'm learning C from... yeah yeah, learning from a book, get the criticisms out of your systems :-D

Anyways, I've got this far...

#include <stdio.h>
#include <ctype.h>
#include <math.h>

main()
{
int i, quit, hex, wait;

printf("Enter hexadecimal number...\n");
scanf("%0X", hex);
printf("%x", hex);

wait = sqrt (3.0);
while (wait != 1){
sqrt(wait);
}

}


About the sqrt bit, that's just an ad hoc way of stalling the program so i can see what it's doing, I'm not really concerned about that...

I've not got anywhere with the hex-int conversion, because I don't really understand the scanf function, and I've never been any good at learning it from cryptic definitions from a book or teacher etc.

It either crashes or gives me a GIGO answer...

Only thing is I don't understand why my input is garbage :-D

So I've reduced the project down to a simple input-output program until I get the hang of the scanf function, only I can't...

Anyone wanna show me the light? lol
IntelMole
Living proof of John Gabriel's theorem
IntelMole
Grand Gerbil Poohbah
 
Posts: 3529
Joined: Sat Dec 29, 2001 7:00 pm
Location: The nearest pub

Postposted on Tue May 13, 2003 4:13 am

OK I'll try to help you despite yesterday's disrespectful post of yours :D .

First: it's not hex-int but hex-dec. Hex. are usually integers, actually.

Q1: You're trying to get a string representing a hex. and convert it manually to an 'int' or to a string representing a dec. ? scanf with the conversion letter 'x' (not 'X' that's only valid for printf and just converts output to uppercase) does it 'automagically'.

About the way of stalling the proggie :D that was fun but you'd better put a simple scanf there too, anyway.

Q2: What compiler are you using?

Cheers and welcome to the C world.

try this:
Code: Select all
[...]
scanf("%0x", &hex);  /* scanf passes a reference */
printf("%x", hex);      /* printf passes a value */
[...]
no sig
muyuubyou
Grand Gerbil Poohbah
 
Posts: 3231
Joined: Wed Aug 28, 2002 6:19 am
Location: London, UK or Tokyo/Yokohama, Japan or Madrid, Spain

Postposted on Tue May 13, 2003 6:08 am

couldnt u jus use an array to store the string?

im new to C too! BTW theres nothing wrong learning from a book!

I remember those days when I taught myself QBASIC without a book, just trial and error here and there!
Windows XP - The 64-bit wannabe with a 32-bit graphics interface for 16-bit extensions to a 8-bit patch on a 4-bit operating system designed to run on a 2-bit processor by a company that can't stand 1-bit of competition
fc34
Minister of Gerbil Affairs
 
Posts: 2816
Joined: Wed May 08, 2002 8:39 am
Location: Somewhere

Postposted on Tue May 13, 2003 6:20 am

Nothing wrong with learning from a book. As long as you have a good book. I learned VB that way.
"I used to think the brain was the most amazing organ in the entire body. Then I realized who was telling me this."
If ignorance were painful, half the posters here would be on morphine drips.
zgirl
Grand Gerbil Poohbah
 
Posts: 3938
Joined: Tue Jan 01, 2002 7:00 pm
Location: The dark side of the moon

Postposted on Tue May 13, 2003 6:54 am

BTW I forgot to tell you why your program crashed/threw garbage.

You passed scanf a bogus reference -> it interpreted the (garbage) unitialized value ('hex') of your int as a pointer and stored your input there. This can (and usually does) overwrite some memory used by the OS (this causes unstability/crashes quite often).

If you got lucky & didn't bring the OS to it's knees, the unitialized 'hex' value gets printf-ed with the %x modifier.
no sig
muyuubyou
Grand Gerbil Poohbah
 
Posts: 3231
Joined: Wed Aug 28, 2002 6:19 am
Location: London, UK or Tokyo/Yokohama, Japan or Madrid, Spain

Postposted on Tue May 13, 2003 12:28 pm

Disrespectful post???

Yeah, the program either crashed at the scanf stage, or gave an ~8 digit number 20788557 something or other... garbage in other words...

A1:
The stall procedure was there because although I can and have used a scanf to quit the program, that was what was crashing the program, so I figured until I got the scanf function down I'd fall back to a quick bit of nearly-infinite loop, I normally use while(1<2) or somesuch but I couldn't resist using the new-fangled sqrt I'd just found... I dunno if you noticed, but I stuck a declaration in there that i don't use, quit... that was a bit of code leftover from what I didn't delete when i started again...

A2:
I'm using a freebie one I downloaded off the net... Bloodshed Dev-C++, as far as I've pushed it, it's not done too bad, but then again, I haven't really pushed it much, as you can tell :-D

One final question: why the &hex instead of just hex... is that a scanf thing, or is it some hexadecimal-related requirement?

Oh yeah, and "automagically"?

That a programmer's official term? :-P,
IntelMole

Edit: Huh?

Code: Select all
main()
{
int quit, hex, wait;

printf("Enter hexadecimal number...\n");
scanf("%0x", &hex);                         /* scanf passes a reference */
printf("%x", hex);                          /* printf passes a value */

printf("Press any key to quit");
scanf("%d", quit);
}


I'm inputting the following hex a2d3 every time, and that fails, so I'm trying just sticking a in there and seeing what it comes up with... and every time it crashes as soon as I press enter!

Once again for emphasis: huh? :lol: Thanks for the help btw,
IntelMole
Living proof of John Gabriel's theorem
IntelMole
Grand Gerbil Poohbah
 
Posts: 3529
Joined: Sat Dec 29, 2001 7:00 pm
Location: The nearest pub

Postposted on Tue May 13, 2003 12:42 pm

Disrespectful post???
Yeah that one where you corrected my "theoretic" for "theoretical". Theoretic does appear in my dictionary anyway :D (= theoretical).

The stall procedure was there because although I can and have used a scanf to quit the program, that was what was crashing the program
I guess you were passing it a value then. Put the '&'. Solved.

I'm using a freebie one I downloaded off the net... Bloodshed Dev-C++, as far as I've pushed it, it's not done too bad, but then again, I haven't really pushed it much, as you can tell :D
AFAIK it's a good one. Doesn't it support console compiling? that way you shouldn't need to make your program stall.

One final question: why the &hex instead of just hex... is that a scanf thing, or is it some hexadecimal-related requirement?
OK there I go again.

&hex is a reference (the address where 'hex' is). scanf (case sensitive, so no capitals :D) needs a reference. If you pass it a value, scanf will think it's a reference anyway (going to somewhere in your memory, as the value indicates, and writing your stuff there. That's hazardous stuff for the OS).

This is 'pointers' stuff. There's a lot of controversy about them. You'll find a lot of scary stuff about this on the net. C/C++ allows you to play with them. This gives you power, but power that will make you goof your programs quite often.


http://info.astrian.net/jargon/terms/a/ ... cally.html :lol:

Edit: argg!!! look at your last scanf
BTW 'any key' there should read 'any key as long as it's Enter (Return for Commodorians)
Last edited by muyuubyou on Tue May 13, 2003 1:01 pm, edited 2 times in total.
no sig
muyuubyou
Grand Gerbil Poohbah
 
Posts: 3231
Joined: Wed Aug 28, 2002 6:19 am
Location: London, UK or Tokyo/Yokohama, Japan or Madrid, Spain

Postposted on Tue May 13, 2003 12:51 pm

BTW take that '0' out of scanf. It's doing nothing but maybe crashing your program if your compiler doesn't ignore it as mine does :D .

scanf("%x", &hex);
no sig
muyuubyou
Grand Gerbil Poohbah
 
Posts: 3231
Joined: Wed Aug 28, 2002 6:19 am
Location: London, UK or Tokyo/Yokohama, Japan or Madrid, Spain

Postposted on Tue May 13, 2003 1:28 pm

muyuubyou wrote:Yeah that one where you corrected my "theoretic" for "theoretical". Theoretic does appear in my dictionary anyway :D (= theoretical).


Oh yeah, that one... I was still right though, wasn't I? :-P

I guess you were passing it a value then. Put the '&'. Solved.


I meant that I felt that as long as I couldn't get the first scanf right, I shouldn't bother putting another set of problems in there, and stick with what I know works ...

AFAIK it's a good one. Doesn't it support console compiling? that way you shouldn't need to make your program stall.


Good question, not yet found that option though...

&hex is a reference (the address where 'hex' is). scanf (case sensitive, so no capitals :D) needs a reference...


Thanks, very well explained :-D

This is 'pointers' stuff. There's a lot of controversy about them. You'll find a lot of scary stuff about this on the net. C/C++ allows you to play with them. This gives you power, but power that will make you goof your programs quite often.


No sh*t :-P


http://info.astrian.net/jargon/terms/a/automagically.html :lol:
I stand corrected... I believe that makes it 1-1 ...

Edit: argg!!! look at your last scanf


Uh huh, <does "poor boy looking for help" look...>

Stuck an amperand on the quit variable, but I still think the problem is with the first scanf since it crashes straight after that...

Of course I could be utterly wrong :-D
IntelMole
Living proof of John Gabriel's theorem
IntelMole
Grand Gerbil Poohbah
 
Posts: 3529
Joined: Sat Dec 29, 2001 7:00 pm
Location: The nearest pub

Postposted on Tue May 13, 2003 1:39 pm

OK copy paste this:

intelMole.c
Code: Select all
#include <stdio.h>

int main(void)
{
int hex, wait, quit;

printf("Enter hexadecimal number...\n");
scanf("%x", &hex);                        /* scanf passes a reference*/
printf("%d", hex);                          /* printf passes a value */

printf("\nEnter a small beautiful number to quit");
scanf("%d", &quit);

return 0; /* Tell the OS there was no problem */
}


printf("%d", hex); /* printf passes a value */
...so the output is decimal (a bit more interesting :D)
no sig
muyuubyou
Grand Gerbil Poohbah
 
Posts: 3231
Joined: Wed Aug 28, 2002 6:19 am
Location: London, UK or Tokyo/Yokohama, Japan or Madrid, Spain

Postposted on Tue May 13, 2003 1:57 pm

ROFLMAO :-D

I've just done a copy and paste of your code, which was virtually identical to my version (I added the & in the last scanf...), I've run it... stuck in "a" as the value...

STIL it crashes! :-D

<homer> Something's wrong... </homer>

Even though I KNOW your code is right (okay, maybe I've a strong inkling), it still crashes the instant after the value is entered...

V confusing...


Ok this is probably the first post of many :-D


Warned ya :lol:,
IntelMole[/quote]

edit: found problem... I was running the .c file instead of the .dev file... which seems to have found the problem...

Thanks loads muyuubyou,
IntelMole
Living proof of John Gabriel's theorem
IntelMole
Grand Gerbil Poohbah
 
Posts: 3529
Joined: Sat Dec 29, 2001 7:00 pm
Location: The nearest pub

Postposted on Tue May 13, 2003 2:19 pm

Good thing you show some confidence :D

IntelMolev2_0.c
Code: Select all
#include <stdio.h>

int main(void)
{
int hex, quit;

printf("Enter hexadecimal number...\n");
scanf("%x", &hex);                      /* scanf passes a reference*/
printf("%x hex is %d dec", hex, hex);        /* printf passes a value */

printf("\nEnter a small beautiful number to quit: ");
scanf("%d", &quit);
printf("Have a nice day\n");

return 0; /* Tell the OS there was no problem */
}


If this doesn't work send it to the guys at BloodShed. Maybe they have some lack of %x support (nobody uses that **** with scanf :D).

Works here. Just tried it using gcc with -pedantic flag.

See you 2morrow
no sig
muyuubyou
Grand Gerbil Poohbah
 
Posts: 3231
Joined: Wed Aug 28, 2002 6:19 am
Location: London, UK or Tokyo/Yokohama, Japan or Madrid, Spain

Postposted on Tue May 13, 2003 2:41 pm

My compiler help says you have to use an unsigned int as the pointer to pass, though I doubt that is casing the problem since they are typically the same size.

void main(void)
{
int quit;
unsigned int hexVal;

printf("Enter hexadecimal number...\n");
scanf("%08X", &hexVal); /* scanf passes a reference, 8 numbers max, x == X*/
printf("0x%08X hex is %d dec", hexVal, hexVal); /* printf passes a value capitol X makes hex characters upper case */

printf("\nEnter a small beautiful number to quit: ");
scanf("%d", &quit);
printf("Have a nice day\n");

return 0; /* Tell the OS there was no problem */
}
liquidsquid
Minister of Gerbil Affairs
 
Posts: 2447
Joined: Wed May 29, 2002 10:49 am
Location: New York

Postposted on Wed May 14, 2003 3:17 am

Well liquidSquid, I checked the ANSI and says nothing about the need of using unsigned there. Thanks anyway for taking the time to check it and not leaving all the work to me :D .

BTW main can't return void (that's not standard), more even so if you explicitly return 0 at the end of the proggie.

scanf does not support capital 'X' (it's 'x' but compilers usually swallow that anyway). Printf does do what you say if you use capital X (in case you want uppercases...).

stdio.h is needed.

I think I'll download his compiler (he said he used Bloodshed) to check it out... I think that compiler is french, so it surrenders quite easily :D
no sig
muyuubyou
Grand Gerbil Poohbah
 
Posts: 3231
Joined: Wed Aug 28, 2002 6:19 am
Location: London, UK or Tokyo/Yokohama, Japan or Madrid, Spain

Postposted on Wed May 14, 2003 7:48 am

It can't return void only on programs that are within other calling programs like an OS on a PC. I have been programming embedded stuff, so if you even exit main() you are lost in space. My main() is the primary end all of be all function, and has no return (where would you go?). Sorry about any confusion.

BTW I tried this routine on my system (68EZ328 based) and it seems to work and compile just fine, but it took some doing since I didn't have the I/O hooked up to allow scanf and printf to work properly. I have my own much more simple routines for these functions to reduce the footprint.

If all else fails, have the user input a string instead, limiting the characters to 0-9, A-F, then convert the string to an int manually. Then printf should be able to format it any way you want. What you may be running into is the compiler isn't completly supportive of all input types in the scanf function. Many free compilers are not 100% complient, or will do things slightly different than the ANSI standard. You will have to pour through the documentation to see if the scanf() has hex input support implimented.

Otherwise I think Borland has one of thier C++ compilers available for download for free out there somewhere, and that is quite loaded with features and produces fantastic output. I would go find that if you can.

-LS
liquidsquid
Minister of Gerbil Affairs
 
Posts: 2447
Joined: Wed May 29, 2002 10:49 am
Location: New York

Postposted on Wed May 14, 2003 8:24 am

Well I have plenty of compilers. I usually go fine with GCC.

IntelMole is who's using Bloodshed and is trying to get into the wild C world :D

Yeah LS printf and scanf aren't exactly the bed for embedded systems. Worked in Japan programming microcontrollers and I know for sure ;)

Hey IntelMole, what version did you download? are you using the IDE?
Looks like it's using GCC (same as me!). Open a DOS shell and try compiling it using the command line (gcc -c crap.c -o crap.exe) :D
no sig
muyuubyou
Grand Gerbil Poohbah
 
Posts: 3231
Joined: Wed Aug 28, 2002 6:19 am
Location: London, UK or Tokyo/Yokohama, Japan or Madrid, Spain

Postposted on Wed May 14, 2003 10:06 am

I just use LCC BASE system for windows. Works fine, and is free.

download it at: http://www.cs.virginia.edu/~lcc-win32
Windows XP - The 64-bit wannabe with a 32-bit graphics interface for 16-bit extensions to a 8-bit patch on a 4-bit operating system designed to run on a 2-bit processor by a company that can't stand 1-bit of competition
fc34
Minister of Gerbil Affairs
 
Posts: 2816
Joined: Wed May 08, 2002 8:39 am
Location: Somewhere

Postposted on Wed May 14, 2003 7:17 pm

I just downloaded the version on downloads.com

http://download.com.com/3000-2069-16832 ... ag=lst-0-1

IDE version?

lol, I dunno, I just run the thing,
IntelMole
Living proof of John Gabriel's theorem
IntelMole
Grand Gerbil Poohbah
 
Posts: 3529
Joined: Sat Dec 29, 2001 7:00 pm
Location: The nearest pub

Postposted on Fri May 16, 2003 5:08 am

From your link:
Bloodshed Dev-C++ 4.0 is a full-featured programming environment and compiler for creating software in C++. Included in the Dev-C++ environment are all of the standard features necessary for writing, compiling, debugging, and executing programs written in C.
Strictly for the hard-core C++ programmer, Dev-C++ allows you to compose all of your source code without many of the hand-holding features and expenses included in many of the available programming environments.

If you know how to program in C++, Bloodshed Dev-C++ 4.0 lets you do exactly that.

So it's 4.0. I won't care about the "strictly for the hardcore C++ programmer". C++ won't be any more difficult for such claims :D.

I guess you're using the IDE (Integrated Development Environment).

Try opening a DOS shell and doing "gcc" and see what happens...

I'm using Yahoo messenger, just in case you didn't notice. I have a MSNmessenger account too but I don't use it too often. Maybe that's better way to get this running (when I have the time, of course :D).

I guess you want to start programming stupid games real soon, don't you?. I prefer linux rather than windows as target anyway ;) but we can try making things portable.
no sig
muyuubyou
Grand Gerbil Poohbah
 
Posts: 3231
Joined: Wed Aug 28, 2002 6:19 am
Location: London, UK or Tokyo/Yokohama, Japan or Madrid, Spain

Postposted on Fri May 16, 2003 5:51 am

I'm not sure why are you getting that error. I just downloaded it from your link, and it **** works!! :D

Just double-clicked on the .c (associated .c to it during set-up, as it does by default) and compiled-executed it...

You tell me what you're doing, mate :D
no sig
muyuubyou
Grand Gerbil Poohbah
 
Posts: 3231
Joined: Wed Aug 28, 2002 6:19 am
Location: London, UK or Tokyo/Yokohama, Japan or Madrid, Spain

Postposted on Sat May 17, 2003 5:13 am

Muyuubyou, I've got the thing working... yello? :-P

I was compiling the .c file, which I expect caused the compiler to screw itself and produce silly code somehow. Compiling the .dev file produced a program that works flawlessly...

BTW, I have a theory about how the thing works...

When you input the hex number, as long as C knows it's a hex number, it'll store the number in memory, but in binary. From there, binary -> integer conversion is easy. Am I close?

Thanks again,
IntelMole
Living proof of John Gabriel's theorem
IntelMole
Grand Gerbil Poohbah
 
Posts: 3529
Joined: Sat Dec 29, 2001 7:00 pm
Location: The nearest pub

Postposted on Sat May 17, 2003 8:14 am

Of course it's stored in binary :D . The scanf function does all the conversion (in the same way it does when you pass it a dec number via %d).

In fact, when you explained your problem I thought you wanted to program the conversion yourself, and not simply calling scanf to do it ;)

How is your progress going? I want you to start with some SDL and OpenGL real soon. 8)
no sig
muyuubyou
Grand Gerbil Poohbah
 
Posts: 3231
Joined: Wed Aug 28, 2002 6:19 am
Location: London, UK or Tokyo/Yokohama, Japan or Madrid, Spain

Postposted on Mon May 19, 2003 1:14 pm

The problem might just be that Dev-C++ is a C++ compiler, not a C compiler. While C is virtually a subset of C++, there are some C things that just will not work with an ANSI C++ compiler.

LiquidSquid:
Code: Select all
scanf("%08X", &hexVal); /* scanf passes a reference, 8 numbers max, x == X*/


C does not have references. Just pointers.
Code: Select all
&hexVal
is a pointer to hexVal, not a reference. The scanf function only takes pointers to variables, not references (because they don't exist in C). It is very important to understand the difference if you get into C++ or any other language that has real references.

muyuubyou:
How is your progress going? I want you to start with some SDL and OpenGL real soon.


Cool, I am writing a windows app that uses OpenGL at work right now to do some graphical analyzation of data we collect from the international space station. Let me know if you need any help.
Last edited by Veritas on Mon May 19, 2003 1:33 pm, edited 1 time in total.
Veritas
Gerbil First Class
 
Posts: 113
Joined: Wed Dec 26, 2001 7:00 pm
Location: Houston, TX

Postposted on Mon May 19, 2003 1:29 pm

Code: Select all
void main(void)


Ack!!!!

Never use main like that. Even if your compiler allows it. It is not valid ANSI C and will not compile with compilers that actually do make the effort to be standard compatible. And if the OS you are running the program on expects a value to be returned, returning a void could be all kinds of trouble.

main() should always return an int as such:

Code: Select all
int main(void)
{
   return 0;
}



EDIT: Yes, I am a stickler for following standards. :)
Veritas
Gerbil First Class
 
Posts: 113
Joined: Wed Dec 26, 2001 7:00 pm
Location: Houston, TX

Postposted on Mon May 19, 2003 1:47 pm

liquidsquid wrote:void main(void)

Non-standard, diagnostic required. Microsoft violates the standard by accepting this without a diagnostic.

I don't know if the C standard allows it, but the C++ standard allows no return from main(), e.g.

Code: Select all
int main(void)
{
// ... etc ... - no return statement
}


Of course, VC6 (haven't tried VC7.1 yet) converts this into void main(). :x
Craig P.
Gerbil Team Leader
 
Posts: 285
Joined: Tue Dec 31, 2002 3:12 am
Location: South Bend, IN

Postposted on Mon May 19, 2003 2:11 pm

I'm a little late to this party, it seems... :D

For interactive command line programs, fgets() is actually a bit better than scanf(), as it is line-oriented rather than field-oriented. E.g., you can re-prompt the user if they don't enter a valid hex number, and you can also allow the user to just hit Enter to exit, instead of having to enter another number:

Code: Select all
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>

int main(void)
{

    char buffer[12];
    long value;

    do
    {
        printf("Enter hexadecimal number...\n");
        fgets(buffer, sizeof(buffer), stdin);   /* read string */
    } while (!isxdigit(buffer[0]));             /* until we get valid hex */

    value = strtol(buffer, NULL, 16);           /* convert from hex */

    printf("0x%08lX hex is %ld dec\n", value, value);     /* output */

    printf("Hit Enter to quit: ");
    fgets(buffer, sizeof(buffer), stdin);       /* wait for user to hit Enter */
    printf("Have a nice day\n");

    return 0; /* Tell the OS there was no problem */

}
Last edited by just brew it! on Mon May 19, 2003 2:46 pm, edited 1 time in total.
just brew it!
Administrator
Gold subscriber
 
 
Posts: 37705
Joined: Tue Aug 20, 2002 10:51 pm
Location: Somewhere, having a beer

Postposted on Mon May 19, 2003 2:26 pm

I don't know if the C standard allows it, but the C++ standard allows no return from main(), e.g.


I tried it with gcc and it creates an executable, but it gave me this warning:

main.c:10: warning: control reaches end of non-void function
Veritas
Gerbil First Class
 
Posts: 113
Joined: Wed Dec 26, 2001 7:00 pm
Location: Houston, TX

Postposted on Mon May 19, 2003 2:54 pm

Veritas, what version of gcc and what command line switches? With gcc 3.2 and -pedantic (or -Wall) I don't get the warning. It seems that main() is treated as a special case; for any function other than main(), -Wall will result in a warning if a non-void function is missing the final return statement.
just brew it!
Administrator
Gold subscriber
 
 
Posts: 37705
Joined: Tue Aug 20, 2002 10:51 pm
Location: Somewhere, having a beer

Postposted on Mon May 19, 2003 3:52 pm

I used -pedantic and -Wall

However, I was actually using mingw (gcc v3.2 for windows) so that may make a difference.


Edit:
I just tried it on my BSD box running gcc 2.95.3 and got this
[job ~/test]$ gcc -Wall main.c -o main
main.c: In function `main':
main.c:6: warning: control reaches end of non-void function
[job ~/test]$
Last edited by Veritas on Mon May 19, 2003 3:56 pm, edited 1 time in total.
Veritas
Gerbil First Class
 
Posts: 113
Joined: Wed Dec 26, 2001 7:00 pm
Location: Houston, TX

Postposted on Mon May 19, 2003 3:55 pm

I tried both on a Redhat 8.0 system, and on Windows (using Cygwin). Ahh well, one of the great mysteries of the universe, I guess! :wink:
just brew it!
Administrator
Gold subscriber
 
 
Posts: 37705
Joined: Tue Aug 20, 2002 10:51 pm
Location: Somewhere, having a beer

Next

Return to Developer's Den

Who is online

Users browsing this forum: No registered users and 2 guests

cron