用指针交换同一字符串的两个字符

Swapping two characters of the same string with pointers

我正在尝试解决朋友发给我的一段代码。他正在练习指针并尝试使用它们来反转字符串。

这应该是一个非常简单的任务,但我的知识在这里存在差距。我已经能够成功地创建一个 for 循环,它使用 ij 作为控制变量正确地遍历字符串。我也已经能够打印出需要交换的字符。

唯一的问题是 for 循环中的注释代码行。它应该交换这两个值,但抛出错误,我不明白为什么。

#include <stdio.h>

int length(char *p);
void reverse(char *);

int main() {
    char *p = "Computer";
    reverse(p);
}

int length(char *p) {
    int i;
    for (i = 0; *(p + i) != '[=10=]'; i++);
    return i;
}

void reverse(char *p) {
    int l, i;
    char t;

    for (l = 0; *(p + l) != '[=10=]'; l++);
    int len = l;
    int temp;
    for (i = 0; i < l; i++, l--) {
        t = *(p + i);
        printf("i-th element - %c\n", t);
        printf("j-th element - %c\n", *(p + len - 1 - i));
        *(p + i) = *(p + len - 1 - i);  // crash
    }
    puts(p);
}

我什至不确定是否可以这样交换它们。我会选择 t = p[i]; p[i] = p[i + 1]... 方法。如果有人能纠正和解释这个和指针相关的戏剧,那就太好了。

首先,您不能尝试修改字符串文字。

您应该使用(可修改的)数组:

    char p[] = "Computer";

而不是

    char *p = "Computer";

其次,您需要

*(p + len - 1 - i) = t;

之后

*(p + i) = *(p + len - 1 - i);

完成交换。

对于初学者,您不能更改字符串文字

char *p = "Computer";

任何更改字符串文字的尝试都会导致未定义的行为。

所以不是指向字符串文字的指针,而是声明一个字符数组,如

char s[] = "Computer";

此外,您的函数 reverse 不使用函数 length,实际上不反转字符串。

这个循环

for (i = 0; i < l; i++, l--) {

使用两个辅助变量作为索引。

函数reverse不输出任何内容。它要做的是反转传递的字符串。函数的调用者决定是否输出反转字符串或将其用于其他目的。

函数 lengthreverse 可以通过以下方式仅使用指针来声明和定义

size_t length( const char *s ) 
{
    const char *p = s;

    while ( *p ) ++p;

    return p - s;
}

char * reverse( char *s ) 
{
    if ( *s )
    {
        for ( char *p = s, *q = s + length( s ); p < --q; ++p )
        {
            char c = *p;
            *p = *q;
            *q = c;
        }
    }

    return s;
}

函数reverse可以这样调用

int main( void )
{
    char s[] = "Computer";

    puts( s );
    puts( reverse( s ) );
}

这是一个演示程序。

#include <stdio.h>

size_t length( const char *s ) 
{
    const char *p = s;

    while ( *p ) ++p;

    return p - s;
}

char * reverse( char *s ) 
{
    if ( *s )
    {
        for ( char *p = s, *q = s + length( s ); p < --q; ++p )
        {
            char c = *p;
            *p = *q;
            *q = c;
        }
    }

    return s;
}

int main( void )
{
    char s[] = "Computer";

    puts( s );
    puts( reverse( s ) );
}

它的输出是

Computer
retupmoC

正如您在两个函数中看到的那样,用作索引的变量都不存在。这些函数仅使用指针。

使用尖点需要小心,否则到处都会出现“分段错误”。但是,让我们这样做。我使用的一种反转字符串的技术是,第一个指针指向字符串的开头,另一个指针指向字符串的结尾;并在它们到达字符串中间时促进交换(这样我将处理减少了一半)检查此代码

/* reverses a string
 * !!! this function modifies input string !!! 
 */
char *reverse(char *s)
{
    char *h, *t, c; /* h)ead, t)ail and a temporary c */
    int len = 0;
    /* positioning the pointers at beginning and end of string s */
    len = length(s);

    h = (char*)&s[0];
    t = (char*)&s[len - 1];

    for (int i = 0; i < (len / 2); i++)
    {
        /* swap chars */
        c = *h;
        *h = *t;
        *t = c;

        /* increase h pointer, decrease t pointer */
        h++;
        t--;
    }
    return s;
}

纯指针...以任何形式交换 *h 和 *t 时你都无法摆脱临时存储 ( c );

请注意输入字符串需要声明为 char name[] 否则 sigsegv 会跟随您!

如果你想保存字符串供以后直接打印到stdout,你可以这样做:

char * reverse(char * I){
  int i,l;
  char * O;
  l=strlen(I);
  O=malloc(l+1);
  for(i=1;i<=l;i++)O[i-1]=I[l-i];
  O[l]='[=10=]';
  return O;
}
int main(){
  char * p=reverse("Computer");
  printf("%s",p);
  free(p);
}