I write a program to solve Exercise 2-2 of K&R.
#include<stdio.h>
#define MAXLINE 1000
/* write an equivalent loop without using && or || */
int Getline(char s[], int lim);
int main()
{
int len;
char line[MAXLINE];
while ((len = Getline(line, MAXLINE)) > 0) {
printf("%s%15s%d\n", line, "length: ", len);
}
return 0;
}
int Getline(char s[], int lim)
{
int flag = 1;
int i = 0, c = 0;
for (i = 0; flag == 1; ++i) {
if (i < lim - 1) {
if ((c = getchar()) != '\n') {
if (c != EOF) {
;
}
else {
flag = 0;
}
}
else {
flag = 0;
}
}
else {
flag = 0;
}
if (flag == 1) {
s[i] = c;
}
}
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
This program is wrong...in a weird way. I run this code with redirection like
./2-2 <in
with the in file
Get this line.
Then the output to the screen is countless
G length: 1
It looks like the program stuck in a loop. But when I stop using redirection and just type Get this line. to the terminal, though it is still wrong, the countless output disappeared. Why?
The problem is here:
for (i = 0; flag == 1; ++i) {
^^^
i will always increment to at least 1
before the for-loop ends
so your function will never return 0
Instead of incrementing in a for-loop, only increment after inserting a new element. Like
if (flag == 1) {
s[i] = c;
++i;
}
Instead of a for-loop, you could use a while loop, like:
int i = 0;
while (flag == 1)
{
...
}
The next step is to get rid of the flag and use break
insted. Like:
int i = 0;
while (1)
{
if (i >= lim - 1) break;
...
}
Your code will be much shorter and easier to read.
You have also complicated your function quite a bit. If you simply want to get the line redirected from the file, store it in line
and insure it is nul-terminated (and without the trailing '\\n'
- which you shouldn't leave dangling off strings you store), you could do something quite simple like:
int Getline (char *s, int lim)
{
int i = 0; /* char count - length */
while (i < lim - 1) { /* loop while chars fit */
int c = getchar(); /* getchar */
if (c == EOF) /* validate EOF? */
goto done;
if (c == '\n') /* validate newline */
continue;
s[i++] = c; /* good char, increment len */
}
done:;
s[i] = 0; /* nul-terminate */
return i; /* return length */
}
( note: from your comment about not having used break
before, then a simple goto
works just as well)
Example Use/Output
Given your file containing the line "Get this line."
$ ./bin/equivloop <dat/in
Get this line. length: 14
(note: if you store the newline, then the length would be 15 and that output would be on the next line)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.