c - 为什么这个简单的代码有时不起作用????然后当我重新启动我的代码块时它有时会起作用

标签 c

#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);

     }

这太疯狂了......我花了一整夜它不起作用,然后第二天晚上它突然完美地工作......我很困惑

最佳答案

您的代码有很多问题。 如果您关心的只是让代码正常工作,那么并不是所有这些都很重要。 不过,我在这里尝试向您展示代码中清楚的不同误解,并向您展示如何更好地编写代码。

您误解了 NULL 的含义。 NULL 指针不指向任何东西 字符串以 '\0' 结尾,这是一个 ASCII NUL,不是同一件事,尽管两者都使用值 0。

char* s = "你好";

上面的字符串实际上有 6 个字符长。 5 个字节表示 hello,1 个字节表示卡在末尾的“\0”。顺便说一句,这意味着您只能拥有最多 19 个字符长的字符串,因为您需要为终端 '\0' 保留一个字节

char* r = NULL;

指针 r 没有指向任何东西。那里没有 '\0',如果你尝试查看 r[0],你将会崩溃。

正如 Ooga 指出的,您错过了以 '\0' 终止,这将产生随机错误,因为您的 printf 将继续尝试打印,直到找到第一个零字节。是否在任何特定的运行中摔倒都是运气问题。零很常见,因此通常您会在崩溃之前停止,但您可能会在字符串后打印出一些垃圾。

就我个人而言,我宁愿崩溃也不愿让程序随机打印出错误的东西。至少当你崩溃时,你知道出了问题并且可以修复它。

您似乎还忘记释放您 malloc 的内存。 如果要使用 malloc,则应该在末尾使用 free:

int* a = malloc(20);
...
free(a);

您也只分配了 20 个字符。如果你重蹈覆辙,你会在内存中做出可怕的事情。 20 似乎太短了,您只有 19 个字符加上末尾的 null 可以使用,但如果 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* 大小(字符) 与 20 相同。

您可能看到过这样的示例:

20 * sizeof(int)

由于 sizeof(int) 不是 1,所以上面会做一些事情。通常 sizeof(int) 是 4 个字节,因此上面将分配 80 个字节。

gets 不安全,因为它没有说明缓冲区有多长 始终使用 fgets 而不是 gets。 (见下文)。 许多计算机已被利用此错误进行了黑客攻击(请参阅 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++ 中要容易得多,因为 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++ 会让它变得容易得多。

关于c - 为什么这个简单的代码有时不起作用????然后当我重新启动我的代码块时它有时会起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23176296/

相关文章:

c - 建筑中 undefined symbol ,C

c++ - 为什么我们可以取消引用函数指针?

c - 如何找到st_link的偏移量?

c - 使用 pipe、fork 和 exec 后程序挂起

c - C 中 "char"之前的语法错误

c - 为什么 printf ("value: %f",10/2);输出 0.000000?

c - 我可以使用 gdb 的 x 命令打印内存,但是如果我使用 printf,则会出现段错误

随身携带 C 编译器

c - 什么是不同的功能 : `malloc()` and `kmalloc()` ?

c - 使用C编程和链表的词频但频率计数错误