2016-12-01 84 views
2

我想了解以下代码示例指针程序的片段,不知道是否有可能问这些问题,如果不是,我会删除!了解复杂的指针示例代码C

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之间(其中一个是小写字母,另一个是大写字母)并遍历字母?

任何帮助,将不胜感激!

+0

DO(循环,这WHE这里不做的突破时除外)你知道你使用'''而不是''来表示字符吗? – mch

+0

是的,抱歉。那是我教授在幻灯片中的榜样。我会改变它。 – Nuggets10

+0

你应该学会使用调试器。用几个随机字符串测试代码并在运行时进行调试。这应该让你对代码的实际操作有所了解。 –

回答

0

如果我们看一下for (p=q=s; *p != '\0'; p++)这个基本意思是for循环开始之前,设置p = sq = s。在C语言中,这意味着p,q和s最初设置为等于相同的字符串(或者更具体地说,指向相同的地址)

3

回答您的问题,如果字符不是一封信,它也将令牌集中在一起,如果它位于第一行,则不会剥离,但最后不会放到一条换行符。

评论它:

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 */ 
+0

嗨,感谢您编写示例代码来测试它!我只是使用例子blah2blah4在笔和纸上做了一些步骤,然后用它来标记等等等等(尽管这很有道理),但你的解释要好得多!欣赏它。 :)我不确定换行符是否打算或者不是LOL。 – Nuggets10

+0

原来的代码真的让人困惑,呃? – bipll

+0

@bipll哈哈哈......这可以是一个无符号的长长整型讨论。 –

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的风格相同:

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的风格将使用指针,一个字母的变量;-)