if you point a char pointer to a chunk of memory that you just malloc() and feed it characters at position [0], [1], [2], [3],..., [n] does malloc already provide a null terminator '\0' at the end or must i provide it at the last element of the char array?
int i;
char B; //has the characters hello
char *A=malloc(5*sizeof(char)); //4 bytes for hello + 1 byte for null terminator?
for(i=0; i<strlen(A);i++)
A[i]=B[i];
after the for loop finishes should i add a null terminator to the last element of A or does malloc() already provide it?
YES you need to put a null terminator explicitly. malloc is just returning starting pointer to the block of 5 byte memory.
After malloc, A contains garbage value, so you need to assign \0 explicitly. However, there are several other errors in your code:
Your declaration of B is wrong, it should be a char array instead of a single char.
The string "hello" contains 6 elements, including the trailing \0, so:
char B[] = "hello";
char *A = malloc(strlen(B) + 1);
for(i = 0; i < strlen(B) + 1; i++)
A[i] = B[i];
Or you can simply use strcpy:
strcpy(A, B);
Malloc will not provide memory filled with nulls.
As pointed out above, use strcpy and be safe.
I edited out the calloc part. That was wrong.
Related
I need help with char array. I want to create a n-lenght array and initialize its values, but after malloc() function the array is longer then n*sizeof(char), and the content of array isnt only chars which I assign... In array is few random chars and I dont know how to solve that... I need that part of code for one project for exam in school, and I have to finish by Sunday... Please help :P
#include<stdlib.h>
#include<stdio.h>
int main(){
char *text;
int n = 10;
int i;
if((text = (char*) malloc((n)*sizeof(char))) == NULL){
fprintf(stderr, "allocation error");
}
for(i = 0; i < n; i++){
//text[i] = 'A';
strcat(text,"A");
}
int test = strlen(text);
printf("\n%d\n", test);
puts(text);
free(text);
return 0;
}
Well before using strcat make
text[0]=0;
strcat expects null terminated char array for the first argument also.
From standard 7.24.3.1
#include <string.h>
char *strcat(char * restrict s1,
const char * restrict s2);
The strcat function appends a copy of the string pointed to by s2
(including the terminating null character) to the end of the string
pointed to by s1. The initial character of s2 overwrites the null
character at the end of s1.
How do you think strcat will know where the first string ends if you don't
put a \0 in s1.
Also don't forget to allocate an extra byte for the \0 character. Otherwise you are writing past what you have allocated for. This is again undefined behavior.
And earlier you had undefined behavior.
Note:
You should check the return value of malloc to know whether the malloc invocation was successful or not.
Casting the return value of malloc is not needed. Conversion from void* to relevant pointer is done implicitly in this case.
strlen returns size_t not int. printf("%zu",strlen(text))
To start with, you're way of using malloc in
text = (char*) malloc((n)*sizeof(char)
is not ideal. You can change that to
text = malloc(n * sizeof *text); // Don't cast and using *text is straighforward and easy.
So the statement could be
if(NULL == (text = (char*) malloc((n)*sizeof(char))){
fprintf(stderr, "allocation error");
}
But the actual problem lies in
for(i = 0; i < n; i++){
//text[i] = 'A';
strcat(text,"A");
}
The strcat documentation says
dest − This is pointer to the destination array, which should contain
a C string, and should be large enough to contain the concatenated
resulting string.
Just to point out that the above method is flawed, you just need to consider that the C string "A" actually contains two characters in it, A and the terminating \0(the null character). In this case, when i is n-2, you have out of bounds access or buffer overrun1. If you wanted to fill the entire text array with A, you could have done
for(i = 0; i < n; i++){
// Note for n length, you can store n-1 chars plus terminating null
text[i]=(n-2)==i?'A':'\0'; // n-2 because, the count starts from zero
}
//Then print the null terminated string
printf("Filled string : %s\n",text); // You're all good :-)
Note: Use a tool like valgrind to find memory leaks & out of bound memory accesses.
I create a big 2d char array and want to assign strings to it.
int i;
char **word;
int start_size = 35000;
word=(char **) malloc(start_size*sizeof(char *));
for(i=0;i<start_size;i++)
word[i]=(char *) malloc(start_size*sizeof(char));
word[2][2] = "word";
how do I assign a string?
Explain me why this code doesn't work...
I am new to low level programming and C but experienced in high level programming
You cannot do string assignment in C.
You need to call a function, sepcifically strcpy() (prototype in <string.h>)
#include <string.h>
strcpy(word[2], "word");
word[2][2] = "word";
In the above statement, the string literal "word" is implicitly converted to a pointer to its first element which has type char * whereas word[2][2] has type char. This attempts to assign a pointer to a character. This explains the warning message you have stated -
assignment makes integer from pointer without a cast
You can use string literals only to initialize character arrays. What you need to do is use the standard function strcpy to copy the string literal. Also, you should not cast the result of malloc. Please read this - Do I cast the result of malloc? I suggest the following changes -
int i;
int start_size = 35000;
// do not cast the result of malloc
char **word = malloc(start_size * sizeof *word);
// check word for NULL in case malloc fails
// to allocate memory
for(i = 0; i < start_size; i++) {
// do not cast the result of malloc. Also, the
// the sizeof(char) is always 1, so you don't need
// to specify it, just the number of characters
word[i] = malloc(start_size);
// check word[i] for NULL in case malloc
// malloc fails to allocate memory
}
// copy the string literal "word" to the
// buffer pointed to by word[2]
strcpy(word[2], "word");
You have to decide if you want a list of strings or a 2D array of strings.
A list of string works like this:
char **word;
word = (char**)malloc(start_size*sizeof(char*));
word[2] = "word";
In this example word[2] would be the third string in the list and word[2][1] would be the second character in the third string.
If you want a 2D array of string you have to do this:
int i;
char ***word;
^^^ 3 stars
int start_size = 35000;
word = (char***)malloc(start_size*sizeof(char**));
^^^ 3 stars ^^^ 2 stars
for(i=0;i<start_size;i++)
word[i] = (char**) malloc(start_size*sizeof(char*));
^^^ 2 stars ^^^ 1 star
word[2][2] = "word"; // no it works!
Note that in C you do not need the casts before the malloc. So this would also work:
word = malloc(start_size*sizeof(char**));
I was trying to implement strcat by myself, It seems to work but I don't understand how come p has '\0' at its end? it didn't copy it from b and it shouldn't be there without putting it. Any explanation? The output is "yesMichaelJudy".
#include<string.h>
#include<stdio.h>
#include <stdlib.h>
#include<conio.h>
char* strcat1( char *s1, const char *s2 )
{
register char *p = s1;
while ( *p )
++p;
while (*s2){
*p=*s2;
++p;
++s2;
}
if (*p=='\0') printf("yes");
++p;
p='\0';
return s1;
}
int main(){
char* a;
char* b;
char* result;
result=(char *)calloc(20,sizeof(char));
a=(char *) calloc(20,sizeof(char));
b=(char *) calloc(20,sizeof(char));
strcpy (a,"Michael");
strcpy (b,"Judy");
result=strcat1(a,b);
printf(result);
getch();
return 1;
}
You're allocating the space larger than it needs to be and you're using calloc() which by definition clears all the characters to zero; therefore the extra characters at the end are zero.
strcpy copies the NUL character at the end of a string. Even if it didn't, you're using calloc to allocate your a and b, and calloc allocates and zeros the memory. Since you're allocating more space than you use (allocating 20 bytes, using 4 for Judy and 7 for Michael) you have some zero bytes after the strings anyway.
p='\0';
That's nonsense. It does nothing useful. It will also generate at least a compiler warning if not an error. The code should be
*p='\0';
Which is what puts \0 at the end of the string.
strcpy() null-terminates the string. But even if it didn't, calloc() puts it there. calloc() zeroes out the allocated memory. As soon as you allocated the memory, a and b are just a bunch of string-terminators.
calloc zero initializes ( ie fills it with NUL or '\0') the allocated buffer.
p in your strcat1 points into the array passed through parameter s1. And parameter s1 corresponds to argument a in main. The content of array a in main is filled with data by strcpy (a,"Michael"). This is what put that '\0' at the end of that data. strcpy did that. (You can also say that that '\0' came from "Michael" since "Michael" also has a '\0' at the end, even if it is not specified explicitly).
Here is my code:
printf("%s\n", "test1");
char c = '2';
char * lines[2];
char * tmp1 = lines[0];
*tmp1 = c;
printf("%s\n", "test2");
I don't see the second printf in console.
Question: Can anybody explain me what's wrong with my code?
NOTE: I'm trying to learn C :)
This line:
char * lines[2];
declares an array of two char pointers. However, you don't actually initialize the pointers to anything. So later when you do *tmp1 = (char)c; then you assign the character c to somewhere in memory, possibly even address zero (i.e. NULL) which is a bad thing.
The solution is to either create the array as an array of arrays, like
char lines[2][30];
This declares lines to have two arrays of 30 characters each, and since strings needs a special terminator character you can have string of up to 29 characters in them.
The second solution is to dynamically allocate memory for the strings:
char *lines[2];
lines[0] = malloc(30);
lines[1] = malloc(30);
Essentially this does the same as the above array-of-arrays declaration, but allocates the memory on the heap.
Of course, maybe you just wanted a single string of a single character (plus the terminator), then you were almost right, just remove the asterisk:
char line[2]; /* Array of two characters, or a string of length one */
The array lines in uninitialized. Thus lines[0] is an uninitalized pointer. Dereferencing it in *tmp1 is sheer undefined behaviour.
Here's an alternative, that may or may not correspond to what you want:
char lines[2];
char * tmp1 = lines; // or "&lines[0]"
*tmp = c;
Or, more easily:
char lines[2] = { c, 0 };
lines is uninitialized, and tmp1 initialization is wrong.
It should be:
char lines[2];
char * tmp1 = lines;
Alternatively, you can say:
char * tmp1 = &lines[0];
Or else for an array of strings:
char lines[2][30];
char * tmp1 = lines[0];
The line
char * lines[2];
creates an array of two char pointers. But that doesn't allocate memory, it's just a "handle" or "name" for the pointer in memory. The pointer doesn't point to something useful.
You will either have to allocate memory using malloc():
char * lines = malloc(2);
or tell the compiler to allocate memory for you:
char lines[2];
Note: Don't forget to terminate the string with a 0 byte before you use it.
char *lines[2]; : A two element array of char pointers.
char *tmp; : A pointer to a character.
char *tmp = lines[0] : The value inside the array element 0 of the lines array is transferred into tmp. Because it is an automatic array, therefore it will have garbage as the value for lines[0].
*temp : Dereference the garbage value. Undefined Behaviour.
char * tmp1 = lines[0];
here you declare a char pointer and initialize its pointer value to line[0],the fist element stored in line array which is also uninitialized.
now the tmp is pointing to somewhere unknown and not actually accessible. When you
*tmp1 = (char)c;
you are operating on a invalid memory address which causes a Segmentation fault.
My application falls over when I make the following call to strcat any ideas why?
char *encryptedLine[255] = {0};
char encryptedLString[8];
sprintf(encryptedLString, "%08lX", L);
strcat(*encryptedLine, encryptedLString);
*encryptedLine is NULL pointer: it needs to point a char buffer.
*encyptedLine is equivalent to encryptedLine[0], which is the first entry in the array of char* encryptedLine:
char *encryptedLine[255] = { 0 };
which is a NULL pointer.
To fix, either change to:
char encryptedLine[255] = { 0 };
strcat(encryptedLine, encryptedString);
or:
encryptedLine[0] = malloc(255);
strcat(*encryptedLine, encryptedString);
I think you also need to increase the size of encryptedLString by 1 as:
sprintf(encryptedLString, "%08lX", L);
will attempt to write 9 characters: 8 specified by the format plus 1 for the null terminator:
char encryptedLString[9];
encryptedLine is an array of 255 pointers initialized to NULL. *encryptedLine is a NULL pointer. You are passing a NULL pointer as the first argument to strcat, so it fails.
You are trying to strcat() with 0 as first parameter. *encryptedLine is encryptedLine[0] and you assigned {0} to it
You have an array of char pointers
char *encryptedLine[255]
You haven't allocated any memory and assigned it to any of them. Crash.
/* LINE 1*/ char *encryptedLine[255] = {0};
char encryptedLString[8];
sprintf(encryptedLString, "%08lX", L);
strcat(*encryptedLine, encryptedLString);
Look at LINE1, it allocates an array of 255 pointers to char that are all initialised to 0, then you do a strcat, which will try to write the value from encryptedLString into the location pointed to by the pointer *encryptedLine which is NULL, which isn't allowed.
Just allocate some memory for encryptedLine's pointers, and this program won't crash.