将两个指针字符串连接在一起的函数

时间:2018-11-26 22:05:37

标签: c pointers

在将这两个指针字符串连接在一起时,我遇到了问题,下面是我的连接函数,我应该将字符串1添加到字符串2中。而且我不能使用字符串库中的任何函数,这样做的目的是通过自己编写代码来帮助我们了解函数中实际上是什么代码。

char strconcat(char *user2p, char *user1p) {
    while (*user2p) {
        user2p++;
    }
    while (*user1p) {
        *user2p = *user1p;
        *user2p++;
        *user1p++;
    }
    *user2p = '\0';

    printf("test: %c", *user2p);

    return *user2p;
}

这是我的主要部分中与该功能相关的部分。

int main() {
    char userString1[21], userString2[21];
    char *user1p, *user2p;

    user1p = userString1;
    user2p = userString2;

    printf("Please enter the first string: ");
    gets(userString1);

    printf("Please enter the second string: ");
    gets(userString2);

    printf("String 1 after concatenation: ");
    puts(userString1);
    printf("String 2 after concatenation: %c\n", strconcat(user2p, user1p));

终端一直在给我这个,我没有提供长度和字母顺序的代码。当我尝试在函数中运行测试printf时,它为我提供了null;当我返回该函数时,它却没有给我任何帮助。我不知所措,非常感谢您的帮助!

 Please enter the first string: jackhammer
 Please enter the second string: jacky
 The length of string 1 is: 10
 The length of string 2 is: 5
 String 1 comes before string 2 alphabetically.
 String 1 after concatenation: jackhammer
 (null)
 String 2 after concatenation:

3 个答案:

答案 0 :(得分:5)

您的concat算法很好,但是您必须将 pointer 返回到原始 [最左侧]值,因此您的函数需要在循环之前保存它:

char *
strconcat(char *user2p, char *user1p)
{
    char *orig2p = user2p;

    while (*user2p) {
        user2p++;
    }
    while (*user1p) {
        *user2p = *user1p;
        user2p++;
        user1p++;
    }
    *user2p = '\0';

    printf("test: %s\n", orig2p);

    return orig2p;
}

更新:

要为concat功能提供完全防弹的测试程序,我们可以使用[过大]输入缓冲区并将输入长度限制为最大目标缓冲区的1/2。

gets 剥离换行符,但fgets不是。因此,我创建了一个xgets函数,该函数与gets类似,但是使用了fgetsstrchr来获得[几乎]相同的效果。

尽管我认为可以将标准字符串函数用作 test 代码的一部分,但我已经创建了strchr的手工编码版本[希望这不是您的下一个作业:- )]。

无论如何,这是完整的程序:

#include <stdio.h>

char *
strconcat(char *user2p, char *user1p)
{
    char *orig2p = user2p;

    while (*user2p) {
        user2p++;
    }
    while (*user1p) {
        *user2p = *user1p;
        *user2p++;
        *user1p++;
    }
    *user2p = '\0';

    printf("test: %s\n", orig2p);

    return orig2p;
}

char *
xstrchr(char *buf,int chrwant)
{
    int chrcur;
    char *res = NULL;

    for (chrcur = *buf++;  chrcur != 0;  chrcur = *buf++) {
        if (chrcur == chrwant) {
            res = buf - 1;
            break;
        }
    }

    return res;
}

char *
xgets(char *buf,int maxlen)
{
    char *cp;
    char *res;

    res = fgets(buf,maxlen,stdin);

    if (res != NULL) {
        cp = xstrchr(buf,'\n');
        if (cp != NULL)
            *cp = 0;
    }

    return res;
}

#define MAXLEN      800

int
main(void)
{
    char userString1[MAXLEN], userString2[MAXLEN + 1];
    char *user1p, *user2p;

    printf("Please enter the first string: ");
    user1p = xgets(userString1,MAXLEN / 2);

    printf("Please enter the second string: ");
    user2p = xgets(userString2,MAXLEN / 2);

    if ((user2p != NULL) && (user1p != NULL))
        printf("String 2 after concatenation: %s\n",strconcat(user2p, user1p));

    return 0;
}

答案 1 :(得分:2)

有很多问题。首先是这个。

while (*user1p) {
    *user2p = *user1p;
    *user2p++;
    *user1p++;
}

这是偶然的。如果您有编译器警告,则应该得到警告...

test.c:13:9: warning: expression result unused [-Wunused-value]
        *user2p++;
        ^~~~~
test.c:14:9: warning: expression result unused [-Wunused-value]
        *user1p++;
        ^~~~~~~

未使用它的原因是因为C像这样解释它:

*(user1p++)

增加指针,然后取消引用。您只想增加指针,而无需取消引用。

while (*user1p) {
    *user2p = *user1p;
    user2p++;
    user1p++;
}

然后在这里。

printf("String 2 after concatenation: %c\n", strconcat(user2p, user1p));

%c打印单个char。您需要%s来打印char *。这表明您签名错误。 strconcat应该返回一个char *(即C用于字符串)并返回user2p(一个char *)。

char *strconcat(char *orig_to, const char *from) {
    ...

    return user2p;
}

由于您没有更改from,因此应该const char *让编译器知道并在编译器意外更改时发出警告。


最后,当您返回*user2p时,它已经被移到了字符串的末尾。

while (*user1p) {
    *user2p = *user1p;
    user2p++;
    user1p++;
}
*user2p = '\0';

printf("test: %c", *user2p);

// This points to the null byte just set above
return user2p;

因此,打印strconcat的结果将不打印任何内容。要解决此问题,请将原始指针存储为user2p并返回。

char *strconcat(char *orig_to, const char *from) {
    char *orig_user2p = user2p;

    ...

    return orig_user2p;
}

一些技巧。使用具有良好变量名的代码来描述它们的工作更加容易。

char *strconcat(char *orig_to, const char *from) {
    char *to = orig_to;
    ...
}

char foo[NN]已经使foo成为指针。无需声明单独的char *变量并复制指针。

char from[21], to[21];

请勿使用gets。它可以使用多少内存没有限制,并且很容易使缓冲区溢出。使用fgets可以限制可以读取到可用内存的数量。

printf("Please enter the string to concat from: ");
fgets(from, sizeof(from), stdin);

尽管保留了换行符很烦人,但没有简单的功能来剥离它。您可以使用scanf来删除空格,但是使用beware its many pitfalls

printf("Please enter the string to concat from: ");
scanf("%20s", from);

printf("Please enter the string to concat to: ");
scanf("%20s", to);

最后,请确保要连接的字符串可以包含其自己的内容和新内容。

char from[21], to[41];

printf("Please enter the string to concat to: ");
// Be sure to leave enough room in `to` to fit `from`.
fgets(to, sizeof(to) - sizeof(from), stdin);

答案 2 :(得分:0)

我会创建一个更加动态的内存模型。这段代码更加通用,将字符串连接在一起,创建一个包含两个字符串的新字符串。完成后免费:-)...

char *strconcat(char *string1, char *string2) {
    int lenStr1=0,lenStr2=0;
    char *tmpStr1=string1,*tmpStr2=string2,*returnStr;
    while (*tmpStr1++)lenStr1++;
    while (*tmpStr2++)lenStr2++;
    if((returnStr=(char *)malloc(lenStr1+lenStr2+1))){
        memcpy(returnStr,string1,lenStr1);
        memcpy(&returnStr[lenStr1],string2,lenStr2);
        returnStr[lenStr1+lenStr2]=0;
        return returnStr;
    } else {
        return 0;
    }
}

int main() {
    char *string1="String 1 ",*string2="String 2 ",*result;
    if((result=strconcat(string1, string2))) {
        printf("-> %s \n",result);
        free(result);
    } else {
        printf("Out of memory");
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}