使用C语言中的指针理解操作的问题

时间:2013-09-03 17:23:48

标签: c pointers

我想了解为什么有些角色会消失,之后会消失 在原始字符串中连接。请参阅c = *sibl收到*sibl的第一个字符, *sibl = *inout收到*inout的内容,但c中存储的字符不在*inout。而且,*inout = c不会更改*inout的内容,而是c会与*inout的内容联系起来。我不明白为什么会这样!

我的代码:

void Cripto (char *inout, int i) {
    char *sibl, c;
    while (*inout) {
        sibl = inout+1;
        if (!sibl)
            break;
        if (*inout >= 'A' && *inout <= 'Z'){
            *inout += i;
        }
        c = *sibl;
        printf("val c %c\n",c);
        printf("val inout after c %s\n",inout);
        printf("val sibl after c %s\n",sibl);
        *sibl = *inout;
        printf("val sibl after att %s\n",sibl);
        *inout = c;
        printf("val inout after att %s\n",inout);
    inout = sibl+1;
    }
}

int main() {
    char str[30];
    int i;
    scanf("%s %d", str, &i);
    Cripto(str, i);
    printf("%s\n", str);
    return 0;

}

“teste”3的结果:

val c: e  
val inout after c: teste  
val sibl after c: este  
val sibl after att: tste  
val inout after att: etste  
val c: t  
val inout after c: ste  
val sibl after c: te   
val sibl after att: se  
val inout after att: tse  
val c:  
val inout after c: e  
val sibl after c:    
val sibl after att: e  
val inout after att:  

3 个答案:

答案 0 :(得分:2)

你需要谨慎的另一件事(除非你有意这样做)是以下两行:

sibl = inout+1;
*sibl = *inout;

您将sibl指向inout + 1,然后通过inout的值指定sibl的值(实际上是指向inout + 1的指针)。这将改变inout本身的值。因此,如果inout是(“123”),则sibl指向“23”并且使用“* sibl = * inout”,则使用第一个char设置inout(即sibl)的第二个char。因此,inout将成为“113”。

答案 1 :(得分:1)

您遇到问题的原因是您在while()循环中以2为步骤进行迭代:

while(*inout) {
    sibl = inout+1;
    // ...
    inout = sibl+1;  // = (inout+1)+1 = inout+2
}

想要做的事情是迭代inout指向的字符串并添加i(可能是一个小值)char是一个大写字母,所以为什么不使用类似的东西:

while(*inout) {
    if( *inout>='A' && *inout<='Z' ) {
        *inout += (char)i;
    }
    inout++;
}

答案 2 :(得分:1)

此代码中没有连接。只有覆盖发生。这是代码的作用:

  1. 在某个内存缓冲区中有一个字符串,用作输入和输出。变量inout是一个从该字符串开头开始的指针。但是,随着函数的进行,此指针被修改为指向此字符串中的其他字符。因此,当您稍后输出它指向的字符串时,将仅打印字符串的后缀。前缀仍然存在,但C字符串始终从开始指针解释为终止空字符。

  2. 在第一次迭代中,inout是指向第一个字符的指针,sibl指向输入数组中的第二个字符。如果任何一个指向终止空字符,则循环终止。

  3. 如果inout指向的字符为大写,则其ASCII值增加i。作为旁注:此操作在编写时不可逆,因为'Z' + 3(或类似)将映射到一些本身不会被修改的非字母数字字符。

  4. 序列c = *inout; *inout = *sibl; *sibl = c交换两个相邻的字符。

  5. inout = sibl + 1;有效地将inout向前移动了两个字符,因为sibl上次设置为inout + 1

  6. 第二次迭代对字符3和4做同样的事情,就像第一次迭代对字符1和2做的那样。您不再在printf输出中看到第一次迭代的结果,因为这两个字符现在位于两个指针之前,并且在函数内基本上无法访问。然而,main中的指针未被修改,并且最后printf应该为您提供整个操作结果。