Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 连接C+中的字符串时出错+;_C++_String - Fatal编程技术网

C++ 连接C+中的字符串时出错+;

C++ 连接C+中的字符串时出错+;,c++,string,C++,String,我试图将数组中包含的所有字符串合并到一个字符串中,因此我产生了以下代码: #include <string.h> #include <stdlib.h> #include <stdio.h> char *join_strings(const char *array[]) { int n_array (sizeof (array) / sizeof (const char *)); int i; int total_length;

我试图将数组中包含的所有字符串合并到一个字符串中,因此我产生了以下代码:

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

char *join_strings(const char *array[])
{
    int n_array (sizeof (array) / sizeof (const char *));

    int i;
    int total_length;
    char *joined;
    char *end;
    int *lengths;

    lengths = (int *)malloc (n_array * sizeof (int));
    if (!lengths) {
        fprintf (stderr, "Malloc failed.\n");
        exit (EXIT_FAILURE);
    }

    total_length = 0;

    for (i = 0; i < n_array; i++) {
        lengths[i] = strlen (array[i]);
        total_length += lengths[i];
    }

    joined = (char *)malloc(total_length + 1);

    if (!joined) {
        fprintf (stderr, "Malloc failed.\n");
        exit (EXIT_FAILURE);
    }

    end = joined;

    for (i = 0; i < n_array; i++) {
        int j;
        for (j = 0; j < lengths[i]; j++) {
            end[j] = array[i][j];
        }
        end += lengths[i];
    }
    end[total_length] = '\0';

    char *result = joined;

    free (lengths);
    free (joined);

    return result;
}

int main()
{
    const char *lol0 = "First";
    const char *lol1 = "Second";
    const char *fullString[] = { lol0, lol1 };
    const char *joined = join_strings(fullString);

    puts(joined);

    return 0;
}
#包括
#包括
#包括
字符*连接字符串(常量字符*数组[])
{
int n_数组(sizeof(array)/sizeof(const char*);
int i;
int总长度;
字符*已加入;
字符*结束;
整数*长度;
长度=(int*)malloc(n_数组*sizeof(int));
如果(!长度){
fprintf(stderr,“Malloc失败。\n”);
退出(退出失败);
}
总长度=0;
对于(i=0;i
但由于某些原因,它只输出“First”,不知道问题可能是:/ 提前谢谢

sizeof(array)
等于
sizeof(const char**)
并且
n\u array
计算不准确。
您必须将数组的长度作为参数传递

还有一个错误。你不能做
免费(加入)在函数
连接字符串中,因为缓冲区仍在使用

固定代码:

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

char *join_strings(const char *array[], int n_array)
{

    int i;
    int total_length;
    char *joined;
    char *end;
    int *lengths;

    lengths = malloc (n_array * sizeof (int));
    if (!lengths) {
        fprintf (stderr, "Malloc failed.\n");
        exit (EXIT_FAILURE);
    }

    total_length = 0;

    for (i = 0; i < n_array; i++) {
        lengths[i] = strlen (array[i]);
        total_length += lengths[i];
    }

    joined = malloc(total_length + 1);

    if (!joined) {
        fprintf (stderr, "Malloc failed.\n");
        exit (EXIT_FAILURE);
    }

    end = joined;

    for (i = 0; i < n_array; i++) {
        int j;
        for (j = 0; j < lengths[i]; j++) {
            end[j] = array[i][j];
        }
        end += lengths[i];
    }
    end[total_length] = '\0';

    char *result = joined;

    free (lengths);

    return result;
}

int main()
{
    const char *lol0 = "First";
    const char *lol1 = "Second";
    const char *fullString[] = { lol0, lol1 };
    char *joined = join_strings(fullString, 2);

    puts(joined);
    free(joined);

    return 0;
}
#包括
#包括
#包括
字符*连接字符串(常量字符*数组[],整数n_数组)
{
int i;
int总长度;
字符*已加入;
字符*结束;
整数*长度;
长度=malloc(n_数组*sizeof(int));
如果(!长度){
fprintf(stderr,“Malloc失败。\n”);
退出(退出失败);
}
总长度=0;
对于(i=0;i
注:


    这个代码是C,不是C++。我删除了
    malloc
    返回值的强制转换,这在这个网站上似乎很讨厌。这将导致C++中的编译错误。
  • 要释放缓冲区,在
    main
    函数中加入的
    类型不应为
    const char*
    。gcc对此提出了警告

很难绝对确定,但从性能角度看,知道长度的好处可能比仅为保存字符串长度而分配堆内存的成本要小

因此,为了好玩,让我们不用额外的长度缓冲:

char * join_strings(const char *array, size_t array_len)
{
  size_t out_len;

  for(size_t i = out_len = 0; i < array_len; ++i)
    out_len += strlen(array[i]);

  char *out = malloc(out_len + 1);
  if(out != NULL)
  {
    char *put = out;
    for(size_t i = 0; i < array_len; ++i)
    {
      for(const char *src = array[i]; *src;)
        *put++ = *src++;
    }
    *put = '\0';
  }
  return out;
}
char*连接字符串(常量char*数组,大小数组)
{
大小不一致;
对于(大小i=out\u len=0;i
顺便说一下,上面是C99。我删除了错误消息,返回
NULL
可能就足够了。它没有经过测试,但不应该离正确性太远。:)


基本上,我的观点是,有时较短的代码更容易使用。

正如MikeCAT所指出的,下面的代码并没有达到您认为的效果。。。但是为什么呢

您正在将
*fullString[]
传递给您的
join\u strings
函数,但是
join\u strings
得到的实际上是
**fullString
,因为指针衰减。每当您将数组传递给函数(例如
a[]
)时,它将衰减为指针(例如
*a
)。指针数组也是如此

这正是您看到
main
函数语法的原因:

int main (int argc, char *argv[])

事实上,main接收的是第二种情况,但允许的语法是。因此,当您将
*fullString[]
传递给
join\u strings
函数时,指针衰减确保
join\u strings
接收
**fullString
。这使得:

有效地
int n_数组8/8
1
sizeof array/sizeof*array
仅在声明和定义
array
的范围内工作。一旦您将其传递给另一个函数,指针衰减将使其不正确

然而,您的代码离此并不遥远。需要进行一些更改,但除了需要学习这一点之外,您已经接近一个工作字符串连接:

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

char *join_strings (const char **array, size_t n_array)
{
    // int n_array (sizeof (array) / sizeof (const char *));

    size_t i;
    size_t total_length;
    char *joined;
    char *end;
    size_t *lengths;

    // lengths = (int *) malloc (n_array * sizeof (int));
    lengths = malloc (n_array * sizeof *lengths);
    if (!lengths) {
        fprintf (stderr, "Malloc failed.\n");
        exit (EXIT_FAILURE);
    }

    total_length = 0;

    for (i = 0; i < n_array; i++) {
        lengths[i] = strlen (array[i]);
        total_length += lengths[i];
    }

    joined = malloc (total_length + 1);

    if (!joined) {
        fprintf (stderr, "Malloc failed.\n");
        exit (EXIT_FAILURE);
    }

    end = joined;

    for (i = 0; i < n_array; i++) {
        size_t j;
        for (j = 0; j < lengths[i]; j++) {
            end[j] = array[i][j];
        }
        end += lengths[i];
    }
    // end[total_length] = '\0';   /* ALWAYS run valgrind (Note3) */
    joined[total_length] = '\0';

    // char *result = joined;

    free (lengths);
    // free (joined);

    return joined;
}

int main ()
{
    const char *lol0 = "First";
    const char *lol1 = "Second";
    const char *fullString[] = { lol0, lol1 };
/*const */char *joined = join_strings (fullString, sizeof fullString/sizeof *fullString);

    puts (joined);
    free (joined);

    return 0;
}
它不仅检查您的分配和释放,还检查您是否尝试访问分配块之外的内存。(如果在启用符号的情况下编译
-g
valgrind将显示与错误相关的行号)此处valgrind显示:

==27700== Invalid write of size 1
==27700==    at 0x40090E: join_strings (ptrdecay.c:45)
==27700==    by 0x400960: main (ptrdecay.c:60)
==27700==  Address 0x51e00a6 is 10 bytes after a block of size 12 alloc'd
==27700==    at 0x4C29964: calloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==27700==    by 0x400838: join_strings (ptrdecay.c:29)
==27700==    by 0x400960: main (ptrdecay.c:60)
嗯?仔细观察您试图以空终止
end
的方式。当时
end
的值是多少?
在哪里结束[总长度]
(或等效写入的
*
    int n_array (sizeof (array) / sizeof (const char *));
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

char *join_strings (const char **array, size_t n_array)
{
    // int n_array (sizeof (array) / sizeof (const char *));

    size_t i;
    size_t total_length;
    char *joined;
    char *end;
    size_t *lengths;

    // lengths = (int *) malloc (n_array * sizeof (int));
    lengths = malloc (n_array * sizeof *lengths);
    if (!lengths) {
        fprintf (stderr, "Malloc failed.\n");
        exit (EXIT_FAILURE);
    }

    total_length = 0;

    for (i = 0; i < n_array; i++) {
        lengths[i] = strlen (array[i]);
        total_length += lengths[i];
    }

    joined = malloc (total_length + 1);

    if (!joined) {
        fprintf (stderr, "Malloc failed.\n");
        exit (EXIT_FAILURE);
    }

    end = joined;

    for (i = 0; i < n_array; i++) {
        size_t j;
        for (j = 0; j < lengths[i]; j++) {
            end[j] = array[i][j];
        }
        end += lengths[i];
    }
    // end[total_length] = '\0';   /* ALWAYS run valgrind (Note3) */
    joined[total_length] = '\0';

    // char *result = joined;

    free (lengths);
    // free (joined);

    return joined;
}

int main ()
{
    const char *lol0 = "First";
    const char *lol1 = "Second";
    const char *fullString[] = { lol0, lol1 };
/*const */char *joined = join_strings (fullString, sizeof fullString/sizeof *fullString);

    puts (joined);
    free (joined);

    return 0;
}
valgrind ./myprogname
==27700== Invalid write of size 1
==27700==    at 0x40090E: join_strings (ptrdecay.c:45)
==27700==    by 0x400960: main (ptrdecay.c:60)
==27700==  Address 0x51e00a6 is 10 bytes after a block of size 12 alloc'd
==27700==    at 0x4C29964: calloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==27700==    by 0x400838: join_strings (ptrdecay.c:29)
==27700==    by 0x400960: main (ptrdecay.c:60)
==27700==  Address 0x51e00a6 is 10 bytes after a block of size 12 alloc'd
==27647== Conditional jump or move depends on uninitialised value(s)
==27647==    at 0x4C2ACF8: strlen (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==27647==    by 0x4E9DE2B: puts (in /lib64/libc-2.18.so)
==27647==    by 0x40092B: main (ptrdecay.c:62)
    joined = calloc (1, total_length + 1);
$ valgrind ./bin/ptrdecay
==27821== Memcheck, a memory error detector
==27821== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==27821== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==27821== Command: ./bin/ptrdecay
==27821==
FirstSecond
==27821==
==27821== HEAP SUMMARY:
==27821==     in use at exit: 0 bytes in 0 blocks
==27821==   total heap usage: 2 allocs, 2 frees, 28 bytes allocated
==27821==
==27821== All heap blocks were freed -- no leaks are possible
==27821==
==27821== For counts of detected and suppressed errors, rerun with: -v
==27821== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)
template <size_t n_array>
char *join_strings(const char *(&array)[n_array])
{
    // other ghastly code omitted for aesthetic reasons
}
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
#include <sstream>
#include <vector>

template <typename InputIterator>
std::string join_strings(InputIterator begin, InputIterator end) {
    std::ostringstream os;
    std::copy(begin, end, std::ostream_iterator<std::string>(os));
    return os.str();
}

int main() {
    std::vector<std::string> arr = {"First","Second"};
    std::string joined = join_strings(begin(arr), end(arr));
    std::cout << joined << '\n';
}