Strcpy versus Strncpy in arrays

P

pete

Mark said:
On Tue, 15 Nov 2005 12:23:12 GMT, in comp.lang.c , pete

This is after the typographical location of the statement "++i"


Luckily I do,

No you don't.
You're talking about the value of expr-3 in a for loop.
 
O

Old Wolf

Mark said:
Because that reads
"for i equals zero to ten, and do some stuff and increment i
afterwards. "

And what about: for (i = 0; i < 10; i += 2)
"for i equals zero to ten, do some stuff, and add 2 to i at
the same time" ?

If anyone does read it that way, then they have a serious
mis-understanding of for loops, and it would be best to
immediately correct them. One way of doing this is to
expose them to pre-increment and post-increment, and have
them observe that they both work the same way.

It would also be good to break them of the idea that "i++"
has anything to do with "afterwards", because it doesn't.
 
K

Keith Thompson

pete said:
In a for statement, expr-3 is evaluated as a void exprssion.

It is evaluated for side effects only and
the value of expr-3 is never used.

(++i) and (i++) have the same side effect.
There is no difference between using either form,
as expr-3 in a for statement.

I think Mark knows that; he's just asserting that one form is less
intuitive than the other. I disagree, but since it's a matter of
perception there's not a whole lot of point in arguing about it.

I suggest that anyone who's seriously confused by
for (i = 0; i < 10; ++i) { ... }
isn't really going to understand
for (i = 0; i < 10; i++) { ... }
either. Anyone who thinks there's a real difference between them
should clear up that misconception before worrying about which one is
clearer.

C code should be written clearly, but it shouldn't cater to readers
who don't know the language.

In a similar vein, I know perfectly well that (x==42) and (42==x) are
semantically equivalent, but I still have a strong stylistic
preference for the former. If I wrongly thought there was a semantic
difference, my opinion that one is clearer than the other would be
worth very little. (I present this as an example; I'm not trying to
resurrect that argument.)
 
P

Paul Hsieh

SK said:
for (n = 0; n < EMPLOYEES; ++n){
do{
printf("\nEnter employee # %d: ", count_EMP);

You have not ended this printf output with a "\n". Thus, its content
might not be output on some systems until the next occurrence of a \n
which happens in your next printf.
scanf("%s %s", &fn, &ln);

This is a "buffer overflow". It means that a user can input data
sufficient to cause a write memory beyond the bounds which you've
declared -- this has undefined behavior in the C language.

The standard half assed solution here is to do a fgets() to just read
the raw line, then an sscanf() to parse out the parameters. However,
that suffers the (lesser) problem of buffer truncation. If you are
intent on using the primitive C library, then I would recommend you look
at my article on user input here:

http://www.pobox.com/~qed/userInput.html

You can just use the getf.zip sources directly and then use
getstralloc() macro to fetch the user input correctly, then use sscanf
(after possibly using malloc to allocate space for your inputs).

But if you find all this just a little too painful, you can instead use
"The Better String Library" (http://bstring.sf.net/). You would just do
a bgets(), then a bsplit() to get all the names from the input.
printf("\nPlease enter the hourly wage for the employee: ");
scanf("%f", &wage);

printf("\nPlease enter the number of hours worked this"
" week: ");
scanf("%f", &hours);

Those, of course, are *not* buffer overflows because of the naturally
compressing nature of these modes of usage of scanf.
printf("\nThank you. Process another employee?");
scanf("%s", &again);

You only want to read one character here. So first of all you are
buffer overflowing again, but you are also probably using the wrong
scanf mode. You mean "%c" here, not "%s".
}while(again == 'Y' || again == 'y');

Wait -- you've written a loop here, but you are not storing your data
into incremental storage of any kind. You need to move this do { ... }
while() to the outer loop.
/*Read in the input*/

numemp = scanf("%11s%11s%f%f%f%f%f", &fn, &ln, &RegHr,
&wage, &OTHr, &OTHrPay, &GrossPay);

So is this redundant, or what are you trying to do here? In any event,
this has the buffer truncation problem. If you enter a name with more
than 11 characters, then the spill over characters will just bleed into
the successive parameters.
/*Check if user is done*/

if(again != 'Y' && again !='y');
printf("End of processing\n\n\n");


/*Process the input*/
if(numemp == 6)
{

if (RegHr > 40)
{
OTHr = hours - 40;
OTHrPay = OT * OTHr * wage;

Ok, here you are overwriting OTHr and OTHrPay with these computations,
after you were trying to read them as input. So you are essentially
just losing your input. So perhaps your second scanf is completely
superfluous and should just be removed. (You still need to move the do
{ ... } while to the outer loop.)
RegHrPay = 40.0 * wage;
}

else
{
RegHrPay = hours * wage;
OTHrPay = 0.0;

}

GrossPay = RegHrPay + OTHrPay;

strncpy(emp[n].first_name, fn, FULLNAME);

strncpy has a well known design flaw, where a maximal truncation doesn't
add a '\0' on the end. In general, I would avoid strncpy() in all
cases. There is another extension out there called "strlcpy" which does
not suffer this problem, but still leaves you with the buffer truncation
weakness.

"The Better String Library" makes this whole thing a non-issue. You
would just use bstrcpy(), and there would not be any truncation or
overflow issues.
emp[n].first_name[FULLNAME] = '\0';

This is a bounds overrun error. An array declared of length n can be
legally indexed from 0 to n-1 inclusive. So FULLNAME is 1 more than the
limit you can index with for this declared array. That said, it will
likely function, but end up setting a '\0' into the first character of
the next element (in this case .last_name, thus causing people's last
names to be empty).
 
M

Mark McIntyre

No you don't.

I know what I'm trying to say, and, frankly, its stupid to say that
don't. The only thing you can say for certain is that you don't or
won't understand me. Thats my fault, I'm obviously not explaining
clearly enough.
You're talking about the value of expr-3 in a for loop.

No.
 
M

Mark McIntyre

In a for statement, expr-3 is evaluated as a void exprssion.

You're making my point. To those who know the rules of baseball, the
rules of baseball are obvious.
 
P

pete

I think Mark knows that;

It looks to me like he's talking about the significance
of the value of expr-3, and there is no significance.

There is no other difference between (++i) and (i++)
to discuss.
 
J

Jordan Abel

Inside the body of the loop. Are you hard of reading?

No, the new value is used. The increment happens at the end of the
loop, and then the new value is used for the next execution of the
body. At no time after it is incremented is the previous value used.
 
W

websnarf

pete said:
It looks to me like he's talking about the significance
of the value of expr-3, and there is no significance.

There is no other difference between (++i) and (i++)
to discuss.

The real point is that there is so much more of that code worth
analyzing than that. Its a "style before substance" thing that most of
the posters in this thread seem obsessed with and a great demonstration
of "group think".
 
F

Flash Gordon

Jordan said:
No, the new value is used. The increment happens at the end of the
loop, and then the new value is used for the next execution of the
body. At no time after it is incremented is the previous value used.

I believe that Mark is talking about how people might miss-read the
code, not how it actually works. I'm sure Mark knows how it actually works.

Beginner known that i++ returns the value from before the increment.
Therefore beginner reads the third statement as meaning that the old
value of i is used in the body of the loop.
Therefore beginner has got it wrong.

In the above none of us are the beginner because we all know better.
 
J

Jordan Abel

I believe that Mark is talking about how people might miss-read the
code, not how it actually works. I'm sure Mark knows how it actually works.

I read him as claiming that it works this way and that using ++i
obfuscates how it uses the previous value.
Beginner known that i++ returns the value from before the increment.
Therefore beginner reads the third statement as meaning that the old
value of i is used in the body of the loop.
Therefore beginner has got it wrong.

How can this be used to claim that ++i is less clear, when ++i would in
that case lead to the correct conclusion?
 
M

Mark McIntyre

It looks to me like he's talking about the significance
of the value of expr-3,

I'm not talking about any sort of significance.

Seemingly you're unable to discern the difference between perception
and knowledge.

Lets try a simpler example: the ancients thought frogs 'grew' from
mud, because after heavy rain, frogs were to be seen arising from the
puddles. We knowledgable people know this to be false, but we can
perhaps see why a people with less knowledge might be misled.
 
M

Mark McIntyre

I believe that Mark is talking about how people might miss-read the
code, not how it actually works. I'm sure Mark knows how it actually works.

At last. Somebody who is actually bothering to think ,as opposed to
merely restate segments of the Standard.
In the above none of us are the beginner because we all know better.

Precisely.
 
K

Keith Thompson

Mark McIntyre said:
I'm not talking about any sort of significance.

Seemingly you're unable to discern the difference between perception
and knowledge.

Lets try a simpler example: the ancients thought frogs 'grew' from
mud, because after heavy rain, frogs were to be seen arising from the
puddles. We knowledgable people know this to be false, but we can
perhaps see why a people with less knowledge might be misled.

Ok, but we don't carefully remove frogs from mud to avoid confusing
any ancients who might see them.
 
K

Keith Thompson

Mark McIntyre said:
At last. Somebody who is actually bothering to think ,as opposed to
merely restate segments of the Standard.


Precisely.

Mark, please don't assume that we're all idiots because we
misunderstand or disagree with what you're saying.

So, given these two lines of code:

for (i = 0; i < 10; i++) { ... }
for (i = 0; i < 10; ++i) { ... }

we're all in agreement that they're semantically identical (because
expr-3, either "i++ or "++i", is evaluated only for its side effects,
with the result being discarded).

The point on which we disagree is your claim that one form is more
intuitive than the other. I think a lot of people have misconstrued
what you've said because, frankly, it doesn't seem to us to make a
whole lot of sense.

The most likely explanation for thinking that i++ is better than ++i
in this context would be a mistaken belief that there's a semantic
difference. I understand that you do understand the semantics, and
that that's not the reason for your preference, but you haven't been
very quick to state this explicitly.

If you happen to have a personal preference here, that's fine. In
this particular case, though, you need to be aware that not only will
most others not share your preference, most of us won't even
understand the basis for it, and it's not because we're not bothering
to think.
 
J

Jordan Abel

Mark, please don't assume that we're all idiots because we
misunderstand or disagree with what you're saying.

So, given these two lines of code:

for (i = 0; i < 10; i++) { ... }
for (i = 0; i < 10; ++i) { ... }

we're all in agreement that they're semantically identical (because
expr-3, either "i++ or "++i", is evaluated only for its side effects,
with the result being discarded).

The point on which we disagree is your claim that one form is more
intuitive than the other. I think a lot of people have misconstrued
what you've said because, frankly, it doesn't seem to us to make a
whole lot of sense.

The most likely explanation for thinking that i++ is better than ++i
in this context would be a mistaken belief that there's a semantic
difference. I understand that you do understand the semantics, and
that that's not the reason for your preference, but you haven't been
very quick to state this explicitly.

If you happen to have a personal preference here, that's fine. In
this particular case, though, you need to be aware that not only will
most others not share your preference, most of us won't even
understand the basis for it, and it's not because we're not bothering
to think.

I think that it fundamentally comes down to it being what he learned
first. It's convention, plain and simple. I'll usually use i++ instead
of ++i too, because it's what I learned.
 
P

pete

Jordan Abel wrote:
I think that it fundamentally comes down to it being what he learned
first. It's convention, plain and simple. I'll usually use i++ instead
of ++i too, because it's what I learned.

I actually switched my preference from i++ to ++i,
for expressions evaluated as void.

I consider the standard description of postfix increment
to be more complicated, than that of prefix increment.
Not much more complicated, just a little.

The point being, that I would need some reason
to use the conceptually more complicated increment.
A void expression evaluation provides no such reason.

When I see a postincremented void evaluted expression
in somebody else's code, I tend not to comment on it.
If I rewrite somebody else's posted code and post it,
there's a good chance that
I'll change postincrented void evaluated expressions
to preincremented, because then it's my code.

My preference may also be influenced by K&R writing one way
and Schildt writing the other.

I originally learned C by Schildt,
in three weeks!!!
and again over the course of years
in an ongoing process here on clc.
 
K

Keith Thompson

pete said:
I actually switched my preference from i++ to ++i,
for expressions evaluated as void.

I consider the standard description of postfix increment
to be more complicated, than that of prefix increment.
Not much more complicated, just a little.

The point being, that I would need some reason
to use the conceptually more complicated increment.
A void expression evaluation provides no such reason.

Fair enough.

Personally, I don't even think about the distinction between i++ and
++i if it appears in a void context, and I really have no preference
one way or the other. If the result is used, I have to stop and think
about what's going on, but I actually think both forms are used more
often in void context than otherwise.
 
M

Mark McIntyre

Mark, please don't assume that we're all idiots because we
misunderstand or disagree with what you're saying.

I don't. I have however been forced to the conclusion that several of
you are suffering from a bad case of "the other guy must be an idiot
because he doesn't understand the simple rules of
reverse-polish-flombat swarfling with the added bermudan option, but
disallowing cue bidding"
The point on which we disagree is your claim that one form is more
intuitive than the other. I think a lot of people have misconstrued
what you've said because, frankly, it doesn't seem to us to make a
whole lot of sense.

See above.
 
M

Mark McIntyre

I think that it fundamentally comes down to it being what he learned
first.

I learned both at the same time.

As it happens, I generally use ++var when I want to preincrement a
variable, and var++ when I want to postincrement it.
 

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

Similar Threads

Help with a C program 27
Help with a simple c program 8
Working with the for loop 2
Change of program 1
Pointers 16
scanf for char input getting skipped 0
scanf for char input getting skipped 9
Newbie with an error 6

Members online

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,057
Latest member
KetoBeezACVGummies

Latest Threads

Top