i need help about Turbo C

P

pipito

Hi...i am a beginner in C programming...
my question is like this...
im using the scanf in C to accept input data in output area,

printf("name: ");scanf("%s",name);
printf(Address: ");scanf("%s",address);
printf("age: ");scanf("%d",age);

when i run the program, i use a spacebar in the input data, the
following string after i press the space bar doesnt read anymore or it
skip and going to the next line

name: pipito otso
address: manila philippines
age: 18

i want to input like that one

but it appear like this one

name: pipito otso
address:
age: ------<<<<<the cursor was in this area...but i want to put data in
address:

what are the commands or the best way in order to make it

pls help me experts....

pipito....
 
T

Tom St Denis

pipito said:
Hi...i am a beginner in C programming...
my question is like this...
im using the scanf in C to accept input data in output area,

printf("name: ");scanf("%s",name);

You need to add a "\n" or the printf won't always show. The stream is
only guaranteed to flush if you send a newline.

Also your scanf doesn't eat the newline [that the user enters]. So
when you get to the second scanf() you get just the newline.

You need to flush the input stream [hint: don't use fflush on it].

You may also want to try and use fgets() instead of scanf [hint:
buffer overflows].

And don't spell things with TXT'ing grammar. It's annoying and makes
you look like a small retarded child who should be wearing a helmet.

Tom
 
P

pemo

Tom said:
pipito said:
Hi...i am a beginner in C programming...
my question is like this...
im using the scanf in C to accept input data in output area,

printf("name: ");scanf("%s",name);

You need to add a "\n" or the printf won't always show. The stream is
only guaranteed to flush if you send a newline.

Also your scanf doesn't eat the newline [that the user enters]. So
when you get to the second scanf() you get just the newline.

You need to flush the input stream [hint: don't use fflush on it].

You may also want to try and use fgets() instead of scanf [hint:
buffer overflows].

And don't spell things with TXT'ing grammar. It's annoying and makes
you look like a small retarded child who should be wearing a helmet.

What, the OP used 'plse' - I think we ought to cut him some slack and save
the 'panning' for those that *really* use /baby speak/.
 
B

Barry Schwarz

Hi...i am a beginner in C programming...
my question is like this...
im using the scanf in C to accept input data in output area,

printf("name: ");scanf("%s",name);
printf(Address: ");scanf("%s",address);
printf("age: ");scanf("%d",age);

when i run the program, i use a spacebar in the input data, the
following string after i press the space bar doesnt read anymore or it
skip and going to the next line

name: pipito otso

The %s in your call to scanf stops at the first white space (in this
case, the space between pipito and otso). However, the extra text
(otso) remains in the buffer.

Your next call to scanf will read the otso into address and stop at
the '\n' which resulted from the enter key

Your third call (the %d) will ignore the '\n', realize the buffer is
empty, and wait for your input, which is now out of step with what you
intended.
address: manila philippines
age: 18

i want to input like that one

but it appear like this one

name: pipito otso
address:
age: ------<<<<<the cursor was in this area...but i want to put data in
address:

what are the commands or the best way in order to make it

You should not use scanf with a %s in general (it can lead to buffer
overflows) and you cannot use it if you want your input to contain
spaces. I suggest you check the fgets function in your reference
material. It solves both the overflow and space problems.


Remove del for email
 
L

lovecreatesbeauty

Tom said:
You need to add a "\n" or the printf won't always show. The stream is
only guaranteed to flush if you send a newline.

Also your scanf doesn't eat the newline [that the user enters]. So
when you get to the second scanf() you get just the newline.

At the second time, every input function will be fed with the newline
left by the previous scanf.
You need to flush the input stream [hint: don't use fflush on it].

You may also want to try and use fgets() instead of scanf [hint:
buffer overflows].

What you said are really good points. Someone, e.g. Keith Thompson,
recommended to use scanf for numbers. Do you agree?

I write a trivial program, it maybe have many flaws. Could you comment
on it..

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

enum gender_e{
male, /*0 for male*/
female /*1 for female*/
};

struct student{
char *name;
enum gender_e gender;
int age;
char *address;
};

void disc(void);
void delnl(char *s);

#define STRLEN 200

int main(void){
struct student s1;
int gender = 0;

s1.name = malloc(STRLEN * sizeof *s1.name);
s1.address = malloc(STRLEN * sizeof *s1.address);

printf("Student Name: ");
fgets(s1.name, STRLEN, stdin);
delnl(s1.name);
printf("Gender (0 for male; 1 for female): ");
scanf("%d", &gender);
s1.gender = (enum gender_e)gender;
disc();
printf("Age: ");
scanf("%d", &s1.age);
disc();
printf("Address: ");
fgets(s1.address, STRLEN, stdin);
delnl(s1.address);
printf("\n---\nstudent: %s, %s, %d, %s\n---\n",
s1.name, s1.gender?"male":"female", s1.age, s1.address);
free(s1.name);
free(s1.address);

return 0;
}

/*discard characters i.e. newline in stdin left by scanf*/
void disc(void){
int c;
while ((c = getchar()) != '\n' && c != EOF)
;
}

/*delete the newline read into memory by fgets*/
void delnl(char *s){
char *p;
if(p = strrchr(s, '\n'))
*p = '\0';
}

$ cc -ansi -pedantic -Wall -W inputoutput.c
inputoutput.c: In function `delnl':
inputoutput.c:60: warning: suggest parentheses around assignment used
as truth value
$ ./a.out
Student Name: dennis
Gender (0 for male; 1 for female): 1
Age: 30
Address: bell
 
L

lovecreatesbeauty

lovecreatesbeauty said:
printf("\n---\nstudent: %s, %s, %d, %s\n---\n",
s1.name, s1.gender?"male":"female", s1.age, s1.address);

sorry, this should be:
s1.name, s1.gender?"female":"male", s1.age, s1.address);

it might correct the errors in output.
$ ./a.out
Student Name: dennis
Gender (0 for male; 1 for female): 1

Gender (0 for male; 1 for female): 0
 
S

sarathy

pipito said:
Hi...i am a beginner in C programming...
my question is like this...
im using the scanf in C to accept input data in output area,

printf("name: ");scanf("%s",name);
printf(Address: ");scanf("%s",address);
printf("age: ");scanf("%d",age);

when i run the program, i use a spacebar in the input data, the
following string after i press the space bar doesnt read anymore or it
skip and going to the next line

name: pipito otso
address: manila philippines
age: 18

use
scanf ("%[^\n]",name);
scanf ("%[^\n]",address);

Now your name and address can contain any number of spaces..
 
S

Simon Biber

sarathy said:
use
scanf ("%[^\n]",name);
scanf ("%[^\n]",address);

Now your name and address can contain any number of spaces..

%[^\n] is good advice, but you should also include a number to limit the
number of characters it will attempt to read and put in the array.

Otherwise if the user inputs a line that is too long, it will overflow
the array and cause undefined behaviour - something bad might happen.

For example:

char name[128];
scanf("%127[^\n]", name);

Note how the number is one less than the size of the array, to allow for
the null character to be stored.
 
S

Simon Biber

Bad idea. The %s has no limit to how many characters it will attempt to
read and place in the name array. It might overflow the array. This kind
of bug is the cause of most of the security issues in programs around
the world. It's important to be vigilant and always consider buffer
overflow, no matter how simple or trivial the program is.

If age has type int, then you are right, you need the ampersand to give
the address of age, so that scanf can store into your age variable.

NO!!! NEVER USE gets!!!

Didn't I just tell you above, how important it is to consider buffer
overflows? The gets function is bad, evil and wrong. It is unsafe, and
it cannot be made safe. Do you see why?

One alternative is to use fgets:

fgets(name, sizeof name, stdin);
char *p = strchr(name, '\n');
if(p != NULL) *p = 0;

The two extra lines are to find and remove the newline character from
the end of the string, since fgets doesn't do that for you.

A man of your age should know better than to use juvenile abbreviations
like ‘u’ when talking to adults.

--
Simon.

(for fun, ...)
Name :- Simon Biber
Address :- Sydney Australia
Age :- 23
 
K

Keith Thompson

lovecreatesbeauty said:
Tom said:
You need to add a "\n" or the printf won't always show. The stream is
only guaranteed to flush if you send a newline.

Also your scanf doesn't eat the newline [that the user enters]. So
when you get to the second scanf() you get just the newline.

At the second time, every input function will be fed with the newline
left by the previous scanf.
You need to flush the input stream [hint: don't use fflush on it].

You may also want to try and use fgets() instead of scanf [hint:
buffer overflows].

What you said are really good points. Someone, e.g. Keith Thompson,
recommended to use scanf for numbers. Do you agree?

Perhaps you have me confused with someone else.

Sure, you can use scanf for numbers. Doing so doesn't present the
same overflow possibilities as an unbounded scanf("%s"). But I
usually recommend using fgets() to read a line at a time, then
sscanf() to parse the line once it's been read. (fgets() has its
problems, but they're easier to work around than scanf()'s problems.)
 
K

Keith Thompson

Tom St Denis said:
You need to add a "\n" or the printf won't always show. The stream is
only guaranteed to flush if you send a newline.
[...]

Another approach is to use fflush:

printf("name: ");
fflush(stdout);
fgets(name, sizeof name, stdin);

This isn't absolutely guaranteed to work, but it should work on any
system where this kind of interactive prompting makes sense.
 
M

Michael Wojcik

Sure, you can use scanf for numbers. Doing so doesn't present the
same overflow possibilities as an unbounded scanf("%s").

But it does present the opportunity for UB (per C99 7.19.6.2 #10).

And while this UB is in practice somewhat less frequently an
exploitable defect than character buffer overflows, it often enough
*is* exploitable. (Integer overflow exploits are well-understood
and amply documented.)

Unfortunately, unless an implementation makes stronger guarantees for
the formatted-input functions than are required by the Standard,
they're all unsafe. For nontrivial applications it's better to
gather text with a safe function and parse it using strtol, etc.

fscanf is hardly a high-performance function; it's a pity the
committee didn't elect to err on the side of safety, and require at
least unspecified but safe behavior for numeric conversions.
 
K

Keith Thompson

But it does present the opportunity for UB (per C99 7.19.6.2 #10).

Oof, I hadn't realized that.

For those without a copy of the standard handy:

[...]
If this object does not have an appropriate type, or if the result
of the conversion cannot be represented in the object, the
behavior is undefined.

For example this:

int i;
sscanf("9999999999999999999999999999", "%d", &i);

invokes undefined behavior (assuming 9999999999999999999999999999
overflows type int).

Ick.
 
L

lovecreatesbeauty

Keith said:
Perhaps you have me confused with someone else.

Sure, you can use scanf for numbers. Doing so doesn't present the
same overflow possibilities as an unbounded scanf("%s"). But I
usually recommend using fgets() to read a line at a time, then
sscanf() to parse the line once it's been read. (fgets() has its
problems, but they're easier to work around than scanf()'s problems.)

Oh, did I? Sorry if I did.

Your next post shows that even sscanf is not safe. Does that `undefined
behavior' (caused by *scanf) mean the control flow won't reach line 9
in the following code?

#include <stdio.h>

int main(void){
int age = 0, c;
while (age < 1 || age > 200){
printf("Your age (1 ~ 200): ");
fflush(stdout);
scanf("%d", &age);
while ((c = getchar()) != '\n' && c != EOF) ; /*line 9*/
}
printf("Sdudent: dennis, age: %d, address: bell\n", age);
}

$ cc -std=c99 -Wall -W ioexercise.c
$ ./a.out
Your age (1 ~ 200): HOWOLDAREYOU?
Your age (1 ~ 200): 999999999999999999999999999999999999999999999999
Your age (1 ~ 200): 29
Sdudent: dennis, age: 29, address: bell
$
 
K

Keith Thompson

lovecreatesbeauty said:
Oh, did I? Sorry if I did.
S'awright.

Your next post shows that even sscanf is not safe. Does that `undefined
behavior' (caused by *scanf) mean the control flow won't reach line 9
in the following code?
[snip]

Um, undefined behavior means the behavior is undefined.
 
A

av

Oh, did I? Sorry if I did.

Your next post shows that even sscanf is not safe. Does that `undefined
behavior' (caused by *scanf) mean the control flow won't reach line 9
in the following code?

#include <stdio.h>

int main(void){
int age = 0, c;
while (age < 1 || age > 200){
printf("Your age (1 ~ 200): ");
fflush(stdout);
scanf("%d", &age);
while ((c = getchar()) != '\n' && c != EOF) ; /*line 9*/
}
printf("Sdudent: dennis, age: %d, address: bell\n", age);
}

$ cc -std=c99 -Wall -W ioexercise.c
$ ./a.out
Your age (1 ~ 200): HOWOLDAREYOU?
Your age (1 ~ 200): 999999999999999999999999999999999999999999999999

my little function for get integers unsigned like above return UNS_MAX
set a flag for overflow and read the number until the last "9"
save the char after 9 ungetc it
 
M

Michael Wojcik

Your next post shows that even sscanf is not safe. Does that `undefined
behavior' (caused by *scanf) mean the control flow won't reach line 9
in the following code?

It's *undefined*, which means it says nothing about the behavior after
that point.

It could cause Scott Nudds to come flying out a demon's nose and
reformat the hard drive of your AS/400.[1]

scanf could refuse to convert the input data at that point in the
stream and return a value indicating it had only performed the
specified conversions up to that point in the format string. (Note
that scanf returns the number of conversions it successfully
performed.)

Or it could do anything else. Since the behavior is undefined, it's
purely a matter of Quality of Implementation (QoI).

IMO, the highest-quality result would be for scanf to refuse to
convert and to return the proper return code at that point.

However, a naive implementation could perform, say, %d conversions by
reading characters into a buffer until it reached a character that
wasn't part of a valid sequence for a %d conversion; and it could use
a fixed-sized buffer for that purpose; and it could overflow that
buffer if too many digits were supplied. That would be lousy QoI,
but it wouldn't violate the standard.

A good implementor wouldn't commit such an obvious error, but there
are implementors who aren't all that good, and even the best
implementors make mistakes once in a while.[2]

Now, for practical C programming, you have to assume a certain QoI
for the implementation(s) you will use; and most C programmers will
also limit themselves to implementations that they know will adhere
to certain behaviors not required by the standard. So it is often
acceptable to say "this C program requires that, in addition to the
requirements of the standard, the implementation behave reasonably
when performing conversions of numeric data using the scanf family".

Generally speaking, vendors who care about conformance to the
standard also care about QoI; or to put it another way, if a vendor
refuses to produce a quality implementation, I'd be suspicious of
their conformance to the standard anyway.

Just be aware that if you disregard the possibility of adverse
behavior from scanf's numeric conversions, you are imposing
additional restrictions on the implementations you use. Many of
us do that every day, as professional C programmers, because
perfect vigilance is too expensive; but it is a trade-off.


[1] I think that covers all the standard c.l.c metaphors.

[2] I'll bet that even Chris Torek and P. J. Plauger have made at
least one mistake each.

--
Michael Wojcik (e-mail address removed)

Thanatos, thanatos! The labourer, dropping his lever,
Hides a black letter close to his heart and goes,
Thanatos, thanatos, home for the day and for ever. -- George Barker
 
D

Dave Thompson

It's *undefined*, which means it says nothing about the behavior after
that point.
However, a naive implementation could perform, say, %d conversions by
reading characters into a buffer until it reached a character that
wasn't part of a valid sequence for a %d conversion; and it could use
a fixed-sized buffer for that purpose; and it could overflow that
buffer if too many digits were supplied. That would be lousy QoI,
but it wouldn't violate the standard.
It would if it failed for e.g. -0000000000000000000000000000012345 .
The UB is allowed only for (converted) value out of range.

You _could_ correctly parse (or buffer?) whitespace, sign, and leading
zeros and then inadequately buffer other digits -- but IMNVHO that
goes beyond naive into just silly. Or perverse, of course.
A good implementor wouldn't commit such an obvious error, but there
are implementors who aren't all that good, and even the best
implementors make mistakes once in a while.[2]

Now, for practical C programming, you have to assume a certain QoI
for the implementation(s) you will use; <snip>
Generally speaking, vendors who care about conformance to the
standard also care about QoI; or to put it another way, if a vendor
refuses to produce a quality implementation, I'd be suspicious of
their conformance to the standard anyway.
And even if it somehow does conform I wouldn't want to use it.
Just be aware that if you disregard the possibility of adverse
behavior from scanf's numeric conversions, you are imposing
additional restrictions on the implementations you use. Many of
us do that every day, as professional C programmers, because
perfect vigilance is too expensive; but it is a trade-off.
Realistically, you can easily write conversion code that traps or
returns garbage for overflow on some machines. I can, just barely,
imagine a very limited machine, about the 8080 or 6502 or PDP-8 level,
where multiplication must be done 'by hand' and the (most) available
primitive for multiplication (by 10?) cleverly(?) handles both word
and more-than-word (for some choice of word) in such a way that
unexpected and unallowed-for overflow clobbers something vital.
[2] I'll bet that even Chris Torek and P. J. Plauger have made at
least one mistake each.

What, you don't think they'd be willing to share? <G>

- David.Thompson1 at worldnet.att.net
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,776
Messages
2,569,602
Members
45,184
Latest member
ZNOChrista

Latest Threads

Top