Terminating a pointer to a pointer? - c

I get no compiler warning from this but it segfaults. So how can I copy a '\0' at the beginning of the string so I can then use strncat ? (The use of strncpy is not allowed and using memcpy and then terminating the string segfaults also.)
I wrote this to illustrate the problem:
void func(char **str)
{
*str = realloc(*str, -);
*str[0] = '\0'; // I get segfault here.
strncat(*str, -, -);
// memcpy(*str, -, -);
// *str[strlen(*str)] = '\0'; // I get segfault here.
}
int main(void)
{
char *str = NULL;
func(&str);
return 0;
}
EDIT: I meant to write strlen(*str) and not strlen(str). Sorry.

The problem with the second segfaulting line is operator precedence.
[] has higher precedence than *, so *str[strlen(*str)] is interpreted as *(str[strlen(*str)]) - that is, dereference the address pointed to by the memory at str + strlen(*str).
You want (*str)[strlen(*str)] - that is, the character at the end of of str-dereferenced.

Segmentation faults occur when the memory being accessed by the program is invalid. It is very likely that the realloc call was not able to allocate the amount of memory being requested. It is a best practice to check whether the memory is properly allocated before proceeding to access it.
I tried this program and works well in my system.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void func(char **str)
{
*str = realloc(*str, sizeof(char) * 20);
if( *str == NULL)
{
printf("Memory allocation failed\n");
return;
}
*str[0] = '\0';
strncat(*str, "hello world", 11);
//memcpy(*str, "hello world", 11); //memcpy also works fine
//(*str) [strlen(*str)] = '\0';
printf("String : %s\n", *str);
}

Related

Truncate string with realloc() in C?

For an assignment i´m asked to change a string str3 containing "Hello World!" to "Hello", and to use realloc() to remove the the exess memory. I dont realy know how to do it.
How do i use realloc() to truncate the string?
How do i change the string from "Hello World!" to "Hello"?
The DString is a char* pointer so DString *str is a double pointer char**.
From the main()function we send str3 containing "Hello World!" and a blanc space to the function shrinkDString().
int main() {
shrinkDString(&str3, ' '); // truncate str3 after the blank, only "Hello" remains
shrinkDString(&str3, ' '); // nothing happens, "Hello" remains the same
}
As pre- and postcondition i´m supposed to use assert(). The DString *str is a double pointer to str3 and ch is a blanc space. Storing "hello World!" in str3 uses 13 memory including \0, "Hello" should only use memory of 6 including \0.
void shrinkDString(DString *str, char ch) {
// Shrinks the DString *str up to the first occurence of ch.
// Precondition: str is not NULL
// Precondition: *str is not NULL
/* Postcondition: if str has been truncated, its new length corresponds to the position of ch in the
original str*/
/* Tips:
- think that str is already allocated in memory and may be changed! Only the proper amount of
memory for storing the truncated string is allocated when the function return
- do not forget the char for ending a string '\0'
- useful C functions: realloc.
*/
}
This is what i´ve tried so far but i get a memory leak when using realloc() and assert(*str != NULL); is dereferencing NULL pointer.
void shrinkDString(DString *str, char ch) {
assert(str != NULL);
assert(*str != NULL);
*str = (char*)realloc(*str, 6);
}
I dont know how to continue. Grateful for any help!
You'd do something like
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char *s = malloc(100);
strcpy(s, "Hello World!");
printf("1 - s=%p *s = '%s'\n", s, s);
s[5] = '\0';
s = realloc(s, strlen(s)+1);
printf("2 - s=%p *s = '%s'\n", s, s);
return 0;
}
Note that realloc may not actually change the address of the memory block - it may just release the extra space at the end of it, or it may not do anything at all!
Note that this example code doesn't do any of the necessary checking for invalid return values, etc, which you should add.
onlinegdb here
It is not possible only using the realloc. You need also to add the trailing null character.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TEXT "Hello World"
int main()
{
char *ptr = malloc(strlen(TEXT) + 1);
strcpy(ptr,TEXT);
printf("original string: %s", ptr);
ptr = realloc(ptr, 6);
ptr[5] = 0;
printf("realloced string: %s", ptr);
free(ptr);
return(0);
}
How do i use realloc() to truncate the string?
You don't. A string is terminated by a null byte, and realloc() does not change any of the string's bytes. At least not in any way that you could rely on. The entire effect of a shrinking realloc() is, that it will consider the memory beyond the new size as free and safe for reuse by a future malloc() call. So, for example, the code
char* string1 = strdup("Hello World!");
string1 = realloc(string1, 6);
char* string2 = malloc(7);
printf("%s", string2); //reading uninitialized data, don't do this
might conceivably print "World!". It could print "I've encrypted your harddrive, please pay ***$ in bitcoins..." instead. Whatever. The C standard does not care. It is simply one of the possible things that might happen, that the malloc() call returns the memory that was cut off from string1 with the realloc() call. (Real implementations won't actually print "World!" for reasons which are way beyond this question.)
How do i change the string from "Hello World!" to "Hello"?
You terminate the string with a null byte. That's as simple as
(*str)[5] = 0;
Note the parentheses which force the double pointer to be dereferenced before performing the array subscript operation. Once you have cut down the string like this, you can subsequently also shrink the allocation with realloc():
(*str)[5] = 0;
*str = realloc(*str, 6); //5 characters plus one terminating null byte
the following proposed code:
cleanly compiles
performs the desired functionality
checks for and handles errors
and now, the proposed code:
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
void shrinkDString( char **str, char targetChar)
{
char *localStr = *str;
assert(str != NULL);
assert(localStr != NULL);
char *stopChar = strchr( localStr, (int)targetChar );
if( ! stopChar )
{
fprintf( stderr, "target char not in **str\n" );
return;
}
// impllied else, target char found
*stopChar = '\0';
char *temp = realloc( localStr, strlen( localStr ) + 1 );
if( ! temp )
{
perror( "realloc failed" );
exit( EXIT_FAILURE );
}
// implied else, realloc successful
*str = temp;
}

Check chars in a string while using pointers

I want to check each individual char in a string. The string is stored in a pointer.
for some reason I can't, it only let me get the whole string.
here's my code:
int main() {
char *s=(char*)calloc(30,sizeof(char));
s="hello";
printf("%s",&s[2]);
return 0;
}
this code print "llo", i need only 1 char like "l" or "o".
anyone know how i can achieve it?
ty
Use the %c conversion specifier to print a sinlge character instead of %s to print a string.
Also the memory allocation by calloc() is useless, since the pointer to char s get assigned by the address of the first element of the string literal "hello" one statement later.
#include <stdio.h>
int main (void)
{
const char *s = "hello";
printf("%c", s[2]);
return 0;
}
Output:
l
Side Note:
Use the const qualifier to prevent any unintentional write attempts to the string literal that lead to undefined behavior.
If you want to allocate memory and assign/initialize the allocated memory by the string literal "hello", use strcpy() (header string.h):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main (void)
{
char *s = calloc(30, sizeof(*s));
if (!s) // Check if allocation failed.
{
fputs("Error at allocating memory!", stderr);
exit(1);
}
strcpy(s, "hello");
printf("%c", s[2]);
return 0;
}
Output:
l
or you can use strdup() (Note: strdup() is not part of the standard C library) which will automatically allocate memory with the string of the string literal passed as argument initialized:
#include <stdio.h>
#include <string.h>
int main (void)
{
char *s = strdup("hello");
if (!s) // Check if allocation failed.
{
fputs("Error at allocating memory!", stderr);
exit(1);
}
printf("%c", s[2]);
return 0;
}
Side note:
"The string is stored in a pointer."
Something like that is not possible. The pointer points to the first element of the string (literal). The pointer does not store a string.

Memory allocation of pointer working for fixed variable assigned string but not for user input string

Given program is working for string that is fixed in code for example
char str[100] = "With fixed string this code works"
// Output of the program is "fixed string this code works"
But as soon as I take the str input using
scanf("%s", &str);
it seems error is found with memory allocation because after input is given code returns error value.
The full code is as following
int main (void) {
char str[100];
char *p = (char *)malloc(sizeof(char) * str[100]);
printf("Enter something: ");
scanf("%s", &str);
*p = str;
p = strchr(str, ' ');
puts(p + 1);
// Check for the first space in given input string if found then
while (*p++)
if (*p == ' ' && *++p)
printf("%s", *p);
printf ("\n\n");
return 0;
}
Not sure if for dynamic memory allocation while using scanf function to input string any other allocation process is required
Your malloc has a bug:
char *p = (char *)malloc(sizeof(char)*str[100]);
Let's simplify a bit first.
Don't cast malloc (See: Do I cast the result of malloc?):
char *p = malloc(sizeof(char)*str[100]);
sizeof(char) is (by definition) always 1 on all architectures, regardless of how many bits it occupies, so we can eliminate it:
char *p = malloc(str[100]);
Now we have:
char str[100];
char *p = malloc(str[100]);
You have undefined behavior. str has no values (i.e. unitialized) and you are passing the element that is one past the end of the array, so you have undefined behavior.
So, the length parameter passed to malloc is, thus, random.
You have four problems:
First: with scanf, it should be like that:
scanf("%s",str);
because str is an address. Also make sure that scanf will scan for a string from stdin until it finds space or new line and that what you don't want. So you'd better use fgets(str, 100, stdin);.
Second: with malloc, it should be like that:
malloc(sizeof(char)*100)
because str[100] has not a specific value.
Third: You shouldn't change the address of memory allocated using malloc
malloc function allocates memory in heap and return the address of memory allocated, so you shouldn't do this p = strchr(str, ' '); since strchr will return the address of the first occurrence of the space (the address returned by malloc will be lost) .
Fourth: freeing the memory allocated using malloc
You should free the memory allocated using malloc using free function which take the address of the memory allocated.
Your code should be like that:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (void) {
char str[100];
char *p = malloc(sizeof(char)*100); //Do NOT cast the return of malloc
printf("Enter something: ");
fgets(str, 100, stdin); //Use fgets to include the spaces between words
strcpy(p, str);//use stcpy to Not change the address of memory allocated
//p = strchr(str, ' '); -->This step will change the address
//of memory allocated using malloc
//puts (p + 1);
/*Instead you can do this*/
char *c = strchr(str, ' ');
puts(c+1);
// Check for the first space in given input string if found then
char *mem =p;
while (*p++)
if (*p == ' ' && *++p)
printf ("%s", p);
printf ("\n\n");
free(mem);
return 0;
}
Scanf %s only reads in a string up to the first whitespace and then stops, which is probably what is causing you problems. I would avoid scanf anyway, it's dangerous and can cause problems if you're not familiar with it. You could try fgets to read from stdin instead. See if this does what you want:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_LENGTH 100
int main (void)
{
char *str = (char *) malloc (sizeof(char) * MAX_LENGTH + 1);
bzero(str, MAX_LENGTH + 1);
printf("Enter something: ");
fgets(str, MAX_LENGTH, stdin);
// Remove the newline
if ((strlen(str) > 0) && (str[strlen (str) - 1] == '\n'))
{
str[strlen (str) - 1] = '\0';
}
char *p = strchr(str, ' ');
if (p != NULL)
{
// Pointing to the space, which we will skip
p++;
printf ("%s\n\n", p);
}
return 0;
}

cutting a string when a character is found

I wrote a function that cuts the string "hello world" to "hell" if a 'o' is found.
I keep getting a segmentation fault. I don't know where the mistake could be.
Could anyone help?
Thank you in advance.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* cutString(char* str, char del){
char *newstring =(char*) str;
malloc(sizeof(char)*strlen(str));
int i= 0;
for(; newstring[i]!='\0'&&newstring[i]!=del;i++);
if(i==strlen(newstring))
printf("not found");
else
newstring[i]='\0';
return newstring;
}
int main(){
cutString("Hello World",'o');
return 0;
}
There are two major problems with your code:
char *newstring =(char*) str makes newstring point to the old str. And since you pass a literal string (which is read only) you will have undefined behavior attempting to modify it.
malloc(sizeof(char)*strlen(str)); is a memory leak. And doesn't allocate space for the terminator.
The crash is probably because point one, when you attempt to modify the read-only string literal.
There are a number of problems in your code. The main problem is that you don't assign the return value from malloc to newstring. Besides that you need to malloc an extra byte for the string termination.
Further, your loop must copy characters from str into newstring.
In main you must assign the return value from the function to a char pointer variable to get hold of the new string.
Something like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* cutString(char* str, char del){
char *newstring = malloc(strlen(str) + 1); // malloc into newstring
int i= 0;
while (newstring[i]!='\0' && str[i] != del) // Stop when a) no more chars in str or b) "del" is found
{
newstring[i] = str[i]; // Copy character from str to newstring
++i;
}
newstring[i]='\0'; // Terminate the string
return newstring;
}
int main(){
char* newstring = cutString("Hello World",'o'); // Save the returned value
printf("%s\", newstring);
free(newstring);
return 0;
}
newstring[i]='\0';
This line is invalid. Modifying string literals is undefined behavior. I would suggest check this out :segmentation fault when using pointer
A better solution would be to use arrays instead of pointers

Getting string with C function

I need to get strings dynamically but as I need to get more than one string, I need to use functions. So far I wrote this
(I put //**** at places i think might be wrong)
char* getstring(char *str);
int main() {
char *str;
strcpy(str,getstring(str));//*****
printf("\nString: %s", str);
return 0;
}
char* getstring(char str[]){//*****
//this part is copy paste from my teacher lol
char c;
int i = 0, j = 1;
str = (char*) malloc (sizeof(char));
printf("Input String:\n ");
while (c != '\n') {//as long as c is not "enter" copy to str
c = getc(stdin);
str = (char*)realloc(str, j * sizeof(char));
str[i] = c;
i++;
j++;
}
str[i] = '\0';//null at the end
printf("\nString: %s", str);
return str;//******
}
printf in the function is working but not back in main function.
I tried returning void, getting rid of *s or adding, making another str2 and tring to strcpy there or not using strcpy at all. Nothing seems to working. Am I misssing something? Or maybe this is not possible at all
//Thank you so much for your answers
Getting the string part can be taken from this answer. Only put a \n as input to the getline funtion.
char * p = getline('\n');
Three things :-
don't cast malloc, check if malloc/realloc is successful and sizeof is not a function.
The problem is not with the function that you are using, but with the way you try copying its result into an uninitialized pointer.
Good news is that you don't have to copy - your function already allocates a string in dynamic memory, so you can copy the pointer directly:
char *str = getstring(str);
This should fix the crash. A few points to consider to make your function better:
main needs to free(str) when it is done in order to avoid memory leak
Store realloc result in a temporary pointer, and do a NULL check to handle out-of-memory situations properly
There are two things to take away from the lesson as it stands now:
(1) You should have one way of returning the reference to the new string, either as an argument passed by reference to the function OR as a return value; you should not be implementing both.
(2) Because the subroutine your teacher gave you allocates memory on the heap, it will be available to any part of your program and you do not have to allocate any memory yourself. You should study the difference between heap memory, global memory, and automatic (stack) memory so you understand the differences between them and know how to work with each type.
(3) Because the memory is already allocated on the heap there is no need to copy the string.
Given these facts, your code can be simplified to something like the following:
int main() {
char *str = getstring();
printf( "\nString: %s", str );
return 0;
}
char* getstring(){
.... etc
Going forward, you want to think about how you de-allocate memory in your programs. For example, in this code the string is never de-allocated. It is a good habit to think about your strategy for de-allocating any memory that you allocate.
Let's simplify the code a bit:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* getstring()
{
char c = 0;
int i = 0, j = 2;
char *str = NULL;
if ((str = (char*) malloc(sizeof(char))) == NULL)
return NULL;
printf("Input String: ");
while (c = getc(stdin)) {
if (c == '\n') break;
str = (char*) realloc(str, j * sizeof(char));
str[i++] = c;
j++;
}
str[i] = '\0';
printf("getstring() String: %s\n", str);
return str;
}
int main()
{
char *str = getstring();
printf("main() String: %s\n", str);
free(str);
return 0;
}
Then execute:
$ make teststring && ./teststring
cc teststring.c -o teststring
Input String: asdfasfasdf
getstring() String: asdfasfasdf
main() String: asdfasfasdf

Resources