我有一个函数需要一个char指针,就像这个:
void func(char *string);
我希望以这种方式更改传递的char数组:
func(“用户”) - >你好,用户!
解决此任务的更好方法是什么?
选项#1; - >使用其他字符数组 - > temp(将被声明一次)
void func(char *string, char *temp){
sprintf(temp, "Hello, %s!", string);
}
并在临时使用后
选项#2; - >使用temp作为局部变量(应该每次在函数体中声明)
void func(char *string){
char temp[512];
sprintf(temp, "Hello, %s!", string);
sprintf(string, "%s", temp);
// or strcpy(string, temp); string[strlen(temp)]=0;
}
问题是经常调用函数。第二种选择是否会显着降低性能?还有其他选择可以解决这个问题吗?
答案 0 :(得分:2)
第一种选择是两者中较好的选择。如果与字符串文字一起使用,第二个将调用未定义的行为,因为您无法覆盖它们。当然,无论如何它都没有任何意义,你期望如何改变被覆盖的文字?
当然,对于输入字符串,缓冲区溢出保护和正确const
会更好:
void func(const char *string, char *out, size_t out_max)
{
snprintf(out, out_max, "Hello, %s!", string);
}
到目前为止,大多数系统都应该有snprintf()
。
答案 1 :(得分:0)
另一种方式是:
获取大小为"Hello! User" + 1
的字符串,并使用"Hello! "
char string[20] = "Hello! ";
(让)
然后每次都在string + 7
处输入。 (7
的长度为"Hello! "
)
scanf("%s", string + 7);
如果您想在此之后的任何时间使用"User"
字符串,那么string + 7
将始终指向它。
答案 2 :(得分:0)
性能没有太大差别,部分原因是因为它是一个小函数,并且因为编译器知道如何优化这些类型的东西,一般来说最好的做法是声明它一次。由于您不知道用户名将需要多长时间,因此您必须进行一些内存分配。我建议做这样的事情:
void func(char* name) {
char* hello = "Hello! ";
//allocate memory for the whole string
char* tmp = (char*)malloc(sizeof(char)*(strlen(name)+strlen(hello)+1));
//construct the string
strcpy(tmp, hello);
strcat(tmp, name);
//print it
printf("%s\n", tmp);
//discard of the space you used
free(tmp);
}
这样你就可以确保你有足够的内存和性能,我认为printf是那里最慢的操作。
答案 3 :(得分:0)
你已经有几个选择;但既然你说你真的想要最高性能的解决方案,也许以下是有用的 - 你创建一个不断重复使用的单个函数(而不是硬编码模板字符串,你传递它;这样你只有一个这样的功能,而不是每个可能输出的一个功能)。我很确定带有snprintf
参数的%s
函数在一个不太合适的编译器上执行类似于memcpy
的操作,所以这应该尽可能高效。无论如何,产生输出到屏幕的工作远远慢于生成字符串的工作。请记住,从长远来看,易于维护的代码将始终是正确的选择。
有两种方法可以做到这一点 - 你可以像这样创建一个实际的函数:
void create_output(char* subThis, char* intoThis, char* outputThat, int n){
snprintf(outputThat, n, intoThis, subThis);
}
或者您可以使用#define
将一个名称别名替换为另一个名称。这样做的好处是,您可以在封面下使用snprintf
时使用更自然的参数顺序:
#include <stdio.h>
#define MAX_OUT 100
#define create_output(a,b,c,d) snprintf((c),(d),(b),(a))
//void create_output(char* subThis, char* intoThis, char* outputThat, int n)
int main(void) {
char username[]="Fred";
char template[]="Hello %s";
char output[MAX_OUT];
create_output(username, template, output, MAX_OUT);
// and show that it works:
printf("%s\n", output);
}
如果保持输出缓冲区始终可用于此目的,您甚至可以简化用户的生活:在下面,#define
使用逗号运算符执行snprintf
函数但返回指向结果的指针OUTPUT
- 这是一个只定义一次的全局范围的缓冲区。这可能看起来有点像黑客,但它以尽可能高效和灵活的方式生成您要求的功能(最小的开销 - 很多工作在编译时完成)。
#include <stdio.h>
#define MAX_OUT 100
char OUTPUT[MAX_OUT];
#define create_output(a,b) (snprintf(OUTPUT,MAX_OUT,(b),(a)), OUTPUT)
// apparent prototype:
// char* create_output(char* subThis, char* intoThis)
// it returns a pointer to the location where the string is stored
int main(void) {
char username[]="Fred";
char template[]="Hello %s";
char *output;
output = create_output(username, template);
// and show that it works:
printf("%s\n", output);
}
答案 4 :(得分:0)
void func(const char *string, char *outbuff){
const char *p = "Hello, ";
while(*p)
*outbuff++ = *p++;
p = string;
while(*p)
*outbuff++ = *p++;
p = "!";
while(*outbuff++ = *p++);
}