2 strings are given, second word will be append to first one and 3rd variable will store this. For example;
char *str1 = "abc";
char *str2 = "def";
char *str3 = "abcdef"; //should be
Here is my code, I get runtime error:
#include <stdio.h>
#include <malloc.h>
void append(char *str1, char *str2, char *str3, int size1, int size2)
{
int i=0;
str3 = (char*) malloc(size1+size2+1);
str3 = str1;
while (str2[i] != '\0') {
str3[i+size1] = str2[i];
i++;
}
str3[size1+size2] = '\0';
}
int main()
{
char *str1 = "abc";
char *str2 = "def";
char *str3;
append(str1, str2, str3, 3, 3);
return 0;
}
str3 = (char*) malloc(size1+size2+1);
str3 = str1;
Here's your problem. Doing this replaces the pointer to the correct amount of space from malloc to the pointer where str1 is contained. Keeping with your loop design, change this to:
str3 = malloc(size1+size2+1);
for (int j = 0; str1[j] != '\0'; j++)
str3[j] = str1[j];
Also, see this question/answer about casting the result of malloc in C:
Do I cast the result of malloc?
There is another issue with the code. You pass pointer by value. So any malloc inside a function will do only local changes. After function ends your pointer will still point to the old value. You should pass a pointer to pointer if you want to change it. See an example:
#include <stdio.h>
char *c = "Second";
void assign(char *s) { s = c; }
int main()
{
char *str = "First";
assign(str);
printf("String after assign: %s\n", str);
return 0;
}
After running the program you will see 'First' in you console. The correct code is:
#include <stdio.h>
char *c = "Second";
void assign(char **s) { *s = c; }
int main()
{
char *str = "First";
assign(&str);
printf("String after assign: %s\n", str);
return 0;
}
#include <stdio.h>
#include <stdlib.h> //to standard
#include <string.h>
char *append(const char *str1, const char *str2, int size1, int size2){
//parameter char *str3 is local variable.
//It is not possible to change the pointer of the original.
//str3 = str1;//<<-- memory leak
//str3[i+size1] = str2[i];//<<-- write to after str1(can't write!)
char *str3 = (char*) malloc(size1+size2+1);
memcpy(str3, str1, size1);//copy to alloc'd memory.
memcpy(str3 + size1, str2, size2);//copy to after str1
str3[size1+size2] = '\0';
return str3;
}
int main(){
char *str1 = "abc";
char *str2 = "def";
char *str3;
str3 = append(str1, str2, 3, 3);
printf("%s\n", str3);
return 0;
}
Related
I'm trying to write a simple C function to copy the contents of one char array to another using pointer arithmetic. I can't seem to get it working, can you tell me where I'm going wrong?
#include <stdio.h>
#include <stdlib.h>
void copystr(char *, const char *);
int main()
{
char hello[6] = "hello";
const char world[6] = "world";
copystr(&hello, &world);
return 0;
}
void copystr(char *str1, const char *str2)
{
*str1 = *str2; //copy value of *str2 into *str1
printf("%s %s", *str1, *str2); //print "world" twice
}
Help appreciated, thanks.
EDIT:
Here is the working code:
#include <stdio.h>
#include <stdlib.h>
void copystr(char *, const char *);
int main()
{
char hello[6] = "hello";
const char world[6] = "world";
copystr(hello, world);
printf("%s %s", hello, world);
return 0;
}
void copystr(char *str1, const char *str2)
{
/*copy value of *str2 into *str1 character by character*/
while(*str2)
{
*str1 = *str2;
str1++;
str2++;
}
}
You are only copying the first character of the string.
void copystring(char* str1, const char* str2)
{
while(*str2)
{
*str1 = *str2; //copy value of *str2 into *str1
str1++;
str2++;
}
}
and then in main, after calling copystring
printf("%s %s", hello, world); //print "world" twice
But please don't do this! Use strncpy in real life, if working with plain C strings.
I'm having trouble getting the parameters correct in my cat function. I would think since I'm changing temp that I would need to pass the address since I want to be able to see that in main. I think I'm getting screwed up by the decaying.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* Swaps strings by swapping data*/
void swap2(char *str1, char *str2)
{
char *temp = (char *)malloc((strlen(str1) + 1) * sizeof(char));
strcpy(temp, str1);
strcpy(str1, str2);
strcpy(str2, temp);
free(temp);
}
void cat(char *temp, char *strings_line_tokens[])
{
strcat (temp,strings_line_tokens[1]);
strcat (temp,strings_line_tokens[2]);
strcat (temp,strings_line_tokens[3]);
}
int main()
{
char str1[10] = "geeks";
char str2[10] = "forgeeks";
char temp[80] = {0};
char *strings_line_tokens[503] = {0};
int lower_bound_of_big_boy_counter = 0;
strings_line_tokens[0] = malloc(strlen("string")+1);
strcpy(strings_line_tokens[0], "string");
strings_line_tokens[1] = malloc(strlen("string1")+1);
strcpy(strings_line_tokens[1], "string1");
strcpy (temp,strings_line_tokens[0]);
lower_bound_of_big_boy_counter++;
cat(&temp, strings_line_tokens)
printf("temp is %s", temp);
swap2(str1, str2);
printf("str1 is %s, str2 is %s", str1, str2);
getchar();
return 0;
}
Working code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
/* Swaps strings by swapping data*/
void swap2(char *str1, char *str2)
{
char *temp = (char *)malloc((strlen(str1) + 1) * sizeof(char));
strcpy(temp, str1);
strcpy(str1, str2);
strcpy(str2, temp);
free(temp);
}
void cat(char *temp, char *strings_line_tokens[])
{
strcat (temp,strings_line_tokens[1]);
strcat (temp,strings_line_tokens[2]);
}
int main()
{
char str1[10] = "geeks";
char str2[10] = "forgeeks";
char temp[80] = {0};
char *strings_line_tokens[503] = {0};
int lower_bound_of_big_boy_counter = 0;
strings_line_tokens[0] = malloc(strlen("string")+1);
strcpy(strings_line_tokens[0], "string");
strings_line_tokens[1] = malloc(strlen("string1")+1);
strcpy(strings_line_tokens[1], "string1");
strings_line_tokens[2] = malloc(strlen("string2")+1);
strcpy(strings_line_tokens[2], "string1");
strcpy (temp,strings_line_tokens[0]);
lower_bound_of_big_boy_counter++;
cat(temp, strings_line_tokens);
printf("temp is %s \n", temp);
swap2(str1, str2);
printf("str1 is %s, str2 is %s\n", str1, str2);
getchar();
return 0;
}
http://ideone.com/rQM5qL
temp has type char[80], and &temp has type char (*)[80], which is not compatible with char *, which cat() wants, as the message says.
The array temp will be automatically converted to a pointer to the first element of the array when it is used as function parameter (more generally, operands of operators other than sizeof and unary &), so you don't have to use & here.
In conclusion, try cat(temp, strings_line_tokens); (Don't forget the semicolon!)
cat(&temp, strings_line_tokens)
must be
cat(temp, strings_line_tokens);
^ also don't forget the ;
temp after conversion has type char * but &temp has type pointer to char [80].
I want to do in C, what can be achieved in Java as follows
String str = "hello";
System.out.println(str + 'a');
I have written the following.
1. It doesn't work
2. Is there an easier way to do this in C, something that can be achieved in java in a single line.
#include <stdio.h>
char* charcat(char str[], char c);
int main(void)
{
char str[] = "hello";
printf("%s\n",charcat(str,'a'));
}
char* charcat(char str[], char c)
{
char newstr[] = {c,'\0'};
char temp[20];
strcpy(temp,str);
strcat(temp,newstr);
return temp;
}
EDIT :
I have edited based on ameyCU's response.
char* charcat(char str[], char c);
int main(void)
{
char str[] = "hello";
printf("%s\n",charcat(str,'a'));
}
char* charcat(char str[], char c)
{
char* temp;
char newstr[] = {c,'\0'};
temp = malloc((strlen(str) + 1)* sizeof(char));
strcpy(temp,str);
return strcat(temp,newstr);
}
EDIT 2:
char* charcat(char str[], char c);
int main(void)
{
char str[] = "hello";
char temp[20];
strcpy(temp,str);
printf("%s\n",charcat(temp,'a'));
}
char* charcat(char str[], char c)
{
char newstr[] = {c,'\0'};
return strcat(str,newstr);
}
I think what you were trying to do was this:
char* charcat(char str[], char c)
{
char newstr[] = {c,'\0'};
char *temp=(char *)malloc((strlen(str)+1+1)*sizeof(char));
strcpy(temp,str);
strcat(temp,newstr);
return temp;
}
make sure you free() the pointer.
You can use strcat() function
char str1[20]="hello";
strcat(str1,"c");
printf("%s",str1);
Problem is that you return a local variable.
return temp;
temp is local variable and its scope is just inside the function it is declared.
After concatenation -strcat(temp,newstr);
You can do this -
strcpy(str,temp);
return str;
But this will also change the contents of original array.
EDIT
To keep original array intact assign a pointer to string in function and return the pointer .
And also to use functions like strcpy and strcat you need to include string.h header.
This uses snprintf() to get the required length for the target string. Memory is allocated and then snprintf() creates the target string.
#include<stdio.h>
#include<stdlib.h>
char* charcat(char str[], char c);
int main ( ) {
char str[] = "hello";
char *output = NULL;
printf ( "str-> %s\n\n", str);
if ( ( output = charcat ( str, 'a'))) {//successful return of pointer
printf ( "output-> %s\n", output);
free ( output);//release memory
}
return 0;
}
char* charcat(char str[], char c)
{
char *temp = NULL;
int length = 0;
length = snprintf ( NULL, 0, "%s%c", str, c);//get required length
if ( ( temp = malloc ( length + 1))) {//allocate plus one for '\0'
snprintf ( temp, length + 1, "%s%c", str, c);//malloc succeeds make target
}
return temp;
}
It is always better to use strncat() instead of strcat to avoid buffer overflows.
#include <cstdio>
#include <cstring>
int main ()
{
char str[20] = "hello";
strncat (str, "a", sizeof(str) - strlen(str) - 1);
printf("%s",str);
return 0;
}
Output:
helloa
RUN SUCCESSFUL (total time: 49ms)
Something like Java in a single line
// String str = "hello";
// System.out.println(str + 'a');
const char *str = "hello";
printf("%s%c\n", str, 'a');
Or is one wants to print a concatenated string, we need to do memory management.
char *charcatconst char *src, int ch) {
size_t len = strlen(src);
char *s = memcpy(malloc(len+2), src, len); // Out-of-memory check omitted.
s[len] = ch;
s[len+1] = '\0';
return s;
}
// simple usage, but a memory leak
puts(charcat("hello", 'a'));
// Better to free memory explicitly
char *s = charcat("hello", 'a');
puts(s);
free(s);
This question already has answers here:
What is the difference between char s[] and char *s?
(14 answers)
Closed 9 years ago.
I have a piece of code that works fine on char[] but gives a run-time error when performed on a char*.
#include <stdio.h>
#include <string.h>
void rotateLeft(char* str, int pos, int size){
char temp;
int i;
for(i=pos; i < size-1; i++) {
temp = str[i];
str[i] = str[i+1];
}
str[size-1] = temp;
}
void removeAllDups(char* str) {
int size = strlen(str);
int i,j;
char cur;
for (i=0; i<size; i++) {
cur = str[i];
for(j=i+1; j<size;) {
if (str[j] == cur) {
rotateLeft(str, j, size);
size--;
str[size] = '\0';
}
else {
j++;
}
}
}
}
int main(void) {
char str1[] = "hello there";
char* str2 = malloc(sizeof(char)*14);
strcpy (str2, "goodbye matey");
removeAllDups(str1); // succeeds
printf("%s\n", str1);
removeAllDups(str2); // fails
printf("%s\n", str2);
free(str2);
return 0;
}
Run-time error is given when removeAllDups(str2) is reached. What is my problem?
char* str2 = "goodbye matey"; initializes str2 with a pointer to data that should not be changed. While str2 points to such data, modiying it leads to UB.
char str1[] = "hello there";
char* str2 = "goodbye matey";
removeAllDups(str2); // fails
str2 = str1;
removeAllDups(str2); // OK
str2 = "goodbye matey2";
removeAllDups(str2); // fails
str2 = strdup("goodbye matey3");
removeAllDups(str2); // OK
char* str2 = "goodbye matey" is equivalent to declaring static const char str2[] = "goodbye matey". So you cannot modify the content pointed to by str2.
I'm trying to create a split function using strtok and a dynamic array.
However, I have no clue where things are going wrong: No informative error messages.
It does say segmentation fault, but I don't understand how the heap is corrupt or whatever causes that happens.
Would someone be willing to explain to me what is wrong and how to do it correctly?
Edit 11:16 CST code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **toArray(char **array, char str[], char sep[], int *count);
char** my_split(const char* str, char delim, int* size);
int main(int argc, char* argv[]) {
char* test = "Hello there lol";
int *count = 0;
char **array = malloc(sizeof(char*) * 5);
toArray(array, test, " ", count);
printf("Count: %d\n", *count);
int array_i;
for (array_i = 0; array_i < *count; array_i++) {
printf("array %d: %s\n", array_i, array[array_i]);
free(array[array_i]);
}
free(array);
return 1;
}
char **toArray(char **array, char str[], char sep[], int *count) {
char *temp = str;
temp = strtok(temp, sep);
array[0] = temp;
*count = 1;
while ((temp = strtok(NULL, sep)) != NULL ) {
array[(*count)++] = temp;
}
return array;
}
Compiler messages are our friend. I simpley used them to track down your issues. Try the following, and compare whats been done to what you had. Special attention to decalration and usage of pointer variables... :)
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char **toArray(char **array, char str[], char sep[], int *count);
int main(int argc, char* argv[]) {
char test[] = "Hello there lol";
int count = 0;
char **array = malloc((sizeof(char*) * 5) +1); //added "+ 1" here, read why
toArray(array, test, " ", &count); //in comment below
printf("Count: %d\n", count);
int array_i;
for (array_i = 0; array_i < count; array_i++) {
printf("array %d: %s\n", array_i, array[array_i]);
//free(array[array_i]);
}
getchar();
free(array);
return 1;
}
char **toArray(char **array, char str[], char sep[], int *count) {
char *temp = str;
temp = strtok(temp, sep);
array[0] = temp;
*count = 1;
while ((temp = strtok(NULL, sep)) != NULL) {
array[(*count)++] = temp;
}
return array;
}
[EDIT] Example Output:
Also. The line char **array = malloc(sizeof(char*) * 5);, needed to be
char **array = malloc(sizeof(char*) * 5 + 1); because "hello" is actually 5 chars plus a NULL char, '\0'.
Some rules of thumb for C string(s).
1) when using malloc or calloc, don't forget to allow room for '\0'.
`char *buf1;` //buffer needed to manipulate buf2
`char buf2[]="someString";`
`buf1 = malloc(strlen(buf2)+1);` or `buf1 = malloc(sizeof(buf2));`
(note:, no '+1'. see '4)' below. )
2) clear (initialize) new allocated variable before use. eg:
memset(buf, 0, strlen("someString")+1); //preferred, all bytes are zeroed
OR
buf[0]=0; //useful, but use with care (only first byte is zeroed.)
3) Free all dynamically allocated memory when done with it. Eg:
free(buf);
4) Using strlen() function or sizeof() macro. (both popular for use in [mc]alloc())
Given:
char *buf1 ="Hello"; //6 characters |H|e|l|l|o|\0|
char buf2[] ="Hello"; //6 characters |H|e|l|l|o|\0|
char buf3[5]="Hello"; //5 characters |H|e|l|l|o|
char buf4[5]="Hel"; //4 characters |H|e|l|\0| |
char buf5[5]="Helloo";//should get compile error, too many initializers
Compare strlen() - sizeof() results:
strlen(buf1); //->5 (requires +1 in malloc for new variable req'd to hold "Hello\0")
sizeof(buf1); //->4 (returns sizof (char *), not # chars in string)
strlen(buf2); //->5 (requires +1 in malloc for new variable req'd yo hold "Hello\0")
sizeof(buf2); //->6 (counts all chars, including '\0')
strlen(buf3); //-> (error: Missing terminating NULL in string argument)
sizeof(buf3); //->5 (counts all chars, but there is no '\0' in this string - wrong!)
strlen(buf4); //->3 (counts chars, but not '\0')
sizeof(buf4); //->5 (counts ALL allocated space, including '\0')
You are passing char *test = "Hello there lol"; to your toArray(). Unfortunately, the string is not modifiable, so when you try to modify it with strtok(), you get a segmentation fault.
The simplest fix is:
char test[] = "Hello there lol";
You also have:
int *count = 0;
and you call the function with:
toArray(array, test, " ", count);
You need an integer, and to pass its address:
int count = 0;
...
toArray(array, test, " ", &count);
You were also trying to free the strings that were pointed at by the elements in array, but those were never allocated (they are parts of the string test). Don't free what was not allocated with malloc() et al.
With those fixes in place, this code works:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char **toArray(char **array, char str[], char sep[], int *count);
int main(void)
{
char test[] = "Hello there lol";
int count = 0;
char **array = malloc(sizeof(char *) * 5);
toArray(array, test, " ", &count);
printf("Count: %d\n", count);
for (int i = 0; i < count; i++)
printf("array %d: %s\n", i, array[i]);
free(array);
return 0;
}
char **toArray(char **array, char str[], char sep[], int *count)
{
char *temp = str;
temp = strtok(temp, sep);
array[0] = temp;
*count = 1;
while ((temp = strtok(NULL, sep)) != NULL)
array[(*count)++] = temp;
return array;
}
Output:
Count: 3
array 0: Hello
array 1: there
array 2: lol