2

I am rather new to programming so please bear with me.

Here is the prompt for exercise 1-18: Write a program to remove trailing blanks and tabs from each line of input, and to delete entirely blank lines.

And here is my code:

#include <stdio.h>

#define MAXLINE 1000

int better_line_length(char line[], int lim);
void copy(char to[], char from[]);

int main(void)
{
    int len, a;
    char s[MAXLINE];
    char better_s[MAXLINE];

    while ((better_line_length(s, MAXLINE)) > 0) {
            copy(better_s, s);
            printf("%s\n", better_s);
        }

    return 0;
}

int better_line_length(char s[], int lim)
{
    int c, i, last_letter = 0;

    for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) {
        s[i] = c;
        if (c != ' ' && c != '\t')
            last_letter = i+1;
    }
    if (c == '\n' && s[0] == c)
        last_letter = 0;

    s[last_letter] = '\0';

    return last_letter;
}

void copy(char to[], char from[]) 
{
    int i = 0;

    while ((to[i] = from[i]) != '\0')
        ++i;
}

My program is not giving me the output I expect. It properly removes trailing blanks and tabs in the absence of a blank line, but things get weird when a blank line is present.

For example, if my input is (where ▯▯▯ are spaces)

abcdefg▯▯▯▯▯▯▯▯▯▯▯▯
1234▯▯▯▯▯

I get the expected output of

abcdefg
1234

But if my input is something like

abcdefg▯▯▯▯▯▯▯▯▯▯▯▯
1234▯▯▯▯▯

xyz▯▯▯▯▯▯
987▯▯▯▯▯

I get an output of

abcdefg
1234

But I expect an output of

abcdefg
1234
xyz
987

It seems like my while statement, while ((better_line_length(s, MAXLINE)) > 0) in main() stops executing when it encounters a blank line instead of just skipping over it. I've spent hours on this and I still can't figure out why. I thought that setting better_line_length to return 0 if the first character of a line is '\n' would fix the code, but it doesn't change a thing.

Why am I encountering this unexpected output, and why doesn't the above idea fix my program?

Please remember that K&R doesn't introduce certain advanced topics until much past chapter 1, so pointers and certain other topics do not yet make sense to me.

Thanks!

jhschwartz
  • 168
  • 1
  • 2
  • 13

2 Answers2

2

I see you are still trying to solve this exercise. Good for you, don't give up!

As for problems with your current solution: one thing you can do is you can modify the better_line_length() function to return something meaning there was an empty line and skip that line inside the while ((len = better_line_length(s, MAXLINE)) > 0) loop.

For example, you can add the following inside the body of better_line_length(), right after the for loop:

if(i == 0 && c == '\n')
  return -1;

Then you will know that this is the line you need to skip. You could also add similar return code meaning that there was end of file/end of stdin.

Let me know if you need any more help.

syntagma
  • 23,346
  • 16
  • 78
  • 134
  • Thanks! I finally got it to work with your help, but I'm not quite sure why. I added in your suggestion after the `for` loop, and also added a conditional statement of `if (len > 0) {` under my `while ((len = better_line_length(s, MAXLINE)))`, and the program works! But I don't understand why returning -1 works but returning 0 doesn't. Since the loop executes the conditional only when `better_line_length()` is greater than 0, shouldn't it skip lines when the function returns either 0 or -1? – jhschwartz Nov 24 '14 at 01:43
  • I think you haven't quite understood `while` loops. It executes until the condition is true. It will only 'skip' lines by ending the loop and not processing any more lines. – Persixty Nov 24 '14 at 06:53
  • What you may get confused about is the way C handles while/if conditions: integers are can treated like booleans: 0 (zero) is always false, and non-zero (1, -1, etc.) are always true. – syntagma Nov 24 '14 at 09:53
1

Look closely at the line you mention:

while ((better_line_length(s, MAXLINE)) > 0) {

If the function better_line_length() returns 0 the condition is false and the loop ends. That's why it's giving up at the first blank line.

You should think about returning something different when you've really reached the end or just a blank line.

You might (for example) return -1 when you've reached the end of the input.

Persixty
  • 8,165
  • 2
  • 13
  • 35
  • But even if I change that line to be `while (better_line_length(s, MAXLINE)) {` I still get the same output. – jhschwartz Nov 23 '14 at 22:30
  • Yes, because 0 is 'false' so you've not really changed anything! I still suggest returning -1 if you read EOF and the line length is empty. Then you use while ((better_line_length(s, MAXLINE))!=-1) { – Persixty Nov 23 '14 at 22:34