a newbie question.

M

Mike

Hi

#include<stdio.h>
main()
{
char s[]="Taiwan University.";
float a;
scanf("%f",&a);
printf("%f",a);
printf("input string:");
gets(s);
puts("%s",s);
}

After compiled by Visual Studio, the above program can input a.
But after it shows a, then I cannot enter s string.
Why?

Mike
 
D

DDD

Hi

#include<stdio.h>
main()
{
char s[]="Taiwan University.";
float a;
scanf("%f",&a);
printf("%f",a);
printf("input string:");
gets(s);
puts("%s",s);

}

After compiled by Visual Studio, the above program can input a.
But after it shows a, then I cannot enter s string.
Why?

Mike

The routine scanf will stop when met Enter key, then gets() get the
Enter key.
 
M

Micah Cowan

Mike said:
After compiled by Visual Studio, the above program can input a.
But after it shows a, then I cannot enter s string.

Maybe yes, maybe no. The way you've written your code, you might never
be able to tell.
#include<stdio.h>
main()

int main(void)

would be significantly better.
{
char s[]="Taiwan University.";

Why fill s[] with a value just to overwrite it?
float a;
scanf("%f",&a);
printf("%f",a);

If scanf() encounters a conversion error (say you enter "a" instead of
a float value), a will still be uninitialized when you print it, in
which case anything could happen.
printf("input string:");

If stdout is line-bufered, you won't see this prompt before it starts
expecting input.
gets(s);
puts("%s",s);

Since gets() strips newlines, puts() won't print one, so you may not
see this output either.

Aside from that, gets() is unsafe.

Aside from reading further into your C book, you might take a peek at
the comp.lang.c FAQ http://c-faq.com/ for better understanding of
what's wrong with your code.
 
K

Keith Thompson

Mike said:
#include<stdio.h>
main()
{
char s[]="Taiwan University.";
float a;
scanf("%f",&a);
printf("%f",a);
printf("input string:");
gets(s);
puts("%s",s);
}

After compiled by Visual Studio, the above program can input a.
But after it shows a, then I cannot enter s string.
Why?

The comp.lang.c FAQ is at <http://www.c-faq.com/>. You've just asked
question 12.18a.

Some more points:

"main()" is more or less ok in some circumstances, but
"int main(void)" is better.

You should probably print a new-line after each item that you print.
For example,
printf("%f\n", a);
Otherwise your output will be illegibly joined together on a single
line.

Never use the gets() function. See question 12.23 in the
aforementioned FAQ.

The puts() function takes one argument, not two. Since you have the
required "#include <stdio.h>" (good for you), the compiler should have
caught this error. In other words, it's very likely that the code you
posted is not the same as your actual code. Always copy-and-paste the
*exact* code you're having trouble with; don't paraphrase it, and
don't try to re-type it. Recommended reading:
<http://www.catb.org/~esr/faqs/smart-questions.html>.

It's a good idea to add a "return 0;" at the end of the main function.
 
U

user923005

Hi

#include<stdio.h>
main()
{
  char s[]="Taiwan University.";
  float a;
  scanf("%f",&a);
  printf("%f",a);
  printf("input string:");
  gets(s);
  puts("%s",s);

}

After compiled by Visual Studio, the above program can input a.
But after it shows a, then I cannot enter s string.
Why?

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

char *getsafe(char *buffer, int count)
{
char *result = buffer,
*np;
if ((buffer == NULL) || (count < 1))
result = NULL;
else if (count == 1)
*result = '\0';
else if ((result = fgets(buffer, count, stdin)) != NULL)
if (np = strchr(buffer, '\n'))
*np = '\0';
return result;
}

int main(void)
{
char s[256] = "Taiwan University.";
int converted;
float a;
puts("Enter a floating point number:");
if (getsafe(s, sizeof s)) {
converted = sscanf(s, "%f", &a);
if (converted == 1)
printf("%f\n", a);
else
puts("Failed to collect a float from standard input.");
puts("input string:");
if (getsafe(s, sizeof s))
puts(s);
else
puts("Failed to collect a string from standard input.");
} else {
puts("Failed to collect a floating point input from standard
input.");
}
return 0;
}
 
F

Falcon Kirtaran

Mike said:
Hi

#include<stdio.h>
main()
{
char s[]="Taiwan University.";
float a;
scanf("%f",&a);
printf("%f",a);
printf("input string:");
gets(s);
puts("%s",s);
}

After compiled by Visual Studio, the above program can input a.
But after it shows a, then I cannot enter s string.
Why?

Mike

Just to add to the other posts, your string literal "Taiwan University."
is of type const char *. You should not assign anything to it, because
it might be stored in a place in memory to which your program cannot
write, at which point it will crash (this idea can be summarized easily:
never cast away the constness of string literals). Have a look at
malloc() and free() instead, or just declare an array of char, eg. char
s[81].

If you're feeling a bit overwhelmed with all these replies, being a
newbie, note that strings are much more complicated than other variables
in C.
 
B

Ben Bacarisse

Falcon Kirtaran said:
Mike said:
#include<stdio.h>
main()
{
char s[]="Taiwan University.";
Just to add to the other posts, your string literal "Taiwan
University." is of type const char *.

Not in C. The elements have type char and are read-only but the
standard stops just short of saying that they have type "const char".
You should not assign anything
to it,

It is just as well, then, that the OP does not do that! 'char s[] =
"...";' is not the same as 'char *s = "...";' -- I am sure this is
covered in the FAQ.

To the OP: apart from using gets (never do that) it is perfectly OK
to change the contents of your array 's'. The string literal is used
only to initialise it, after that, you can change it as much as you
want.

Had you written 'char *s = "something";' then you can not change the
data pointed to by 's' -- the arrays created by string literals are
read-only and any attempt to change them is undefined (i.e. bad things
could happen).
because it might be stored in a place in memory to which your
program cannot write, at which point it will crash (this idea can be
summarized easily: never cast away the constness of string
literals).

I think a less confusing rule (for C) is that one should treat string
literals as if there were const.
 
R

Richard Bos

Falcon Kirtaran said:
Just to add to the other posts, your string literal "Taiwan University."
is of type const char *.

No, it's not. It's of type char * (not const), but the text is not
(reliably) writable. This is illogical, but it's for hysterical raisins.

Richard
 
K

Keith Thompson

Mike said:
#include<stdio.h>
main()
{
char s[]="Taiwan University."; [...]
}
[...]

At least one person has remarked on the fact that the code set the
array s to the value "Taiwan University." and then overwrites it.

In fact, given the empty square brackets, the initializer does two
things: it determines the initial value of s and it determines its
size (19 bytes in this case). Copying the string "Taiwan University."
into s is a bit wasteful, but it's a fairly concise way to say that
you want s to be big enough to hold that particular string value.

An alternate way to do the same thing is:

char s[sizeof "Taiwan University." + 1];

but it's easy to forget the "+ 1" (needed to allow for the terminating
'\0').

I'm resisting the temptation to propose adding a new feature to the
language so you can write:
char s[] != "Taiwan University."; /* :cool:} */
to set the size without initializing the array.

(Of course, 19 bytes isn't big enough to make the program immune to
buffer overruns, but we've covered that.)
 
R

Ralf Damaschke

Keith said:
char s[]="Taiwan University.";
it's a fairly concise way to say that
you want s to be big enough to hold that particular string value.

An alternate way to do the same thing is:

char s[sizeof "Taiwan University." + 1];

but it's easy to forget the "+ 1" (needed to allow for the
terminating '\0').

Oops, it seems as easy to confuse sizeof with strlen, too.

Ralf
 
J

John Bode

Hi

#include<stdio.h>
main()
{
char s[]="Taiwan University.";
float a;
scanf("%f",&a);
printf("%f",a);
printf("input string:");
gets(s);
puts("%s",s);

}

After compiled by Visual Studio, the above program can input a.
But after it shows a, then I cannot enter s string.
Why?

Mike

When you type in your floating point number (3.14159, for example) and
hit Enter, the input stream looks like this:

{'3','.','1','4','1','5','9',\n}

After the call to scanf(), the newline character is still left in the
input stream:

{\n}

because scanf() with the %f conversion specifier stops reading at the
first character that isn't part of a valid floating-point constant.

gets() reads up to the next newline character; since there's already a
newline character in the input stream left over from the last input
operation, it returns immediately.

There are two ways around this. The easy way is to stick a getchar()
after the scanf() to consume the newline. A somewhat more involved
(but ultimately safer) way is to read your floating-point number in as
a string using fgets() (*NOT* gets()), and then convert using sscanf()
or strtod().

Do not use gets(); it *WILL* introduce a point of failure in your
code. Use fgets() instead:

fgets(s, sizeof s, stdin);

Unlike gets(), fgets() writes the trailing newline to your buffer.
 
K

Keith Thompson

Ralf Damaschke said:
Keith said:
Mike said:
char s[]="Taiwan University.";
it's a fairly concise way to say that
you want s to be big enough to hold that particular string value.

An alternate way to do the same thing is:

char s[sizeof "Taiwan University." + 1];

but it's easy to forget the "+ 1" (needed to allow for the
terminating '\0').

Oops, it seems as easy to confuse sizeof with strlen, too.

Absolutely; good catch. (sizeof "string literal" already includes the
trailing '\0'; the +1 is unnecessary.)

(As it happens, I realized I had made this error as I was driving to
work this morning; I haven't had a chance to post until now.)
 
D

David Thompson

Mike <[email protected]> writes:

If stdout is line-bufered, you won't see this prompt before it starts
expecting input.
Actually, you probably will; see 7.19.3p3 about "input is requested".
(Barring the UB earlier for an uninit float.) But you _might_ not.
Since gets() strips newlines, puts() won't print one, so you may not
see this output either.
_printf_, which the OP apparently meant, wouldn't add a newline,
but _puts()_ would -- but would be called as puts(s) .
Aside from that, gets() is unsafe.
That too.

- formerly david.thompson1 || achar(64) || 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,774
Messages
2,569,599
Members
45,167
Latest member
SusanaSwan
Top