# Thread: Reversing a line at a time !

1. ## Reversing a line at a time !

Well I was solving the K&R problem - Write a function reverse(s) that reverses the character string s . Use it to write a program that reverses its input a line at a time. I got the first part correct but when I tried to modify to accommodate the second part the results aren't as intended. I know I screwed up somewhere in the array index calculation, but can't make it right ! Please help ! Here's my code so far:

Code:
#include <stdio.h>
#define MAXLINE 1000

void getline(char[], int);
int main()
{
char line[MAXLINE];
getline(line, MAXLINE);
printf("%s", line);
return 0;
}
void getline(char s[], int maxlen)
{
int arrayLength, c, temp, i, preLen = 0;
for(arrayLength = 0; arrayLength  < maxlen-1 && (c = getchar()) != EOF; arrayLength++)
{
if(c == '\n')
{
s[arrayLength] = '\n';
for(i = preLen; i < (arrayLength+preLen)/2; i++)
{
temp = s[i];
s[i] = s[arrayLength - i - 1];
s[arrayLength - i - 1] = temp;
}
preLen += arrayLength;
}
else
{
s[arrayLength] = c;
}
}
s[arrayLength--] = '\0';
}

Code:
getline(line, MAXLINE);
reverseline(line);
printf("%s", line);
Don't cram unrelated functionality into getline.

3. Originally Posted by Salem
Code:
getline(line, MAXLINE);
reverseline(line);
printf("%s", line);
Don't cram unrelated functionality into getline.
Made two functions and almost solved the problem but there's a small snag. One of my inputs token gets skipped ! Why is it behaving like that?

Code:
#include <stdio.h>#include <stdlib.h>
#define MAXLINE 1000
void reverseLine(char[], int);
int getline(char[], int);
int main()
{
int len,c;
char line[MAXLINE];
while((c = getchar()) != EOF)
{
len = getline(line, MAXLINE);
reverseLine(line, len);
printf("%s\n", line);
}
return 0;
}
int getline(char s[], int maxlen)
{
int str, c;
for(str = 0; str < maxlen-1 && (c = getchar()) != EOF && c != '\n'; str++)
{
s[str] = c;
}
if(c == '\n')
{
s[str] = '\0';
}
return str;
}
void reverseLine(char s[], int len)
{
int i, temp;
for(i = 0; i < len/2; i++)
{
temp = s[i];
s[i] = s[len - i - 1];
s[len - i - 1] = temp;
}
}
Thanks !

4. Well, you don't need to call getchar at all in main. You should return EOF from getline when it reads it (and the buffer's empty), so that you can use it like this:

Code:
while ((len = getline(line, MAXLINE)) != EOF) { reverseLine(line, len); puts(line); }
See any implementation of fgets if you have trouble doing this, since it works in a similar way.

5. Originally Posted by Barney McGrew
Well, you don't need to call getchar at all in main. You should return EOF from getline when it reads it (and the buffer's empty), so that you can use it like this:

Code:
while ((len = getline(line, MAXLINE)) != EOF) { reverseLine(line, len); puts(line); }
See any implementation of fgets if you have trouble doing this, since it works in a similar way.
Works perfectly ! Now I get it ! It was the getchar() that ate my last character. Thanks for clearing it out ! I can't use fgets as it is not yet introduced in the text. Thanks for the help .

6. The way getline is defined in K&R, the return value should be 0 (not EOF) in the case that no more lines can be read. This is because getline assumes that a minimal line has a length of 1. The authors also mention that you can also implement getline by just calling fgets:

Code:
/* getline: read a line, return length*/
int getline(char *line, int max)
{
if (fgets(line, max, stdin) == NULL)
return 0;
else
return strlen(line);
}

7. His function discards the newline character, so it returns 0 and stores an empty string with empty lines. I'd say EOF (or any negative integer value) is a good choice for his particular function.

8. Originally Posted by c99tutorial
The way getline is defined in K&R, the return value should be 0 (not EOF) in the case that no more lines can be read. This is because getline assumes that a minimal line has a length of 1. The authors also mention that you can also implement getline by just calling fgets:

Code:
/* getline: read a line, return length*/
int getline(char *line, int max)
{
if (fgets(line, max, stdin) == NULL)
return 0;
else
return strlen(line);
}
My getline() is the bare minimum version as described in the first chapter. It's not the more advanced implementation.

9. Originally Posted by Jeet
My getline() is the bare minimum version as described in the first chapter.
Which edition of the book are you using? In the second edition, the getline() function presented is guaranteed to null-terminate the string. However, your version will only null-terminate it in the case that '\n' is encountered.

10. Originally Posted by c99tutorial
Which edition of the book are you using? In the second edition, the getline() function presented is guaranteed to null-terminate the string. However, your version will only null-terminate it in the case that '\n' is encountered.
You are correct, however not null terminating was my choice not K&R's style.

11. You can define it that way if you want. But a potential problem is that some apparently correct uses are undefined

Code:
int main(void) {
char s[100];
if (getline(s, 100) > 0)
printf("`%s'\n", s);
return 0;
}
If you run this program with some input "abc" which is missing a newline character using K&R's getline(), the output is `abc'. Substituting your version means the output will be undefined. In other words, your version will print `abc??????...' where ??? are random characters in memory, one of which may or may not happen to be a null-terminator that was already hanging around in memory.

12. Originally Posted by c99tutorial
You can define it that way if you want. But a potential problem is that some apparently correct uses are undefined

Code:
int main(void) {
char s[100];
if (getline(s, 100) > 0)
printf("`%s'\n", s);
return 0;
}
If you run this program with some input "abc" which is missing a newline character using K&R's getline(), the output is `abc'. Substituting your version means the output will be undefined. In other words, your version will print `abc??????...' where ??? are random characters in memory, one of which may or may not happen to be a null-terminator that was already hanging around in memory.
Duly noted. But actually my assignment was to replace the null terminator with a newline, the K&R question was a standard of how reversal should be handled.