简体   繁体   中英

why does this simple code gives not work at times????then when i restart my code blocks it does work at times

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

     }

this is crazy........i spend one whole night it didn't work and then next night it suddenly works perfectly....i'm confused

There are many things wrong with your code. Not all of them matter if all you care about is getting the code to work. However, I have tried here to show you different misconceptions that are clear from your code, and show you how to code it better.

You are misunderstanding what NULL means. a NULL pointer doesn't point at anything Strings are terminated with '\\0' which is an ASCII NUL, not the same thing, though both use the value 0.

char* s = "hello";

The above string is actually 6 characters long. 5 bytes for the hello, 1 for the '\\0' that is stuck at the end. Incidentally, this means that you can only have strings up to 19 characters long because you need to reserve one byte for the terminal '\\0'

char* r = NULL;

The pointer r is pointing at nothing. There is no '\\0' there, and if you attempt to look at r[0], you will crash.

As Ooga pointed out, you missed terminating with '\\0' which is going to create random errors because your printf will keep going to try to print until the first zero byte it finds. Whether you crash on any particular run is a matter of luck. Zeros are common, so usually you will stop before you crash, but you will probably print out some junk after the string.

Personally, I would rather crash than have the program randomly print out the wrong thing. At least when you crash, you know something is wrong and can fix it.

You also seem to have forgotten to free the memory you malloc. If you are going to use malloc, you should use free at the end:

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

You also are only mallocing 20 characters. If you go over that, you will do horrible things in memory. 20 seems too short, you will have only 19 characters plus the null on the end to play with but if you do have 20 characters each in a and b, you would need 40 characters in c.

If this is an assignment to use malloc, then use it, but you should free when you are done. If you don't have to use malloc, this example does not show a reason for using it since you are allocating a small, constant amount of memory.

You are initializing c:

char* c = {0};

In a way that makes no sense. The {0} is an array with a single zero value. c is pointing to it, but then you immediately point it at something else and never look at your little array again.

You probably mean that C is pointing to nothing at first. That would be:

char* c = NULL;

but then you are immediately wiping out the null, so why initialize c, but not a and b?

As a general rule, you should not declare values and initialize them later. You can always do something stupid and use them before they are initialized. Instead, initialize as you declared the:

int* a = malloc(20);
int* b = malloc(20);
int* c = malloc(40);

Incidentally, the size of a char is by definition 1, so: 20* sizeof(char) is the same as 20.

You probably saw an example like:

20 * sizeof(int)

Since sizeof(int) which is not 1 the above does something. Typically sizeof(int) is 4 bytes, so the above would allocate 80 bytes.

gets is unsafe, since it doesn't say how long the buffer is ALWAYS use fgets instead of gets. (see below). Many computers have been hacked using this bug (see http://en.wikipedia.org/wiki/Robert_Tappan_Morris )

Still, since malloc is not really needed, in your code, you really should write:

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';

...

Last, I don't know if you are learning C or C++. I will simply point out that this kind of programming is a lot easier in C++ where a lot of the work is done for you. You can first get concatenation done the easy way, then learn all the pointer manipulation which is harder.

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

Of course, you still need to learn this low-level pointer stuff to be a sophisticated programmer in C++, but if the purpose is just to read in and concatenate lines, C++ makes it a lot easier.

You are not properly null-terminating c . Add this before the printf :

c[i] = '\0';

Leaving out null-termination will seem to work correctly if the char at i happens to be 0 , but you need to set it to be sure.

The string c is not being terminated with a null char, this means printf does not know where to stop and will likely segfault your program when it overruns. The reason you may be getting sporadic success is that there is a random chance the malloced area has been pre zeroed when you allocate it, if this is the case it will succeed as a null char is represented as a literal 0 byte.

there are two solutions available to you here, first you could manually terminate the string with a null char as so:

c[i] = '\0';

Second you can use calloc instead of malloc, it guarantees the memory is always pre zeroed.

As a side note you should likely add some length checking to your code to ensure c will not overflow if A and B are both over 10. (or just make c 40 long)

I hope this helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM