#include <stdio.h>
#include <stdlib.h>
main()
{
char *a,*b,*c={0};
int i=0,j=0;
a=(char *)malloc(20*sizeof(char));
b=(char *)malloc(20*sizeof(char));
c=(char *)malloc(20*sizeof(char));
printf("Enter two strings:");
gets(a);
gets(b);
while(a[i]!=NULL)
{
c[i]=a[i];
i++;
}
while(b[j]!=NULL)
{
c[i]=b[j];
i++;
j++;
}
printf("The concated string is %s",c);
}
这很疯狂........我花了一整晚它没有工作,然后第二天晚上它突然完美......我很困惑
答案 0 :(得分:4)
您的代码有很多问题。 如果你关心的只是使代码工作,并非所有这些都很重要。 但是,我在这里尝试向您展示代码中明确的不同误解,并向您展示如何更好地编写代码。
你误解了NULL意味着什么。 NULL指针不指向任何东西 字符串以&#39; \ 0&#39;终止。这是一个ASCII NUL,不是一回事,尽管它们都使用值0。
char * s =&#34;你好&#34 ;;
上面的字符串实际上是6个字符长。你好5个字节,1个用于&#39; \ 0&#39;那个被困在最后。顺便说一句,这意味着您只能拥有长达19个字符的字符串,因为您需要为终端保留一个字节&#39; \ 0&#39;
char * r = NULL;
指针r指向任何东西。没有&#39; \ 0&#39;在那里,如果你试图看r [0],你会崩溃。
正如奥加指出的那样,你错过了终止与&#39; \ 0&#39;这会产生随机错误,因为你的printf将继续尝试打印,直到找到它的第一个零字节。你是否在任何特定的运行中崩溃都是运气问题。零是常见的,所以通常你会在崩溃之前停止,但你可能会在字符串后打印出一些垃圾。
就个人而言,我宁愿崩溃,也不会让程序随机打印出错误的东西。至少在你崩溃的时候,你知道出了什么问题,可以解决它。
你似乎也忘记释放你对malloc的记忆。 如果您打算使用malloc,最后应该免费使用:
int* a = malloc(20);
...
free(a);
你也只是在拍摄20个字符。如果你重复一遍,你会在记忆中做出可怕的事情。 20似乎太短,你只有19个字符加上结尾的空格来玩,但是如果你在a和b中分别有20个字符,你需要在c中有40个字符。
如果这是使用malloc的赋值,那么使用它,但是当你完成时你应该自由。如果你不必使用malloc,这个例子没有显示使用它的原因,因为你正在分配一小块恒定的内存。
您正在初始化c:
char* c = {0};
以一种毫无意义的方式。 {0}是一个具有单个零值的数组。 c指向它,但是你立刻将它指向别的东西,再也不会看你的小阵列了。
你可能意味着C首先指向的是什么。 那将是:
char* c = NULL;
然后你立即消灭了null,那么为什么要初始化c,而不是a和b?
作为一般规则,您不应声明值并在以后初始化它们。你总是可以做一些愚蠢的事情,并在初始化之前使用它们。相反,在声明:
时进行初始化int* a = malloc(20);
int* b = malloc(20);
int* c = malloc(40);
顺便提一下,char的大小按定义1,所以: 20 * sizeof(char) 与20相同。
你可能看到了一个例子:
20 * sizeof(int)
因为sizeof(int)不是上面的1所做的事情。通常sizeof(int)是4个字节,因此上面将分配80个字节。
获取是不安全的,因为它没有说缓冲区有多长 总是使用fgets而不是获取。 (见下文)。 许多计算机都使用此错误进行攻击(请参阅http://en.wikipedia.org/wiki/Robert_Tappan_Morris)
但是,由于不需要malloc,在你的代码中,你真的应该写:
enum { SIZE = 128 };
char a[SIZE];
fgets(a, SIZE, STDIN);
char b[SIZE];
fgets(b, SIZE, STDIN);
char c[SIZE*2];
int i;
int j = 0;
for (i = 0; a[i] != '\0' && i < 127; i++)
c[j++] = a[i];
for (i; b[i] != '\0' && i < 127; i++)
c[j++] = a[i];
c[j] = '\0';
...
最后,我不知道你是在学习C还是C ++。我将简单地指出,在C ++中,这种编程很容易,其中很多工作都是为您完成的。你可以先用简单的方法完成连接,然后学习更难的所有指针操作。
#include <string>
#include <iostream>
using namespace std;
int main() {
string a,b,c;
getline(cin, a); // read in a line
getline(cin, b);
c = a + b;
cout << c;
}
当然,你仍然需要学习这个低级指针,才能成为C ++中一个复杂的程序员,但如果只是为了读入和连接行,C ++会让它变得更容易。
答案 1 :(得分:2)
您未正确终止c
。在printf
:
c[i] = '\0';
如果i
处的字符恰好是0
,则省略空终止似乎会正常工作,但您需要将其设置为确定。
答案 2 :(得分:0)
字符串c没有以null char终止,这意味着printf不知道停止的位置,并且当程序超出时可能会对程序进行段错误。你可能获得零星成功的原因是,当你分配它时,malloced区域有一个随机的机会被预先归零,如果是这样的话,它会成功,因为一个空字符表示为一个字面的0字节。
这里有两种解决方案,首先你可以手动终止带有空字符串的字符串,如下所示:
c[i] = '\0';
其次,您可以使用calloc而不是malloc,它可以保证内存始终预先归零。
作为附注,您应该在代码中添加一些长度检查,以确保如果A和B都超过10,则c不会溢出。(或者只是使c 40长)
我希望这会有所帮助。