理解C中的复杂指针示例代码

时间:2016-12-01 21:45:18

标签: c pointers

我正在尝试了解示例指针程序的以下片段,不确定是否可以提出这些问题,如果不是,我会删除!

void f1(char *s) {
    char *p, *q;
    for (p=q=s; *p != '\0'; p++) {
        if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z'))
            *q++ = *p;
        else if (q > s && *(q-1) != '\n')
            *q++ = '\n';
    }
    *q = '\0';
}

我知道有三个指针p,s和q,但我不确定p=q=s需要什么?是否检查指针p和q是否在char a-z之间(一个是小写,另一个是大写)和迭代字母?

任何帮助将不胜感激!

3 个答案:

答案 0 :(得分:3)

回答你的问题,如果一个字符不是一个字母,snips会将一个字符串标记为行,它也会将标记组合在一起并剥离它是否在第一行,但不是在最后一个,它将留下一个换行符。

评论它:

void f1(char *s) {
     /* Two pointers, q for writing and p for reading */
    char *p, *q;

    /* Initialize both at the beginning and start looping the input string */
    for (p=q=s; *p != '\0'; p++) {
        /* If it is a letter, just keep it */
        if ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z'))
            *q++ = *p;
        /* If not, increment the write pointer only if the last
           is not a newline with boundary check */
        else if (q > s && *(q-1) != '\n')
            *q++ = '\n';
    }
    *q = '\0';
}

如果您输入:

char var [] = "    THIS.is a    STRING\n"
              "with two lines...";

结果是:

THIS
is
a
STRING
with
two
lines
/*with one newline at the end */

答案 1 :(得分:0)

如果我们在for循环开始之前查看基本上意味着SelectTagHelper,请设置SelectListDescriptor<select asp-descriptor="@ViewBag.CountryDescriptor"><option value="">-- Choose country</option<</select>。在C语言中,这意味着p,q和s最初被设置为等于相同的字符串(或者更具体地说,指向相同的地址)

答案 2 :(得分:0)

使用索引而不是指针的版本:

void f1(char *buf) {
    size_t src, dst;
    for (src=dst=0; buf[src]; src++) {
        if ((buf[src] >= 'A' && buf[src] <= 'Z') || (buf[src] >= 'a' && buf[src] <= 'z'))
            buf[dst++] = buf[src];
        else if (dst && buf[dst-1] != '\n')
            buf[dst++] = '\n';
    }
    *q = '\0';
}

Kernighan-style

void f1(char *buf) {
    size_t src, dst;
    for (src=dst=0; buf[dst] = buf[src]; src++) {
        if (buf[src] >= 'A' && buf[src] <= 'Z' || buf[src] >= 'a' && buf[src] <= 'z')
            { dst++; continue; }
        if (dst && buf[dst-1] != '\n')
            { buf[dst++] = '\n'; }
    }
}

注意: Kernighan风格的有一个很好的属性:

  for (src=dst=0; buf[dst] = buf[src]; src++) {...}

保证在循环结束后将'\ 0'写入目标。所以,没有可能忘记它。 (除了突破循环时,这里没有这样做)

(当然真正的 Kernighan风格会使用指针和单字母变量; - )