What exactly breaks the while loop in main? - c

What exactly breaks the while loop in this code? This is code from the book The C Programming Language from the C creators. It is a code from section 1.9. I guess int len will always be bigger than 0, but somehow when I compile this code the while loop breaks when I press Ctrl+Z (which is EOF for Windows).
#include <stdio.h>
#define MAXLINE 1000 /* maximum input line length */
int mgetline(char line[], int maxline);
void copy(char to[], char from[]);
/* print the longest input line */
main() {
int len; /* current line length */
int max; /* maximum length seen so far */
char line[MAXLINE]; /* current input line */
char longest[MAXLINE]; /* longest line saved here */
max = 0;
while ((len = mgetline(line, MAXLINE)) > 0)
if (len > max) {
max = len;
if (max == len)
copy(longest, line);
}
if (max > 0) /* there was a line */
printf("%s", longest);
return 0;
}
/* mgetline: read a line into s, return length */
int mgetline(char s[], int lim) {
int c, i;
for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
/* copy: copy 'from' into 'to'; assume to is big enough */
void copy(char to[], char from[]) {
int i;
i = 0;
while ((to[i] = from[i]) != '\0')
++i;
}

Loop 1: (In copy)
Strings in C are NUL-terminated by convention. NUL is a special char value with the value 0.
The value of the expression to[i] = from[i] is the new value of to[i].
That is 0 when NUL is reached, and the loop exits.
Loop 2: (In main)
Similarly the value of len = mgetline(line, MAXLINE) is the new value of len. That is 0 if mgetline returns 0 which is does when no characters are read. So that loop exits.

Related

K&R C Programming Language Exercise 1-16

So I'm working on learning C by going through The C Programming Language and trying to do the exercises as I go. Exercise 1-16 seems really simple as it's just making an edit to a program that is already given.
What I can't figure out is why I can't get the code from the book, or from any of the online solutions to this exercise to compile... Everything I've tried throws an error that says: "error: conflicting types for ‘getline’"
Here's the original code from the book:
/* Write a program to print all input lines that are longer than 80 characters. */
#include <stdio.h>
#define MAXLINE 1000 /* maximum input line size */
int getline(char line[], int maxline);
void copy(char to[], char from[]);
int main ()
{
int len; /* current line length */
int max; /* maximum line length seen so far */
char line[MAXLINE]; /* current input line */
char longest[MAXLINE]; /* longest line saved here */
max = 0;
while ((len = getline(line, MAXLINE)) > 0)
if (len > max) {
max = len;
copy(longest, line);
}
if (max > 0) /* there was a line */
printf("%s", longest);
return 0;
}
/* getline: read a line into s, return length */
int getline(char s[], int lim)
{
int c, i;
for (i=0; i<lim-1 && (c=getchar())!=EOF && c!='\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
/* copy: copy 'from' into 'to'; assume to is big enough */
void copy(char to[], char from[])
{
int i;
i = 0;
while ((to[i] = from[i]) != '\0')
++i;
}
Any glaringly obvious mistakes here? Is it just my machine or how I'm trying to compile it?

Length of line in function defaults to 1 after first user input, why?

I am practicing an algorithm from the C programming book and want to output the length of each line after it is typed. After I write a sentence, it gives me the correct out put of "This is a line of length 10" or something. Then in keeps repeating "This is a line of length 1" over and over until I control +z. How can I get it to just print the length and then continue to receive input each time?
#include <stdio.h>
#define MAXLINE 1000 /* maximum input line size */
int getlines(char line[], int maxline);
void copy(char to[], char from[]);
/* print longest input line */
int main()
{
int len; /* current line length */
int max; /* maximum length seen so far */
char line[MAXLINE]; /* current input line */
char longest[MAXLINE]; /*longest line saved here */
max = 0;
while ((len = getlines(line, MAXLINE)) > 0)
printf("This is the line length %d.", len);
if (len > max) {
max = len;
copy(longest, line);
}
if (max > 0) /* there was a line */
printf("%s", longest);
return 0;
}
/* getline: read a line into s, return length */
int getlines(char s[], int lim)
{
int c, i;
for (i=0; i<lim-1 && (c=getchar()) != EOF && c != '\n'; i++)
s[i] = c;
if (c == '\n') {
s[i] = c;
i++;
}
s[i] = '\0';
return i;
}
/* copy: copy 'from' into 'to'; assume to is big enough */
void copy(char to[], char from[])
{
int i;
i = 0;
while ((to[i] = from[i]) != '\0')
i++;
}
Thank you.
You forgot to enclose statements of the while loop in braces and you need to change the condition of the loop.
while ((len = getlines(line, MAXLINE)) > 1 )
{
printf("This is the line length %d.", len);
if (len > max) {
max = len;
copy(longest, line);
}
}
Or the condition in the while loop can look like
while ((len = getlines(line, MAXLINE)) != 0 && line[0] != '\n' )
Pay attention to that the second parameter of the function copy should have the qualifier const
void copy(char to[], const char from[]);
I ran it and its ok. However you need to note that you were using max which is a keyword and hence your code will not work. see here for more information on max
I modified it a little to help you see better:
int main()
{
int len; /* current line length */
int maxVal; /* maximum length seen so far */
char line[MAXLINE]; /* current input line */
//char longest[MAXLINE]; /*longest line saved here */
maxVal = 0;
printf("Enter Input: ");
while ((len = getlines(line, MAXLINE)) > 0){
printf("This is the line length %d.\n", len);
if (len > maxVal) {
maxVal = len;
//copy(longest, line);
printf("Longest Line is now: %s", line);
}
printf("Enter Input: ");
}
return 0;
}
You can use this if there is no other need for longestLine since all you wanted was to print it based on your code
The output was as follow when tested:
Enter Input: Hello
This is the line length 6.
Longest Line is now: Hello
Enter Input: World
This is the line length 6.
Enter Input: Worldly Affairs
This is the line length 16.
Longest Line is now: Worldly Affairs
Enter Input: Hello World
This is the line length 12.
Enter Input:

Problem in Example 1.9 - The C Programming Language

I have tried to compile and run the program below which is the example 1.9 of the book The C Programming Language. It is compiled OK and no errors are found. However, when I run it and see if the program works, instead of returning me the longest line, it returns a sequence of garbage characters with the same length of the longest line.
Here is the program:
#include <stdio.h>
#define MAXLINE 1000
int getline(char line[], int maxline);
void copy(char to[], char from[]);
int main()
{
int len;
int max;
char line[MAXLINE];
char longest[MAXLINE];
max = 0;
while ((len = getline(line, MAXLINE)) > 0) {
if (len > max) {
max = len;
copy(longest, line);
}
}
if (max > 0) {
printf("%s", longest);
}
return 0;
}
int getline(char s[], int lim)
{
int c, i;
for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i) {
s[i] = c;
}
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
void copy(char to[], char from[])
{
int i;
i = 0;
while ((to[i] = from[i] != '\0')) {
++i;
}
}
This expression:
(to[i] = from[i] != '\0')
is not doing what you think. It will compare from[i] != '\0' first, and assign the result to to[i]. This means the destination string will be the correct length but full of characters with code 1.
So probably you copied the parenthesis in the wrong position:
(to[i] = from[i]) != '\0'

maximum line length program prints unreadable characters in c

I am trying to run the maximum line length program as shown in chapter one of "The c programming language" and the output is always a series of question mark boxes like ⍰.
Here is the code:
#include <stdio.h>
#define MAXLINE 1000 /* maximum input line size */
int getline(char line[], int maxline);
void copy(char to[], char from[]);
/* print longest input line */
int main()
{
int len; /* current line length */
int max; /* maximum length seen so far */
char line[MAXLINE]; /* current input line */
char longest[MAXLINE]; /* longest line saved here */
max =0;
while((len = getline(line, MAXLINE)) > 0)
if (len > max) {
max = len;
copy(longest, line);
}
if (max > 0) /* there was a line */
printf("%s", longest);
return 0;
}
/* getline: read a line into s, return length */
int getline(char s[], int lim)
{
int c, i;
for (i = 0; i < lim - 1 && (c = getchar() != EOF) && c != '\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
/* copy: copy 'from' into 'to'; assume to is big enough */
void copy(char to[], char from[])
{
int i;
i = 0;
while ((to[i] = from[i]) != '\0')
++i;
}
Is this a technical issue or something obviously wrong with the code?
Thank-you?
You have a tiny, tiny typo. This line in the getline function:
for (i = 0; i < lim - 1 && (c = getchar() != EOF) && c != '\n'; ++i)
should be
for (i = 0; i < lim - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
The effect of this typo is that you call getchar(), test the returned value to see if it's equal to EOF or not, and assign the 1/0 (true/false) value to the variable c. But what you want to do is assign the returned value from getchar() to c, and then test to see if it's equal to EOF.
So if you type, say, "test", your typo-afflicted getline function was not writing the characters t e s t into line; instead it was writing four 1 values (that is, the character '\001', which is a control-A if you want to think about it that way), and since that's not a printing character, your display system printed it as a little box instead.

strange algorithm in C

I was following one of the exercises in the book "The C Programming Language":
http://users.powernet.co.uk/eton/kandr2/krx116.html
In the below program, if the input file contains the line 'h\n', for example, the getline function initializes i and j to 0. Since 'h' is not EOF or '\n', the block in loop executes, the c is assigned to the 0 index of the s array pointer, since j is 0. Then j increments to 1. Then the block ends and the i counter increments to 1. And the loop checks if the next character is a '\n', and it is, so the block exits. At this point, i and j are both equal to 1. Since c is equal to '\n', c is inserted into index 1 of the s pointer, since j is 1. Then j is incremented to 2. Then i is incremented to 2. Then the null terminator '\0' is inserted into index 2 of the s pointer, since j is 2. Then the function returns 2, since i is also 2.
I see no point of the j variable. Because when it increments, so does i. Someone said I was wrong:
"because they're incremented at different rates. The i counter is used to keep track of the length of the string. The j variable, at the end of the processing, stores the point where the null terminator needs to go in the string."
But I say since i and j are the same values (one is just incremented after the other), you could use i to the point where the null terminator needs to go, since i would also be equal to 2 in my above example.
#include <stdio.h>
#define MAXLINE 1000 /* maximum input line size */
int getline(char line[], int maxline);
void copy(char to[], char from[]);
/* print longest input line */
int main(void)
{
int len; /* current line length */
int max; /* maximum length seen so far */
char line[MAXLINE]; /* current input line */
char longest[MAXLINE]; /* longest line saved here */
max = 0;
while((len = getline(line, MAXLINE)) > 0)
{
printf("%d: %s", len, line);
if(len > max)
{
max = len;
copy(longest, line);
}
}
if(max > 0)
{
printf("Longest is %d characters:\n%s", max, longest);
}
printf("\n");
return 0;
}
/* getline: read a line into s, return length */
int getline(char s[], int lim)
{
int c, i, j;
for(i = 0, j = 0; (c = getchar())!=EOF && c != '\n'; ++i)
{
if(i < lim - 1)
{
s[j++] = c;
}
}
if(c == '\n')
{
if(i <= lim - 1)
{
s[j++] = c;
}
++i;
}
s[j] = '\0';
return i;
}
/* copy: copy 'from' into 'to'; assume 'to' is big enough */
void copy(char to[], char from[])
{
int i;
i = 0;
while((to[i] = from[i]) != '\0')
{
++i;
}
}
Am I right or wrong?
You're not quite right. If the input string is longer than the limit, the loop will continue incrementing i in order to count input characters even though they're not going into the result string.

Resources