这家伙又emo了 2022-05-16 18:32 采纳率: 84.6%
浏览 75
已结题

对于K&R exercise 5-13实现程序中一个语句i = (i + 1) % LINES的质疑

编写程序 tail,打印输入的最后 n 行。
大家好,我关于其实现程序不清楚的部分是如下程序段,书中对i = (i + 1) % LINES的描述是这样的。

    for (i = first; n-- > 0; i = (i + 1) % LINES)
        printf("%s", lineptr[i]);

书中对于该段语句的解读:
因为i从初值first开始递增n次,那么,当i大于LINES时,就会出现某些输人行被反复打印多次的情况。为了避免出现这一局面,我们使用了取模运算符(%)来确保i的取值范围能够落在0到LINES- 1之间。

我知道i = (i + 1) % LINES所起到地作用就是限制变量i的范围。但在思考之后发现这并没什么意义?原因如下:
i的初始值为first,如果最终i要大于LINES,那么first+n就要大于LINES。
又因为程序段中

  first = last - n;//输出行的起始索引,要从输入最后一行的索引开始,退回n个值

那么就是说要满足上面所述的这种情况,last就要大于LINES,但是last不可能大于LINES呀!
原因如下:

        if (++last >= LINES)
            last = 0;//如果输入行总数(last的值)每超过LINES一次,last值就重置一次(设置为0),类似环状结构

所以我就很好奇i = (i + 1) % LINES的重要性
产生的问题:
我无法理解刚才书中这段话的意思。
1.什么时候才会出现它所说的某些输入行被反复打印
2.它说的会出现某些输人行被反复打印多次的情况,某些行是指这些行是随机的吗?
3.我直接把这个程序段

    for (i = first; n-- > 0; i = (i + 1) % LINES)
        printf("%s", lineptr[i]);

改成这个可以吗,因为根据我上面的分析变量i是不可能大于LINES的,所以我觉得没必要限制范围。

    for (i = first; n-- > 0; i ++)
        printf("%s", lineptr[i]);

实现程序

/* Write a Program tail, which prints the last n lines of its input. By default n is 10. let us say; but it can be changed
by an optional argument so that tail -n */
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define DEFLINES 10 /* default # of lines to print */
#define LINES 3 /* maximum # of lines to print */
#define MAXLEN 100 /* maximum length of an input line */

void error(char *);
int mgetline(char *, int);

/* print the last n lines of the input */

int main(int argc, char *argv[])
{
    char *p;
    char *buf; /* pointer to the large buffer */
    char *bufend; /* end of the large buffer */

    char line[MAXLEN];
    char *lineptr[LINES]; /* pointer to lines read */

    int first, i, last, len, n, nlines;

    scanf("%d", &argc);
    for (int i = 1; i < argc; i++)
    {
        argv[i] = (char *)malloc(MAXLEN * sizeof(char));
        scanf("%s", argv[i]);
    }
    getchar();
    if (argc == 1)
        n = DEFLINES;

    else if (argc == 2 && (*++argv)[0] == '-')
        n = atoi(argv[0] + 1);
    else
        error("Usage: tail [-n]");

    if (n < 1 || n > LINES)//将输入的最后n行打印出来,所以n的值有意义的同时,不能够大于最多允许打印的行数
        n = LINES;

    for (i = 0; i < LINES; i++)
        lineptr[i] = NULL;

    if ((p = buf = malloc(LINES * MAXLEN)) == NULL)
        error("tail: cannot allocate buf");
    bufend = buf + LINES + MAXLEN;

    last = 0;    //上一个输入行的索引
    nlines = 0;    //输入行的个数

    while ((len = mgetline(line, MAXLEN)) > 0)
    {
        if (p + len + 1 >= bufend)
            p = buf;
        lineptr[last] = p;

        strcpy(lineptr[last], line);
        if (++last >= LINES)
            last = 0;

        p += len + 1;    //mgetline返回的字符串长度len没有将终止符'\0'算在其中
        nlines++;
    }

    if (n > nlines)        //lines of request more than recording ?
        n = nlines;

    first = last - n;//输出行的起始索引,要从输入最后一行的索引开始,退回n个值

    if (first < 0)
        first += LINES;

    for (i = first; n-- > 0; i = (i + 1) % LINES)
        printf("%s", lineptr[i]);
    return 0;
}

/* error: print error messages and exit */

void error(char *s)
{
    printf("%s\n", s);
    exit(1);
}

/* mgetline: read a line into s and 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;
}

  • 写回答

2条回答 默认 最新

  • 树下等苹果 2022-05-16 19:06
    关注

    我觉得:

        for (i = first; n-- > 0; i = (i + 1) % LINES)
            printf("%s", lineptr[i]);
    

    这句的作用是这样的:
    如果没有使用%:假如写入8行,last=8,输出最后3行,即n=3。那么first=last-n=8-3=5。也就是lineptr[i]的下标i从5开始,如果不对其取模的话,这就超过了定义时的:lineptr[LINES] 的范围,因为LINES=3。所以使用取余能够限定i的值小于LINES。
    这是我的一点看法。

    评论

报告相同问题?

问题事件

  • 已结题 (查看结题原因) 5月22日
  • 修改了问题 5月18日
  • 修改了问题 5月18日
  • 修改了问题 5月17日
  • 展开全部

悬赏问题

  • ¥15 求修改代码,图书管理系统
  • ¥15 请问有没求偏多标签数据集yeast,reference,recreation,scene,health数据集。
  • ¥15 传感网应用开发单片机实训
  • ¥15 Delphi 关于sAlphaImageList使用问题
  • ¥15 寻找将CAJ格式文档转txt文本的方案
  • ¥20 数电设计提问求帮助,出租车计费器
  • ¥15 shein测试开发会问些啥我是写java的
  • ¥15 关于#单片机#的问题:我有个课程项目设计,我想在STM32F103veTX单片机,M3主控模块上设计一个程序,在Keil uVision5(C语言)上代码该怎么编译?(嫌钱少我可以加钱,急急急)
  • ¥15 opnet仿真网络协议遇到问题
  • ¥15 在安装python的机器学习程序包scikit-learn(1.1版本)时遇到如下问题