在没有 strcat 的情况下连接两个字符串
concatenate two strings without strcat
我想在不使用 strcat() 的情况下连接两个字符串 function.But 我没有得到所需的结果。请指出我的错误。
void main() {
char s1[100], s2[100];
int i;
puts("First string?");
gets(s1);
puts("Second string?");
gets(s2);
for (i = strlen(s1); i <= (strlen(s1) + strlen(s2)); i++) {
s1[i] = s2[i - strlen(s1)];
}
puts(s1);
}
使用 sprintf 的变体:
更简单
char buf[200];
sprintf(buf, "%s%s" s1, s2);
更简单并且更安全
char buf[200]
snprintf(buf, sizeof(buf), "%s%s", s1, s2);//prevents buffer overflow
或者,修改您的循环(请参阅行注释了解原因):
int main(void)//note changed main prototype
{
char s1[100], s2[100];//caution here: s1 must be big enough
//to contain its string as well as
//the string stored in s2, plus 1 for NULL
int i;
int len1, len2;//create variables to store string lengths
puts("First string?");
gets(s1);//note, gets is no longer recommended
puts("Second string?");
gets(s2);
len1 = strlen(s1);//store string lengths only once
len2 = strlen(s2);//to avoid calling them repeatedly in loop
for(i = 0; i < len2; i++)//index i in one place only
{
s1[len1+i] = s2[i];
}
s1[len1 + i]=0;//null terminate string when done.
puts(s1);
getchar();//added to pause execution in my environment.
return 0;
}
此处显示了使用上述修改的示例会话:
您的解决方案不起作用,因为您在每次迭代时重新计算 strlen(s1)
以测试是否完成并计算 s2
中的偏移量以从中复制一个字符,但您修改了 s1
在循环中,因此长度发生变化,更糟糕的是,s1
暂时不再 '[=15=]'
终止:测试表达式 i <= strlen(s1) + strlen(s2)
调用未定义的行为,当您复制 s2[i - strlen(s1)]
第二次循环。
使用这些想法来更正您的代码:
不要使用gets
读取输入,使用fgets()
并删除最后的'\n'
。
只计算一次s1
和s2
的长度,并将它们存储在局部变量中。
验证串联不会超过s1
的大小。
用这些局部变量重写你的循环,或者使用strcpy
或memcpy
。
这是一个例子:
#include <stdio.h>
#include <string.h>
int main(void) {
char s1[100], s2[100];
size_t i, len1, len2;
puts("First string?");
if (!fgets(s1, sizeof s1, stdin))
return 1;
len1 = strlen(s1);
if (len1 > 0 && s1[len1 - 1] == '\n')
s1[--len1] = '[=10=]';
puts("Second string?");
if (!fgets(s2, sizeof s2, stdin))
return 1;
len2 = strlen(s2);
if (len2 > 0 && s2[len2 - 1] == '\n')
s1[--len2] = '[=10=]';
if (len1 + len2 >= sizeof s1)
return 2;
/* copy the characters from s2 including the final '[=10=]' */
for (i = 0; i <= len2; i++) {
s1[len1 + i] = s2[i];
}
puts(s1);
return 0;
}
s1 的长度在运行时发生变化,导致您的索引 i 不正确。尝试如下所示:-
l = strlen(s1);
for(i = 0; i < strlen(s2); i++)
{
s1[l++] = s2[i];
}
s1[l] = '[=10=]';
假设s1 = "hello"和s2 = "world",那么在第一次迭代中,s1的长度= 5,s2的索引= 0(i-length(s1));效果很好。但是在第二次迭代中,length(s1) = 6 和 s2 的索引 = 0(i-length(s1))。所以从 s2 中获取字符的索引没有改变。这是关于您的实现中的问题,尽管您应该使用 sprintf 的有效方法。
sprintf(s1, "%s%s", s1, s2);
我在你的程序中并没有真正改变太多,但这是我所拥有的(从你的修改而来)并且它有效。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char s1[100], s2[100];
size_t i, s1l, s2l, total;
puts("First string?");
fgets(s1, sizeof(s1), stdin);
s1[strlen(s1) - 1] = 0x00;
puts("Second string?");
fgets(s2, sizeof(s2), stdin);
s2[strlen(s2) - 1] = 0x00;
s1l = strlen(s1);
s2l = strlen(s2);
total = s1l + s2l;
for(i = s1l; i <= total; i++)
{
s1[i] = s2[i - s1l];
}
puts(s1);
return(0);
}
逐字使用你的程序,问题是由于 s1 的长度在循环的每次迭代中都在变化,检查中的 strlen(s1) 的值不断增加,所以你基本上会得到一个几乎无限的循环...至少直到它遇到一些随机的空字节。但是,当事先获取字符串的长度时,循环终点计数不会改变,从而导致正确的输出。我的代码将使用 clang 编译器在 FreeBSD 10.2 系统上正确编译和运行。
作为旁注,不要 return 在主目录上无效。 始终 return 整数。还要指定您计划使用的库 headers。
编辑:我修改了代码以使用 fgets 而不是 gets,因为 gets 是完全不安全的。它不检查缓冲区大小,因此您很容易发生缓冲区溢出。
// A simple strcat function
int main(void)
{
char str1[100] ="Avis";
stringcat(str1,"karthik");
printf("\n%s",str1);
return 0;
}
void stringcat(char *str1, char *str2)
{
while(*str1)
str1++;
while(*str2)
*str1++ = *str2++;
}
我想在不使用 strcat() 的情况下连接两个字符串 function.But 我没有得到所需的结果。请指出我的错误。
void main() {
char s1[100], s2[100];
int i;
puts("First string?");
gets(s1);
puts("Second string?");
gets(s2);
for (i = strlen(s1); i <= (strlen(s1) + strlen(s2)); i++) {
s1[i] = s2[i - strlen(s1)];
}
puts(s1);
}
使用 sprintf 的变体:
更简单
char buf[200];
sprintf(buf, "%s%s" s1, s2);
更简单并且更安全
char buf[200]
snprintf(buf, sizeof(buf), "%s%s", s1, s2);//prevents buffer overflow
或者,修改您的循环(请参阅行注释了解原因):
int main(void)//note changed main prototype
{
char s1[100], s2[100];//caution here: s1 must be big enough
//to contain its string as well as
//the string stored in s2, plus 1 for NULL
int i;
int len1, len2;//create variables to store string lengths
puts("First string?");
gets(s1);//note, gets is no longer recommended
puts("Second string?");
gets(s2);
len1 = strlen(s1);//store string lengths only once
len2 = strlen(s2);//to avoid calling them repeatedly in loop
for(i = 0; i < len2; i++)//index i in one place only
{
s1[len1+i] = s2[i];
}
s1[len1 + i]=0;//null terminate string when done.
puts(s1);
getchar();//added to pause execution in my environment.
return 0;
}
此处显示了使用上述修改的示例会话:
您的解决方案不起作用,因为您在每次迭代时重新计算 strlen(s1)
以测试是否完成并计算 s2
中的偏移量以从中复制一个字符,但您修改了 s1
在循环中,因此长度发生变化,更糟糕的是,s1
暂时不再 '[=15=]'
终止:测试表达式 i <= strlen(s1) + strlen(s2)
调用未定义的行为,当您复制 s2[i - strlen(s1)]
第二次循环。
使用这些想法来更正您的代码:
不要使用
gets
读取输入,使用fgets()
并删除最后的'\n'
。只计算一次
s1
和s2
的长度,并将它们存储在局部变量中。验证串联不会超过
s1
的大小。用这些局部变量重写你的循环,或者使用
strcpy
或memcpy
。
这是一个例子:
#include <stdio.h>
#include <string.h>
int main(void) {
char s1[100], s2[100];
size_t i, len1, len2;
puts("First string?");
if (!fgets(s1, sizeof s1, stdin))
return 1;
len1 = strlen(s1);
if (len1 > 0 && s1[len1 - 1] == '\n')
s1[--len1] = '[=10=]';
puts("Second string?");
if (!fgets(s2, sizeof s2, stdin))
return 1;
len2 = strlen(s2);
if (len2 > 0 && s2[len2 - 1] == '\n')
s1[--len2] = '[=10=]';
if (len1 + len2 >= sizeof s1)
return 2;
/* copy the characters from s2 including the final '[=10=]' */
for (i = 0; i <= len2; i++) {
s1[len1 + i] = s2[i];
}
puts(s1);
return 0;
}
s1 的长度在运行时发生变化,导致您的索引 i 不正确。尝试如下所示:-
l = strlen(s1);
for(i = 0; i < strlen(s2); i++)
{
s1[l++] = s2[i];
}
s1[l] = '[=10=]';
假设s1 = "hello"和s2 = "world",那么在第一次迭代中,s1的长度= 5,s2的索引= 0(i-length(s1));效果很好。但是在第二次迭代中,length(s1) = 6 和 s2 的索引 = 0(i-length(s1))。所以从 s2 中获取字符的索引没有改变。这是关于您的实现中的问题,尽管您应该使用 sprintf 的有效方法。
sprintf(s1, "%s%s", s1, s2);
我在你的程序中并没有真正改变太多,但这是我所拥有的(从你的修改而来)并且它有效。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char s1[100], s2[100];
size_t i, s1l, s2l, total;
puts("First string?");
fgets(s1, sizeof(s1), stdin);
s1[strlen(s1) - 1] = 0x00;
puts("Second string?");
fgets(s2, sizeof(s2), stdin);
s2[strlen(s2) - 1] = 0x00;
s1l = strlen(s1);
s2l = strlen(s2);
total = s1l + s2l;
for(i = s1l; i <= total; i++)
{
s1[i] = s2[i - s1l];
}
puts(s1);
return(0);
}
逐字使用你的程序,问题是由于 s1 的长度在循环的每次迭代中都在变化,检查中的 strlen(s1) 的值不断增加,所以你基本上会得到一个几乎无限的循环...至少直到它遇到一些随机的空字节。但是,当事先获取字符串的长度时,循环终点计数不会改变,从而导致正确的输出。我的代码将使用 clang 编译器在 FreeBSD 10.2 系统上正确编译和运行。
作为旁注,不要 return 在主目录上无效。 始终 return 整数。还要指定您计划使用的库 headers。
编辑:我修改了代码以使用 fgets 而不是 gets,因为 gets 是完全不安全的。它不检查缓冲区大小,因此您很容易发生缓冲区溢出。
// A simple strcat function
int main(void)
{
char str1[100] ="Avis";
stringcat(str1,"karthik");
printf("\n%s",str1);
return 0;
}
void stringcat(char *str1, char *str2)
{
while(*str1)
str1++;
while(*str2)
*str1++ = *str2++;
}