(编辑)
从 C 中的函数更新和返回字符串时可能存在的误解
我是一名学生,刚刚开始尝试动态内存分配技术。最近,我被告知要在
它应该有两个参数:char c1[],char c2[]。 暂时,我关注一个约束,其中字符串 c1 的长度小于字符串 c2。在这种情况下,我们会将一个较大的字符串复制到一个较小的字符串中。因此,自然而然地,它必须扩大前一个字符串的大小。 (我定义了一个返回字符串长度的函数 len()。它工作正常)
代码:
char* copy(char c1[],char c2[])
{
int i=0;
int lc1=len(c1);
int lc2=len(c2);
if(lc1<lc2)
{
//are the following two lines allowed?
c1=(char*) malloc(lc1*sizeof(char));
c1=(char*) realloc(c1,lc2*sizeof(char));
for(i=0;i<lc2;i++)
{
*(c1+i)=c2[i];
}
*(c1+lc2)='\0';
}
return c1;
}
*如果此代码有多个问题,我不会感到惊讶! * 我试过如下测试:
#include <stdio.h>
#include <string.h>
#include "mystring.h"
main()
{
int i;
char s1[12],s2[12];
gets(s1);
gets(s2);
printf("copy: %s",copy(s1,s2));
printf("\ns1: %s",s1);
}
我希望两个输出相同,即副本和 s1。碰巧只有当我将它与调用一起打印时,它才会起作用。当我打印 s1 时,我期待它打印副本。
我哪里做错了?我认为这与我正在处理的变量的范围有关,或者与整个指针和内存分配有关!
编辑: 我做了一个替代函数 xcopy:
char* xcopy(char c1[])
{
int i=0;
int lc1=len(c1);
char* c2=(char*) malloc((lc1+1)*sizeof(char));
for(i=0;i<lc1;i++)
{
*(c2+i)=c1[i];
}
*(c2+lc1)='\0';
return c2;
}
我意识到这个功能并没有解决实际问题。
谢谢你的帮助!
函数
copy
没有意义。
对于初学者来说,参数
c1
指向的数组不一定包含字符串。所以这条线
int lc1=len(c1);
调用未定义的行为。
即使指针
c1
指向的数组包含一个字符串,存储的字符串也可能比数组的大小小得多。所以又是这条线
int lc1=len(c1);
使用以下 if 语句
if(lc1<lc2)
没有意义。
同样分配内存两次
c1=(char*) malloc(lc1*sizeof(char));
c1=(char*) realloc(c1,lc2*sizeof(char));
不安全、多余且效率低下。
实际上函数并没有复制目标数组中指针
c2
所指向的字符串。因此再次使用参数c1
没有意义。你的函数看起来像 POSIX 函数strdup
如果要删除第一个无意义的参数。
您没有显示函数
len
如何计算字符串的长度,但它似乎不计算字符串的终止零字符。在这种情况下,您至少需要使用表达式 ( lc2 + 1 ) * sizeof( char )
分配内存,为终止零字符 '\0'
保留内存。否则这个声明
*(c1+lc2)='\0';
调用未定义的行为。
函数的用户有责任提供一个足够大的目标数组来存储源字符串。该函数不应分配任何内存。
类比标准C函数
strcpy
函数可以看成下面的样子
char * copy( char s1[], const char s2[] )
{
for ( char *p = s1; ( *p++ = *s2++ ) != '\0'; );
return s1;
}
注意函数
gets
不安全,C标准不支持。而是使用标准 C 函数fgets
。它可以附加一个带有换行符的字符串'\n'
.
要删除它,您可以编写例如
c2[ strcspn( c2, "\n" ) ] = '\0';
#include <stdio.h>
#include <string.h>
/* headers.h
#define SLEN 100
#define SLENT 200
typedef struct size {
size_t length_one[SLEN];
size_t length_two[SLENT];
} siz, *siz_point;
char * copy(char var1[], char var2[])
{
struct size siz;
int i = 0;
siz.length_one = strlen(var1);
siz.length_two = strlen(var2);
if (siz.length_one < siz.length_two) {
void vars_one = (char *) malloc(siz.length_one * sizeof(siz.length_one));
void vars_two = (char *) memcpy(siz.length_one, siz.length_two, size_t memory);
for (i=0; i < siz.length_two; i++) {
*(var1+i) = var2[i];
}
*(var1 + siz.length_two) = '\0';
}
return var1;
}
*/
#define LEN 20
char * s_gets(char * set_string, size_t isize_n);
char * s_gets(char * set_string, size_t isize_n) {
char * retnval;
char * findval;
retnval = fgets(set_string, isize_n, stdin);
if (retnval) {
findval = strchr(set_string, '\n');
if (findval) *findval = '\0';
else
while (getchar() != '\n')
continue;
}
return retnval;
}
int
main() {
int i;
char string_one[LEN];
char string_two[LEN];
s_gets(string_one, "This string one");
s_gets(string_two, "This string two");
printf("Copying string: %s", copy(string_one, string_two));
printf("\nString: %s", string_one);
}
也许你的代码看起来像这样
您提供的代码存在以下问题:
c2
到c1
的字符没有被正确复制。您正在迭代循环直到 lc2
,但是由于您是从 c2
复制到 c1
,所以您应该只迭代 lc1
。您还应该复制每行结尾的空字符。\0
的末尾添加一个空字符 c1
。更正代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int len(char str[])
{
int i = 0;
while(str[i] != '\0')
{
i++;
}
return i;
}
char* copy(char c1[], char c2[])
{
int i = 0;
int lc1 = len(c1);
int lc2 = len(c2);
// Allocate memory for c1 if its length is less than c2's length
if (lc1 < lc2)
{
// Allocate memory for c1 using malloc
char* temp = (char*) malloc(lc2 * sizeof(char));
if (temp == NULL)
{
printf("Memory allocation failed");
exit(1);
}
// Copy the contents of c2 to temp
for (i = 0; i < lc2; i++)
{
*(temp + i) = c2[i];
}
// Add null terminator
*(temp + lc2) = '\0';
// Free memory allocated to c1
free(c1);
// Return the pointer to the newly allocated memory block
return temp;
}
else
{
// If c1 is already big enough to hold the contents of c2, just copy the contents and return c1
for (i = 0; i < lc2; i++)
{
*(c1 + i) = c2[i];
}
// Add null terminator
*(c1 + lc2) = '\0';
// Return the original pointer to c1
return c1;
}
}
int main()
{
char s1[12], s2[12];
printf("Enter string s1: ");
fgets(s1, sizeof(s1), stdin);
printf("Enter string s2: ");
fgets(s2, sizeof(s2), stdin);
// Remove newline character from input strings
s1[strcspn(s1, "\n")] = '\0';
s2[strcspn(s2, "\n")] = '\0';
// Call the copy function and print the results
char* result = copy(s1, s2);
printf("Result: %s\n", result);
free(result);
return 0;
}