我想在C中创建一个简单的str_join
函数(以学习更多关于指针和数组的内容),它实际上将两个字符串连接在一起。
#include <stdio.h>
#include <stdlib.h>
int str_size(char *str);
void str_join(char *str1, char *str2);
int main(int argc, char **argv)
{
char *part1 = "Hello ";
char *part2 = "World!";
str_join(part1, part2);
printf("%s\n", part1);
return 0;
}
int str_size(char *str)
{
char c;
for(int i = 0;; i++)
{
c = str[i];
if(c == '\0')
return i + 1;
}
}
void str_join(char *str1, char *str2)
{
int str_size_1 = str_size(str1) - 1; //Last char is '\0', don't need them 2 times
int str_size_2 = str_size(str2);
char str3[str_size_1 + str_size_2];
int i;
for(i = 0; i < str_size_1; i++)
str3[i] = str1[i];
for(i = 0; i < str_size_2; i++)
str3[i + str_size_1] = str2[i];
str1 = (char *)str3;
}
看起来很简单(也许太简单了)。 我将输出除外:
Hello World
但看起来像是:
Hello
我使用以下命令编译程序:
gcc main.c -o main
然后跑了:
./main
我没有看到我的失败,有人能指出我的错误吗? 谢谢你帮助我!
答案 0 :(得分:1)
在C中,函数参数按值传递。对函数内部的任何参数所做的任何更改都不会反映给调用者(实际参数)。
因此,在您的情况下,str1 = (char *)str3;
并不符合您的想法。
那说,等等,停! str3
是VLA,生命周期是块范围。您不可能返回第一个元素的地址,并期望在访问内存位置的范围之外有效。您需要以超出其范围的方式分配内存。您必须
static
存储的数组(不能与VLA结合使用)答案 1 :(得分:0)
您没有返回您认为从函数返回的指针。
str1 = (char *)str3;
您似乎认为这会更改str1
,以便它指向(正确)连接的字符串str3
,但此更改在函数外部不可见。
您可以(至少)以两种方式解决此问题:
1)与malloc
char *str3 = malloc(str_size_1 + str_size_2);
然后从函数返回此指针(而不是void)
或2)
将指针传递给指向函数的指针,就像这个
一样void str_join(char **str1, char *str2)
然后
*str1 = str3;
答案 2 :(得分:0)
您希望实现的目标是在函数调用方法的引用调用方法的帮助下完成的。但是在您的代码中,str_join
是一个按函数调用的函数。当您更改str1
的值时,它仅针对函数的范围进行更改。因为,当您从str_join
范围退出时,str1
的值再次更改为较早的值,因为您传递给函数的内容不是str1
的地址,而是str1
值的副本。你应该试试这个:
void str_join(char **str1, char **str2)
// though the str2 need not to be passed by reference you can leave it as it is now
用str1
*str1
然后您可以在主要功能中将其称为:str_join(&str1, &str2)
&
符号表示您传递的地址为str1
和str2
答案 3 :(得分:0)
我确信有很多方法可以实现此处所需的内容。在C语言中,一种合理的惯用方法是创建一个新的动态分配字符串,其大小足以容纳原始字符串,并将其返回给调用者。
var filteredRecords = originalRecords.GroupBy(x => new
{
ContractReference = x.Fields[nameof(FieldName.CRFS.ContractReference)],
ActionDate = x.Fields[nameof(FieldName.CRFS.ActionDate)],
Amount = x.Fields[nameof(FieldName.CRFS.Amount)],
CycleDate = x.Fields[nameof(FieldName.CRFS.CycleDate)]
});
调用者必须在结果上调用free()。通常的做法是假设任何返回“char *”的函数返回必须释放的东西,而返回“const char *”的函数返回不需要释放的东西。但是,C标准库中的许多基本的,长期存在的函数都不遵循此约定。