Search code examples
cgetchar

k&r: Exercise 1-18. Program takes input but doesnt produce any output?


i'm currently going through K&R. right now i'm at exercise 1-18: "Write a program to remove trailing blanks and tabs from each line of input, and to delete entirely blank lines.".

remove_trailing_blanks is a function i wrote that's supposed to remove all trailing blanks from a string. the way it accomplishes that is it takes a character array, and copies it to a different string while also removing all trailing blanks. right now i'm only working on the "trailing blanks" part of the exercise because once i get that done it shouldn't be hard to implement the rest.

when compiling with gcc (c89) the program will take input, but will not produce any output. why is that? i'm assuming it has something to do with the way getchar() works? i'm not sure.

thanks in advance (:

EDIT: honestly i just found out that "trailing blanks" does not mean a series of blanks longer than 1. lol

code:

#include <stdio.h>
#define MAXLINE 1000 

int getline(char line[], int limit);
void remove_trailing_blanks(char line[], char new_line[], int lenght);

main()
{
    int c;
    char line[MAXLINE];
    char new_line[MAXLINE];

    while ((c = getline(line, MAXLINE)) != 0) {
        remove_trailing_blanks(line, new_line, c);
        printf("%s\n", new_line);
    }
    return 0;
}

int getline(char line[], int limit)
{
    char c;
    int i;

    for (i = 0; ((c = getchar()) != EOF) && i < limit && c != '\n' ; ++i) {
        line[i] = c;
    }
    if (c == '\n') {
        line[i] = c;
        ++i;
    }
    return i;
}

void remove_trailing_blanks(char line[], char new_line[], int lim) {
    int i, state = 0;
    
    for(i == 0; line[i] != '\0' && i < lim; ++i) {
        if (state > 0) {
            state = 0;
            while (line[i] == ' ') { ++i; }
        }
        if (line[i] == ' ') {
            ++state;
            new_line[i] = line[i];
        }
        else {
            new_line[i] = line[i];
        }
        printf("%s\n", new_line);
    }
}


Solution

  • The function getchar returns a value of type int. You should not store the return value of that function in a char, because depending on the platform you are using,

    • the data type char may not be able to represent the value EOF,
    • you may not be able to distinguish the value EOF from the value of a valid character code.

    It is only safe to store the return value of getchar into a char after you have determined that getchar did not return the value EOF.

    See the following question for further information:

    Why must the variable used to hold getchar's return value be declared as int?

    To fix this problem, all you have to do is change the data type of c from char to int.


    Another problem is that it is unclear whether your strings should be null-terminated or not. The line

    printf("%s\n", new_line);
    

    implies that your string should be null-terminated, because the %s conversion format specification requires this to be the case. However, in your function getline, you are not writing a null character to the end of the string, and you are instead only keeping track of the length of the string with a separate variable.

    If you don't want your strings to be null-terminated, then you must specify the length of the string when calling printf, for example like this:

    printf("%.*s\n", 20, new_line);
    

    In this example, 20 is the length of the string, and you are instructing printf to print at most 20 characters.

    However, if you are following the K&R book, I guess that you are supposed to use null-terminated strings. In that case, your function getline must write a null character to the end of the string.


    Another problem is that in your function remove_trailing_blanks, the line

    for(i == 0; line[i] != '\0' && i < lim; ++i) {
    

    is wrong. If you want to set i to 0, you must use the = assignment operator instead of the == comparison operator.

    Your compiler should be warning you of this, if you have an appropriate warning level active. If you did not get such a warning from the compiler, then I suggest that you read this:

    Why should I always enable compiler warnings?

    This will also tell you how to set the compiler's warning level to an appropriate level.

    Fixing this should solve your problem of not getting output. I will leave the rest up to you.