I was trying to get an element deleted from the middle of array and then shiffting the whole content, and I had a few difficulties because my test array wasn't "right". I fixed the problem by filling the array with a string using strcpy. The commented part above strcpy is the method I used before(which didn't work). Could somebody explain me maybe why isn't it working?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char *array;
int i=5;
array = (char*)calloc(1024, sizeof(char));
if(array == NULL){
printf("Out of memory\n");
return 0;
}
//array = "Just some test string";
strcpy(array, "Just some test string");
printf("%s\n", array);
memmove(array+i+1, array+i, strlen(array)-i);
array[i] = ',';
printf("%s\n", array);
memmove(array+i, array+i+1, strlen(array)-i);
printf("%s\n", array);
free(array);
return 0;
}
The printf is normally working on the commented part, but the memmove() makes my programm crash!
If you have this:
array = "Just some test string";
then
1) You have memory leak due to overwriting the calloc'ed pointer.
2) You are attempting to modify a string literal. That's probably why it crashes. Modifying a string literal is undefined behaviour. They are typically stored in read-only memory. Since strcpy() makes a copy of the string literal, it works as intended and this method fails.
In these statements
memmove(array+i+1, array+i, strlen(array)-i);
array[i] = ',';
there is an attempt to insert character ',' at the position 5 because variable i was initialized with 5.
So the part of the string including the terminating zero has to be shifted right starting with this position. The length of the part is
strlen( array ) - i + 1
because the terminating zero is also must be moved.
So these statements will look like
memmove( array + i + 1, array + i, strlen( array ) - i + 1 );
array[i] = ',';
Then in these statements
memmove( array + i, array + i + 1, strlen( array ) - i );
This statement is correct. Expression strlen( array ) - i is calculated like
( strlen( array ) + 1 ) - ( i + 1 )
As for this statement
array = "Just some test string";
then pointer array points to a string literal and though string literals in C have types of non-constant character arrays nevertheless they are immutable.
Any attempt to modify a string literal results in undefined behaviour of the program.
Also if before this statement you also initialized this pointer with the result of a call to calloc then there will be a memory leak because the pointer is reassigned and the address of the allocated memory is lost.
I tried to do something like this.
I solved it by having:
*(array+strlen(string)+1)=0;
Null terminating the string, but if the subsequent printf() is working correctly this won't help.
Otherwise see:
http://www.java-samples.com/showtutorial.php?tutorialid=591
Related
I'm learning C and I'm so stucked in when allocating memory for a char array in a struct array.
After assigning the value to the char arrays in the first loop, when I try to access the value in a second loop.
Could please anyone help me? thank you
For starters this code snippet invokes undefined behavior
char string[numDigits];
sprintf(string, "%d", 12345);
because the array string does not have a space to store the terminating zero character '\0' of the string built by the call of sprintf. You need to declare the array like
char string[numDigits+ 1];
Secondly this code snippet
table[i].str = malloc(sizeof(char) * numDigits);
table[i].str = string;
produces a memory leak because at first a memory was allocated and its address was assigned to the pointer table[i].str and then the pointer was reassigned.
You need to write
#include <string.h>
//...
table[i].str = malloc(sizeof(char) * ( numDigits + 1 ));
strcpy( table[i].str, string );
And at last for loops in the program shall be rewritten like
for (i = 0; i < n; i++)
^^^^^^
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.
Here's my program:
#include <stdio.h>
char *ft_strcat(char *dest, char *src)
{
int i;
int k;
i = 0;
k = 0;
while (dest[i])
i++;
while (src[k])
{
dest[i + k] = src[k];
//i++;
k++;
}
dest[i + k] = '\0';
return (dest);
}
int main(){
//ft_strcat
char str[] = "Hello, ";
char str2[] = "World!";
printf("%s", ft_strcat(str, str2));
return 0;
}
It's implementing of strcat function.
When I'm trying to copy "World!" to "Hello, " I have an error "zsh: abort". There's no problem when I'm trying to copy to "Hello ".
What can I do with this error? Why this comma causes this problem?
When you define an array with empty dimension and initialize that with a brace-enclosed initializer list, the size of the array is determined by the supplied initializer list elements.
So, in your case, str and str2 are just long enough to hold the strings "Hello, " and "World!", respectively.
So, the problem here is, the destination buffer (passed as the first argument of ft_strcat()) has absolutely no space to hold the concatenated result. You're accessing out of bound memory, thus causing undefined behavior.
In the very first iteration of the while loop,
while (src[k])
{
dest[i + k] = src[k];
//i++;
k++;
}
the index i+k points to out of bound memory for dest. No sooner than you try to use the index to access the memory location, you face UB.
You need to make sure, the destination has enough space left to hold the concatenated result. For that, you can have either of two approaches
Define a bigger array size statically and use that as destination. You can always check for the actual size vs. already used size easily in this case, as this is a character type array meant to be used as string (hint: sizeof vs strlen()).
You can make use of a pointer, use memory allocator function to allocate certain amount of memory and realloc() as needed.
The following function allows me to calculate the length of a character string:
int arrayLen (char array[])
{
int i = 0;
while ( array[i] )
++i;
return i;
}
The problem is, if an array has 20 elements but only uses, say, 5 of them (including the null character \0), then the function will return 5. So from this, it's difficult to know how many characters the string can support in a function. Unfortunately, sizeof can't be used since the array is dynamically-allocated.
Here is an example of the basic function I'm trying to create, it allows the user to insert a character string into another character string at the index of the source[]:
void insertString (char source[], char insert[], int index)
{
int n = arrayLen (insert);
char temp[n];
// Replace characters from index with characters in insert array
for ( i = 0; source[index + i] && insert[i]; ++i )
{
temp[i] = source[index + i];
source[index + i] = insert[i];
}
// Concatenate replaced characters onto source array
for ( i = 0; temp[i]; ++i )
source[index + n + i] = temp[i];
}
The above code works fine until source[] isn't big enough to contain itself and the elements insert[]. Is there anyway to test for this and inform the user?
Update
I understand the limitations of finding the length of an array but is there a way to check if the array has been concatenated correctly onto the source[]?
e.g.
input = the wrong son
output = the wrong person▒▒"
In C, you need to explicitly tell the compiler the buffer size as a parameter since all the elements in an array are not copied into the array parameter; instead they are referenced by a pointer. - T.C.
Additional Info:
sizeof array / sizeof array[0] doesn't work since sizeof array references the size of the pointer to the first element in array, not the size of all the elements in the array. This would only work if the array was declared in the same function was the sizeof calculations.
You could, however, calculate how many elements are occupied in the array as follows:
int i = 0;
while ( array[i] )
++i;
This works if the array is ended by a null character \0. If the array has more space reserved than whats actually used, the above function will fail to identify that.
If you're not passing the actual buffer size to the function, there is no way to determine its size. When you pass an array to a function, it decays to a pointer:
unsigned wrong_sizeof(char arr[])
{
return (unsigned)sizeof arr;
}
int main(void)
{
char s[] = "Hello world!";
char *p;
printf("wrong_sizeof(s): %u\n", wrong_sizeof(s));
printf("sizeof p: %u\n", (unsigned) sizeof p);
printf("sizeof s: %u\n", (unsigned)sizeof s);
return 0;
}
That program first prints the incorrect size calculation, which is incorrect because the function wrong_sizeof receives a pointer to the first element of the array (&s[0]) instead the entire array itself. This is something the C language specification requires.
Next is the size of a pointer using the sizeof operator directly, followed by the size of the array using the sizeof operator directly instead of the function. This proves that the function receives a pointer.
To conclude, you must pass one of two things:
the size of the output buffer
the number of characters to copy
With either one of these, it is no longer your fault as the designer of the function if an incorrect parameter is passed because you're only doing what you're told, similar to strncpy, strcat, etc.
Edit
To address the update:
new_size == source_length - i + insert_size
The size required by the new string, including the null terminator, is the number of characters in the source string, excluding the null terminator, plus the number of characters required for storing the string to insert, including the null terminator. For example:
char buf[] = "Hello, world!"
insertString(buf, "John", 7);
printf("%s\n", buf);
will result in a new string requiring 14 - 7 + 5, or 12, characters: 7 for "Hello, " and 5 for "John\0".
I am new to C and I would like to know the difference between the below two snippet codes.When I try executing first one it works fine,but when I run the second one it gives me segmentation fault.Whats the reason for this behavior?
printf("%c\n",*strptr++);
printf("%c\n",*(strptr+i));
Here is the below code.
#include<stdio.h>
int main(void)
{
char str[100]="My name is Vutukuri";
int i=0;
char *strptr;
strptr=str;
while(*strptr != '\0')
{
printf("%c\n",*strptr++);
//printf("%c\n",*(strptr+i));
//i++;
}
return 0;
}
Entirely different.
The first snippet prints the character at strptr and then increments strptr by one.
The second snippet prints the character at strptr + i.
Apparently, the address strptr refers to an allocated place in memory, while strptr + i points to an unallocated place. If you allocate a string as
char s[LENGTH];
or
char* s = (char*)malloc(LENGTH * sizeof(char));
then you can only use the characters from s[0] to s[LENGTH - 1] (and the string itself can only be LENGTH - 1 long, so there is place for a null terminator). In your case, the pointer strptr + i is probably not in the range s...s + LENGTH - 1.
Maybe you want to replace i with 1.
++ operator first uses the initial value, and then it increments it.
+operator calculates the new value and then uses it.