Input-line reverser

A

Albert

This not-yet-working C program's aim is to output each input line
reversed (so if the user enters 'hello', the program will output
'olleh' - and please assume this stdout and stdin!!!).
Why the h**l isn't this WORKING AND WHY DOES IT CRASH???!

#include <stdio.h>
#define MAXINPUT 256

void reverse(char[], int);

main()
{
int c;
int number;
char s[MAXINPUT];
int i;

for (i=0; (i<MAXINPUT-1) && ((c = getchar()) != '\n'); i++) {
s = c;
++number;
}
reverse(s, number);


for (i=0; i<=number; i++)
putchar(s);
return 0;
}


void reverse(char s[], int num_elements)
{
int i, j;

for (i=0,j=num_elements-1; (i<=num_elements-1) && (j>=0); i++,j--)
s = s[j];
}
 
R

Richard Heathfield

Albert said:
void reverse(char s[], int num_elements)
{
int i, j;

for (i=0,j=num_elements-1; (i<=num_elements-1) && (j>=0); i++,j--)
s = s[j];
}


Desk-check it. That means: get out a piece of paper, and pretend you're a
computer. Write down the values of all objects, each at the head of its own
column. Assuming you have five elements:

Code s[0] s[1] s[2] s[3] s[4] n i j
'h' 'e' 'l' 'l' 'o' 5 ? ?

Put down each code step in the left hand column, and look at the effect the
code has on the values of all the relevant objects. For example:

Code s[0] s[1] s[2] s[3] s[4] n i j
'h' 'e' 'l' 'l' 'o' 5 ? ?
i = 0 'h' 'e' 'l' 'l' 'o' 5 0 ?
j = n-1 'h' 'e' 'l' 'l' 'o' 5 0 4
i <= 4? Yes.
j >= 0? Yes.
s=s[j] 'o' 'e' 'l' 'l' 'o' 5 0 4

and so on. Doing this by hand - "desk-checking" - is an invaluable aid to
understanding what you actually wrote, as opposed to what you thought you
wrote.
 
A

Arthur J. O'Dwyer

Why the h**l isn't this WORKING AND WHY DOES IT CRASH???!

#include <stdio.h>
#define MAXINPUT 256

void reverse(char[], int);

main()

int main(void)
{
int c;
int number;
char s[MAXINPUT];
int i;

for (i=0; (i<MAXINPUT-1) && ((c = getchar()) != '\n'); i++) {

For bonus points, consider what happens if c is EOF.
s = c;
++number;


What is 'number' at this point in the program? Hint: It depends
on what 'number' was at the beginning of the program. Find where you
(failed to) initialized 'number', and you'll have found the main
problem. ...Okay, one of the /two/ main problems.
}
reverse(s, number);


for (i=0; i<=number; i++)
putchar(s);


What is 's[number]'? (For that matter, if you give 'number' a real
name, such as 'length', you'll probably find out why you don't need
it after all.)
return 0;
}


void reverse(char s[], int num_elements)
{
int i, j;

for (i=0,j=num_elements-1; (i<=num_elements-1) && (j>=0); i++,j--)

Once the program no longer crashes, it will be time to examine this
loop's termination condition to find out why it doesn't do anything.
s = s[j];
}



-Arthur
 
R

Richard Heathfield

Albert said:
Could you FIRSTLY tell me why this program crashes?

Sure. It's because the program is not a valid C program. Now, you might
argue that it compiles just fine, and runs just fine except for the
crashing part, and is therefore a valid C program. But you'd be wrong.

The reason it's not a valid C program is that it attempts to modify the
value of an object, when that object hasn't been given a value yet.
Specifically, look at 'number', in main, which you define but to which you
assign no value. Therefore, that object's value is indeterminate.
Nevertheless, you try to use that value (by adding 1 to it), thus invoking
undefined behaviour, just as you would do if you were stupid enough (which,
of course, you never will be) to define main with some return type other
than int. In each case, the C language washes its hands of the program, and
so the results are arbitrary. Crashing is just one of many possibilities.
 
A

Albert

I've 'desk-checked' and I still can't figure out why if I enter 'he' it
outputs 'ee'.
Could you give me another hint?

I've updated the program:

#include <stdio.h>
#define MAXINPUT 256


void reverse(char[], int);


main()
{
int c;
int number = 0;
char s[MAXINPUT];
int i;


for (i=0; (i<MAXINPUT-1) && ((c = getchar()) != '\n') && (c!=EOF);
i++) {
s = c;
++number;
}
reverse(s, number);


for (i=0; i<=number-1; i++)
putchar(s);
return 0;
}


void reverse(char s[], int num_elements)
{
int i, j;

for (i=0,j=num_elements-1; (i<=num_elements-1) && (j>=0); i++,j--)
s = s[j];
}
 
A

Arthur J. O'Dwyer

Could you FIRSTLY tell me why this program crashes?

Yes. You didn't provide any 'main' function.
(Or are you talking about some other program? Why don't you provide
the program in question, or at least some context for your remark?)

If you're using Google Groups to post, *don't*. If you must, then
go Google "Google Groups Usenet" and follow the instructions you find
in re: netiquette.


Note that Richard's reply was better than mine, because /he/ wasn't
not paying enough attention to the 'reverse' function. ;) The second
half of my reply was just plain wrong.

-Arthur
 
R

Richard Heathfield

Albert said:
I've 'desk-checked' and I still can't figure out why if I enter 'he' it
outputs 'ee'.

It's because you tell it to.
Could you give me another hint?

Here are three hints:

You are right to start at both ends and work inward.

You should stop halfway. When i > j, you're done.

You should use a temporary object to store one of the values when swapping.

If you do s = s[j], you lose the original value of s. The idiom you
need is:

tmp = s;
s = s[j];
s[j] = tmp;
 
C

Chris F.A. Johnson

I've 'desk-checked' and I still can't figure out why if I enter 'he' it
outputs 'ee'.
Could you give me another hint? [snip]
void reverse(char s[], int num_elements)
{
int i, j;

for (i=0,j=num_elements-1; (i<=num_elements-1) && (j>=0); i++,j--)
s = s[j];
}


What are the values of s[0] and s[1] after the first iteration of
the loop?
 
M

Mark McIntyre

Could you FIRSTLY tell me why this program crashes?

When you desk-check it, you will discover the answer to that.

Really, Richard is trying to help you by explaining an important
technique in writing computer programmes. Its not all about typing on
keyboards.
Mark McIntyre
 
M

Mark McIntyre

I've 'desk-checked' and I still can't figure out why if I enter 'he' it
outputs 'ee'.

You have s[] = "he";

You set s[0] = s[1]
then you set s[1] = s[0]

what is now in the array?
Could you give me another hint?

You're swapping too much, and you need a temporary.
Mark McIntyre
 
M

Mike Wahler

Richard Heathfield said:
Albert said:


Sure. It's because the program is not a valid C program. Now, you might
argue that it compiles just fine, and runs just fine except for the
crashing part, and is therefore a valid C program. But you'd be wrong.

The reason it's not a valid C program is that it attempts to modify

evaluate, not modify. Modifying (i.e. assigning to it) would be OK.
the
value of an object, when that object hasn't been given a value yet.


-Mike
 
A

August Karlstrom

Albert said:
This not-yet-working C program's aim is to output each input line
reversed (so if the user enters 'hello', the program will output
'olleh' - and please assume this stdout and stdin!!!).
Why the h**l isn't this WORKING AND WHY DOES IT CRASH???!

#include <stdio.h>
#define MAXINPUT 256

void reverse(char[], int);

main()
{
int c;
int number;
char s[MAXINPUT];
int i;

for (i=0; (i<MAXINPUT-1) && ((c = getchar()) != '\n'); i++) {
s = c;
++number;
}
reverse(s, number);


for (i=0; i<=number; i++)
putchar(s);
return 0;
}


void reverse(char s[], int num_elements)
{
int i, j;

for (i=0,j=num_elements-1; (i<=num_elements-1) && (j>=0); i++,j--)
s = s[j];
}


You may also want to consider a much shorter solution using recursion.
It imposes no restrictions on the line length.

#include <stdio.h>

void reverse(void)
{
int c;

c = getchar();
if (c != '\n') {
reverse();
putchar(c);
}
}


int main(void)
{
reverse();
putchar('\n');
return 0;
}


August
 
M

Mark McIntyre

evaluate, not modify. Modifying (i.e. assigning to it) would be OK

Not all modification is assignment. Consider if the modification were
for example ++ or +=.
Mark McIntyre
 
M

Mike Wahler

Mark McIntyre said:
Not all modification is assignment. Consider if the modification were
for example ++ or +=.

Both those operators evaluate their operands.

-Mike
 
M

Mark McIntyre

Both those operators evaluate their operands.

Agreed. My point was that you said, still visible above, that
modifying would be ok since it is the same as assigning. This isn't
correct.
Mark McIntyre
 
R

Richard Heathfield

Mark McIntyre said:
Not all modification is assignment. Consider if the modification were
for example ++ or +=.

The modification in question was in fact ++.
 
R

Richard Heathfield

Mike Wahler said:
Both those operators evaluate their operands.

Indeed, and I did in fact say that "it attempts to modify the
value of an object, when that object hasn't been given a value yet". I'm
still trying to work out what you find objectionable about that.
 
K

Keith Thompson

Richard Heathfield said:
Mike Wahler said:

Indeed, and I did in fact say that "it attempts to modify the
value of an object, when that object hasn't been given a value yet". I'm
still trying to work out what you find objectionable about that.

int i;
i = 42;

The assignment attempts to modify the value of an object, when that
object hasn't been given a value yet.
 

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,744
Messages
2,569,484
Members
44,904
Latest member
HealthyVisionsCBDPrice

Latest Threads

Top