在C中交换名字和姓氏

时间:2018-04-19 20:23:21

标签: c

我的问题是要了解为什么会发生这种情况。

我的目标是将第一个名字“Joe”和姓氏“Bloggs”传递给我创建的交换功能,并让它切换它们。 (所以名字现在包含Bloggs,反之亦然)

我创建了一个交换函数,它将指向名字和姓氏的指针作为参数。该函数似乎有效,因为使用print语句我可以看到两个字符串的值已经改变。

#include <stdio.h>

void swap(char * first, char * last) {
    char * temp;
    temp = first;
    first = last;
    last = temp;
    printf("at end of swap func the first name is: %s\n", first);
    printf("at end of swap func the last name is: %s\n", last);
}

现在似乎是问题,在调用交换函数后,我再次打印名字和姓氏,但它们没有显示交换函数的结果。

int main() {
    char * first = "Joe";
    char * last = "Bloggs";
    printf("The original format: %s %s\n", first, last);
    swap(first, last);
    printf("The new format: %s %s", first, last);//new format was supposed to be Bloggs Joe
}

我搜索过但是我发现的问题并不是我特有的。正如我之前所说,我真的很想知道为什么会这样。我对C知之甚少,所以任何建议都将受到赞赏。

3 个答案:

答案 0 :(得分:11)

在C中,所有参数都按值传递。这意味着该函数中的firstlastfirst中的lastmain不同。对局部变量的更改不会反映在调用者中。

您需要传递要更改的变量的地址。然后在函数中,取消引用给定的指针以更改它们指向的内容。

所以改变你的功能如下:

void swap(char ** first, char ** last) {
  char * temp;
  temp = *first;
  *first = *last;
  *last = temp;
  printf("at end of swap func the first name is: %s\n", *first);
  printf("at end of swap func the last name is: %s\n", *last);
}

并称之为:

swap(&first, &last);

请注意,实际被交换的是指针值,而不是指针实际指向的内容。您可以在两个字符串之间交换字符,但有问题的字符串是字符串文字,无法修改。

如果您有包含字符串的char数组,那么您可以交换字符。事实上,你必须这样做,因为数组与指针不同。

以下是完整字符串交换的完整示例:

#include <stdio.h>
#include <string.h>

// assumes that each array is big enough to hold the contents of the other
void swap(char *first, char *last) {
  int len1 = strlen(first);
  int len2 = strlen(last);
  int maxlen = (len1 > len2) ? len1 : len2;
  char temp[maxlen+1];
  strcpy(temp, first);
  strcpy(first, last);
  strcpy(last, temp); 
  printf("at end of swap func the first name is: %s\n", first);
  printf("at end of swap func the last name is: %s\n", last);
}

int main() {
  char first[10] = "Joe";
  char last[10] = "Bloggs";
  printf("The original format: %s %s\n", first, last);
  swap(first, last);
  printf("The new format: %s %s", first, last);
}

答案 1 :(得分:1)

交换变量是临时使用临时内容完成的:

char *temp;
temp = first;
first = last;
last = first;

这不能很好地转换为使用pass by value的C函数调用。这意味着该函数接收值的副本作为其参数。您可以编写一个宏,但是通用宏必须处理诸如参数是表达式之类的问题,并避免将自己的内部变量与传入的参数进行名称冲突。

#define swap(A, B) do {            \
    char **swap_A__ = &(A);        \
    char **swap_B__ = &(B);        \
    char *swap_temp__ = *swap_A__; \
    *swap_A__ = *swap_B__;         \
    *swap_B__ = swap_temp__;       \
} while (0)

这使您免于编写函数,但实现失去了惯用方法的简单性。

虽然函数调用是首选,但它会失去通过引用接口传递的外观。如果您能够实现通用交换功能:

void swap_generic(void *a, void *b, size_t sz);

然后,您可以将交换宏包装为调用泛型函数,并使您能够模拟“按引用调用”接口,但将适当的参数传递给泛型函数:

#define swap(A, B) do {                                    \
    _Static_assert(sizeof(A) == sizeof(B), "unswappable"); \
    _Static_assert(sizeof(&(A) - &(B)), "type check");     \
    swap_generic(&(A), &(B), sizeof(A));                   \
} while (0)

实现通用交换功能可以按如下方式完成:

void swap_generic (void *a, void *b, size_t sz) {
    char *aa = a;
    char *bb = b;
    while (sz--) {
        char temp = *aa;
        *aa++ = *bb;
        *bb++ = temp;
    }
}

答案 2 :(得分:0)

#include <stdio.h>

void swap(char ** first, char ** last) {
  char * temp;
  temp = *first;
  *first = *last;
  *last = temp;
  printf("at end of swap func the first name is: %s\n", *first);
  printf("at end of swap func the last name is: %s\n", *last);
}

int main() {
  char * first = "Joe";
  char * last = "Bloggs";
  printf("The original format: %s %s\n", first, last);
  swap(&first, &last);
  printf("The new format: %s %s", first, last);//new format was supposed to be Bloggs Joe
}

如果要更改参数的地址,请传递参数的地址,而不是值。