如何在C中使用strcat连接char指针?

时间:2019-03-11 06:20:30

标签: c pointers buffer

我正在使用Linux在C语言中学习指针。我正在尝试使用 strcat 函数,但是它不起作用,我也不明白为什么。

我要将用户名传递给main作为参数,因为我需要连接并在此用户名的第一个位置放置数字1。例如,如果我以参数 username123 作为参数,则需要将其转换为 1username123

我得到了以下代码:

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

int main(int argc, char *arg[]){
    const char *userTemp;
    char *finalUser;

    userTemp = argv[1]; //I got the argument passed from terminal
    finalUser = "1";
    strcat(finalUser, userTemp); //To concatenate userTemp to finalUser
    printf("User: %s\n",finalUser);

    return 0;
}

代码可以编译,但是出现了段错误错误并且不知道为什么。您能帮我朝正确的方向走吗?

5 个答案:

答案 0 :(得分:2)

  

我正在尝试使用strcat函数,但是它不起作用,我也不明白为什么。

对于初学者来说,您确实shouldn't use strcat()。请改用strlcat()。该函数和其他函数的“ l”版本带有一个额外的参数,可让您告诉函数目标缓冲区有多大,从而使函数可以避免写入缓冲区的末尾。 strcat()没有该参数,因此它取决于您确保缓冲区足够大以包含两个字符串。这是C代码中常见的安全问题来源。 “ l”版本还可以确保生成的字符串以null结尾。

  

代码可以编译,但是出现了段错误,并且不知道为什么。

以下是该函数的原型:char *strcat( char *dest, const char *src );

现在,您基本上这样称呼:strcat("1", someString);。也就是说,您正在尝试将someString追加到"1",这是一个字符串常量。 "1"中的任何字符串都没有多余的空间,而且someString中没有任何多余的空间,并且由于您使用的函数会愉快地写入目标缓冲区的末尾,因此您的代码可以有效地覆盖在内存中该字符串常量旁边。

要解决此问题,您应该:

  1. 切换到strlcat()
  2. 使用malloc()或其他某种方式来分配足够容纳两个字符串的目标缓冲区。

答案 1 :(得分:2)

尝试修改字符串文字(例如"1")在C中是未定义的行为。通常,这些内容存储在不可修改的内存中,以便进行某些优化。

让我们暂时将整个程序替换为:

#include <stdio.h>
int main(int argc, char *argv[]){
    printf("User: 1%s\n", (argc > 1) ? argv[1] : "");
    return 0;
}

确保有足够空间的方法是创建一个足以容纳您想做的事的缓冲区。例如:

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

int main(int argc, char *argv[]){
    // Check args provded.

    if (argc < 2) {
        puts("User: 1");
        return 0;
    }

    // Allocate enough memory ('1' + arg + '\0') and check it worked.

    char *buff = malloc(strlen(argv[1]) + 2); 
    if (buff == NULL) {
        fprintf(stderr, "No memory\n");
        return 1;
    }

    // Place data into memory and print.

    strcpy(buff, "1");
    strcat(buff, argv[1]);
    printf("User: %s\n", buff);

    // Free memory and return.

    free(buff);
    return 0;
}

不应该要做的是分配一个固定大小的缓冲区,并盲目复制用户提供的数据。这就是人们通过覆盖意外数据的缓冲区而导致绝大多数安全问题的原因。

答案 2 :(得分:-1)

您缺少有关C的一些基本知识。

finalUser = "1";

这是在“只读”内存中创建的。您不能对此进行更改。 strcat的第一个参数要求为突变分配的内存例如

char finalUser[32];
finalUser[0] = '1';

答案 3 :(得分:-1)

与其他语言不同,C语言中没有真正的字符串类型。

您想要这个:

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

int main(int argc, char *arg[]){
    const char *userTemp;
    char finalUser[100];   // finalUser can contain at most 99 characters

    userTemp = argv[1]; //I got the argument passed from terminal
    strcpy(finalUser, "1");    // copy "1" into the finalUser buffer
    strcat(finalUser, userTemp); //To concatenate userTemp to finalUser
    printf("User: %s\n",finalUser);

    return 0;
}

或更简单:

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

int main(int argc, char *arg[]){
    char finalUser[100];   // finalUser can contain at most 99 characters
    strcpy(finalUser, "1");    // copy "1" into the finalUser buffer
    strcat(finalUser, argv[1]); //To concatenate argv[1] to finalUser
    printf("User: %s\n",finalUser);    
    return 0;
}

免责声明:为简洁起见,此代码包含固定大小的缓冲区,此处不检查缓冲区是否溢出。

C课本中有关字符串的章节应对此进行介绍。

顺便说一句,您还应该检查程序是否通过参数调用:

int main(int argc, char *arg[]){
  if (argc != 2)
  {
     printf("you need to provide a command line argument\n");
     return 1;
  }
  ...

答案 4 :(得分:-1)

因为您没有为目标字符串分配足够的内存。因此,您需要静态或动态分配足够的内存。

通常:

char finalUser[YOUR_REQUIRED_SIZE];

动态地:

char *finalUser = malloc(YOUR_REQUIRED_SIZE);