I have made a strcpy() function
in C, and I am copying words from one array to other not just letters, but when I run it I am getting Segmentation fault what to do?
#include <stdio.h>
void strcpy1(char *dest[], char source[])
{
while ((*dest++ = *source++));
}
int main()
{
char source[3][20] = { "I", "made", "this" };
char dest[3][20];
strcpy1(&dest, source);
//printing destination array contents
for (int i = 0; i < 3; i++) {
printf("%s\n", dest[i][20]);
}
return 0;
}
There are multiple problems in your code:
the prototype for your custom strcpy1 function should be:
void strcpy1(char *dest[], char *source[]);
the arrays source and dest are 2D char arrays: a very different type from what strcpy1 expects, which are arrays of pointers. Change the definition to:
char *source[4] = { "I", "made", "this" };
char *dest[4];
you should pass the destination array as dest instead of &dest
the source array should have a NULL pointer terminator: it should be defined with a length of at least 4. Same for the destination array.
in the print loop dest[i][20] refers to a character beyond the end of the i-th string. You should just pass the string as dest[i].
Here is a modified version:
#include <stdio.h>
void strcpy1(char *dest[], char *source[])
{
while ((*dest++ = *source++));
}
int main()
{
char *source[4] = { "I", "made", "this" };
char *dest[4];
strcpy1(dest, source);
//printing destination array contents
for (int i = 0; dest[i]; i++) {
printf("%s\n", dest[i]);
}
return 0;
}
Note that it is somewhat confusing to name strcpy1 a function that has very different semantics from the standard function strcpy().
The %s specifier is for strings, eg, a char* referring to the first character of a string.
When you pass dest[i][20] to the printf function, it is not a char*. It is a single char, the 21st char (valid indices are 0-19, for a total of 20 elements).
So it is an array-out-of-bounds-index, and also, not a char* as printf expects.
printf("%s\n", dest[i][20]);
Related
Why this works:
#include <stdio.h>
void slice(char *st, int m, int n)
{
int i = 0;
while ((i + m) < n)
{
st[i] = st[i + m];
i++;
}
st[i-1] = '\0';
}
int main()
{
char st[] = "Hello";
slice(st, 1, 6);
printf("The value of string is %s\n", st);
return 0;
}
And this doesn't:
#include <stdio.h>
void slice(char *st, int m, int n)
{
int i = 0;
while ((i + m) < n)
{
st[i] = st[i + m];
i++;
}
st[i-1] = '\0';
}
int main()
{
char*st = "Hello";
slice(st, 1, 6);
printf("The value of string is %s\n", st);
return 0;
}
In first I initialized my string using:
char st[]="Hello"; (using array)
And in latter I used:
char*st="Hello"; (using pointer)
I'm kind of getting confused between these 2 initialization types, what's the key difference between declaring a string by using char st[]="Hello"; and by using char*st = "Hello";.
With char st[] = "Hello";, st[] is a modifiable array of characters. The call slice(st, 1, 6); takes the array st and converts to a pointer to the first element of the array. slice() then receives that pointer, a pointer to modifiable characters.
With char *st = "Hello";, st is a pointer that points to a string literal "Hello". With the call slice(st, 1, 6);, the function receives a copy of the pointer - a pointer to the string literal. Inside slice(), code st[i] = ... is attempting to modify a string literal, that is undefined behavior (UB). It might work, it might fail, it might work today and fail tomorrow - it is not defined.
Do not attempt to modify a string literal.
... passing strings to a function ...
In both cases, code does not pass a string to slice(), but a pointer to a string. Knowing that subtle distinction helps in understanding what is truly happening.
This is an artifact of old syntax in C:
char * s = "Hello world!";
is a non-const character pointer to const memory. It is still permitted by syntax, but the string is still not a mutable object. To be pedantic it should really be written as:
const char * s = "Hello world!";
In contrast:
char s[] = "Hello world!";
allocates a local (on the stack), mutable array and copies the string data to it (from wherever the non-mutable copy is stored in memory). Your function can then do as it likes to your local copy of the string.
The type char [] is different from the type char* (char* is a variable - int. but char[] is an array which is not a variable). However, an array name can be used as a pointer to the array.
So we can say that st[] is technically similar to *str .
the problem in the 2nd version of your code
If you have read-only strings then you can use const char* st = "hello"; or simply char* st = "hello"; . So the string is most probably be stored in a read-only memory location and you'll not be able to modify it.
However, if you want to be able to modify it, use the malloc function:
char *st= (char*) malloc(n*sizeof(char)); /* n-The initial size that you need */
// ...
free(st);
**So to allocate memory for st, count the characters ("hello"-strlen(st)=5) and add 1 for this terminating null character , and functions like scanf and strcpy will add the null character;
so the code becomes :
#include <stdio.h>
void slice(char *st, int m, int n)
{
int i = 0;
while ((i + m) < n)
{
st[i] = st[i + m];
i++;
}
st[i-1] = '\0';
}
int main()
{
char *st =malloc(6*sizeof(char)) ;
const char *cpy="hello";
strcpy(st, cpy); /* copies the string pointed by cpy (including the null character) to the st. */
slice(st, 1, 6);
printf("The value of string is %s\n", st);
return 0;
}
you can fill your string also by a for loop or by scanf() .
in the case of a large allocation you must end your code with free(st);
I have been trying to solve this issue for whole day, and could not do it on my own. Searching the internet didn't help me solve it either
So, this the function prototype:
void invert(char **arr, int n);
First argument is an array of strings, and the second one is number of strings in an array.
This is my code:
#include <stdio.h>
#include <string.h>
void invert(char** arr, int n)
{
int i, j, len;
for(j=0;j<n;j++)
{
len=strlen(arr[j]);
for(i=0;i<len/2;i++)
{
char tmp = arr[j][i];
arr[j][i] = arr[j][len - i - 1];
arr[j][len - i - 1] = tmp;
}
}
}
int main()
{
int n=3, i;
char **arr;
arr[0]="John";
arr[1]="Doe";
arr[2]="Programmer";
invert(arr, n);
for(i=0;i<3;i++)
{
printf("%s ",arr[i]);
}
}
The code breaks when it reaches the line:
arr[j][i] = arr[j][len - i - 1];
and I can't figure out why.
The function receives an array of strings perfectly (tested it with some printf statements for characters of specific strings), and the char tmp succesfully recieves a correct character, but the program crashed when it reaches the line mentioned earlier. Printf statements after that line don't work.
Did I miss anything? Can someone explain what am I doing wrong? Thank you!
For starters this code snippet
char **arr;
arr[0]="John";
arr[1]="Doe";
arr[2]="Programmer";
invokes undefined behavior because the pointer arr is uninitialized and has an indeterminate value.
Moreover this approach in any case is wrong because you may not change string literals.
What you need is to declare a two-dimensional array as for example
enum { N = 11 };
//...
char arr[3][N] =
{
"John", "Doe", "Programmer"
};
In this case the function declaration will look like
void invert( char arr[][N], int n );
The enumeration must be declared before the function declaration.
Instead of the two-dimensional array you could declare an array of pointers like
char s1[] = "John";
char s2[] = "Doe";
char s3[] = "Programmer";
char * arr[3] = { s1, s2, s3 };
In this case the function declaration may be as shown in your question
void invert(char** arr, int n)
So what you need to do with minimal changes is to substitute this code snippet
char **arr;
arr[0]="John";
arr[1]="Doe";
arr[2]="Programmer";
for this code snippet
char s1[] = "John";
char s2[] = "Doe";
char s3[] = "Programmer";
char * arr[3] = { s1, s2, s3 };
To begin with, what you have here:
char **arr;
is a pointer to pointer to char.
Secondly, even if you had an array of pointers to char, like so :
char *arr[3];
And then assigning each string literal :
arr[0]="John";
arr[1]="Doe";
arr[2]="Programmer";
would still invoke Undefined behavior, since you are attempting to modify a string literal which is read only.
What you need is, either a 2D array of chars :
char arr[][100] = {"John", "Doe", "Programmer"};
and also change the function signature to :
void invert(char arr[][100], int n)
or you have to dynamically allocate memory and use a function like strcpy(), strdup(), memcpy() etc :
char **arr;
arr = malloc(n * sizeof(char *)); // or sizeof(*arr)
if (arr == NULL) {
fprintf(stderr, "Malloc failed to allocate memory\n");
exit(1);
}
arr[0] = strdup("John"); // good idea to also check if strdup returned null
arr[1] = strdup("Doe");
arr[2] = strdup("Programmer");
invert(arr, n);
for(i=0;i<3;i++)
{
printf("%s ",arr[i]);
}
for (i = 0; i < 3; i++) {
free(arr[i]);
}
free(arr);
Code is crash unexpectedly, any logical error in this code?
Purpose of this code is to reverse the string.
When I try to debug the code, the issue seems in the strrev function. But could not catch up with the exact issue.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *s[]={"To err is hman..",
"man is wild",
"Dream big thought",
"do it myself self",
};
void xstrrev(char *a1,char *a2,char *a3,char *a4)
{
strrev(a1);
strrev(a2);
strrev(a3);
strrev(a4);
}
int main()
{
for(int i=0;i<4;i++)
{
printf("%s\n",s[i]);
}
printf("Hello world!\n");
xstrrev(s[0],s[1],s[2],s[3]);
for(int i=0;i<4;i++)
{
printf("%s\n",s[i]);
}
return 0;
}
This declaration
char *s[]={"To err is hman..",
"man is wild",
"Dream big thought",
"do it myself self",
};
declares an array of pointers to string literals. Though in C (opposite to C++) string literals have types of non-constant character arrays nevertheless you may not change string literals. Any attempt to change a string literal results in undefined behavior.
Instead of the array of pointers declare a two-dimensional character array like
char s[][18] =
{
"To err is hman..",
"man is wild",
"Dream big thought",
"do it myself self",
};
Pay attention to that the function strrev is not a standard C function.
I assume strrev takes a char * pointer to a null-terminated string and reverses the order of the char elememts of the string in place. That means that it cannot be used to reverse a string literal because modification of a string literal results in undefined behavior.
OP's array s contains pointers to string literals that are passed to strrev, resulting in undefined behavior. To prevent that, the code needs to be changed so that the array s contains pointers to modifiable strings. That can be done either by creating each string as a named array of char, or by constructing each string as an anonymous compound literal.
Version using named arrays of char:
static char s_0[] = "To err is hman..";
static char s_1[] = "man is wild";
static char s_2[] = "Dream big thought";
static char s_3[] = "do it myself self";
char *s[] = { s_0, s_1, s_2, s_3 };
Version using compound literals:
char *s[] = {
(char []){ "To err is hman.." },
(char []){ "man is wild" },
(char []){ "Dream big thought" },
(char []){ "do it myself self" },
};
In both of the cases above, the string literals are only being used to initialized arrays of char that are modifiable. The pointers in array s point to these modifiable arrays of char, so there is no problem passing them to strrev.
Regarding strrev, that function is not defined by the C standard, but it might be an extended standard library function of some implementation. All function names beginning with str, mem, or wcs are reserved by the C standard.
Well as #Vlad from Moscow and #kaylum mentioned, that you can't modify the content of an array of pointers to string literals, so rather than that you can do it with allocation, as shown in the below code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void ft_strrev(char *str)
{
char keep;
int len;
int i;
int stop;
len = strlen(str);
stop = len / 2;
i = 0;
while (len > stop)
{
keep = str[i];
str[i] = str[len - 1];
str[len - 1] = keep;
i++;
len--;
}
}
void xstrrev(char *a1,char *a2,char *a3,char *a4)
{
ft_strrev(a1);
ft_strrev(a2);
ft_strrev(a3);
ft_strrev(a4);
}
int main()
{
char **s;
s = calloc(sizeof(char*), 5);
s[0] = strdup("To err is hman..");
s[1] = strdup("man is wild");
s[2] = strdup("Dream big thought");
s[3] = strdup("do it myself self");
for(int i=0;i<4;i++)
{
printf("%s\n",s[i]);
}
printf("Hello world!\n");
xstrrev(s[0],s[1],s[2],s[3]);
for(int i=0;i<4;i++)
{
printf("%s\n",s[i]);
}
return 0;
}
and since I can't use strrev() function with my compiler, because This is a non-standard function that works only with older versions of Microsoft C, I did my own reverse function ft_strrev.
This relates to C. I am having some trouble understanding how I can assign strings to char pointers within arrays from a function.
#include <stdio.h>
#include <string.h>
void function(char* array[]);
int main(void)
{
char* array[50];
function(array);
printf("array string 0: %s\n",array[0]);
printf("array string 1: %s\n",array[1]);
}
void function(char* array[])
{
char temp[] = "hello";
array[0] = temp;
array[1] = temp;
return;
}
Ideally, I would like the main printf function to return
array string 0: hello
array string 1: hello
But I'm having trouble understanding arrays of pointers, how these pass to functions and how to manipulate them in the function. If I declare a string like char temp[] = "string" then how do I assign this to one of the main function array[i] pointers? (assuming I have my jargon right)
char temp[] = "hello"; only creates a local, temporary array inside the function. So when the function exists, the array will be destroyed.
But with array[0] = temp; you're making array[0] point to the local array temp.
After the function returns, temp doesn't exist anymore. So accessing array[0] which pointed to temp will cause undefined behavior.
You could simply make temp static, so it also exists outside the function:
static char temp[] = "hello";
Or, you could copy the "hello" string to array[0] and array[1]. For copying C-strings, you normally use strcpy.
char temp[] = "hello";
strcpy(array[0], temp);
strcpy(array[1], temp);
However, before copying you need to make sure array[0] and array[1] point to memory that has enough space to hold all characters of "hello", including the terminating null character. So you have to do something like this before calling strcpy:
array[0] = malloc(6);
array[1] = malloc(6);
(6 is the minimum numbers of characters that can hold "hello".)
how do I assign this to one of the main function array[i] pointers
Arrays cannot be assigned.
A pointer cannot hold an array, it can only refer to an array. For the latter the pointer needs to get an array's address assigned.
Referring 1.
This
char temp[] = "hello";
isn't an assigment, but an initialisation.
This
char temp[];
temp[] = "hello";
would not compile (the 2nd line errors), as an array cannot be assigned.
Referring 2.
This
char* array[50];
defines an array of 50 pointers to char, it could reference 50 char-arrays, that is 50 C-"strings". It cannot hold the C-"strings" themselfs.
Example
Applying what is mentioned above to your code whould lead to for example the following:
#include <stdio.h>
#include <string.h>
void function(char* array[]);
int main(void)
{
char* array[50];
/* Make the 1st two elements point to valid memory. */
array[0] = malloc(42); /* Real code shall test the outcome of malloc()
as it might fail and very well return NULL! */
array[1] = malloc(42);
function(array);
printf("array string 0: %s\n",array[0]);
printf("array string 1: %s\n",array[1]);
return 0;
}
void function(char* array[])
{
char temp[] = "hello";
/* Copy the content of temp into the memory that was allocated to
the array's 1st memebrs in main(). */
strcpy(array[0], temp);
strcpy(array[1], temp);
return;
}
first, you need to allocate the destination.
second, char temp[] = "hello"; in function() is local variable. you cannot use their outside of the function. use strcpy to copy the content.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void function(char* dest)
{
char temp[] = "hello";
strcpy(dest, temp);
return;
}
int main(void)
{
// or just char dest[10] = {0};
char *dest = malloc(10);
function(dest);
printf("dest: %s\n", dest);
}
In you program, you defined char* array[50];, so you need to create memory space for each item:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void function(char* a[])
{
char temp[] = "hello";
strcpy(a[0], temp);
strcpy(a[1], temp);
return;
}
int main(void)
{
char *a[50];
int i = 0;
for (i = 0; i < 50; ++i)
a[i] = malloc(10);
function(a);
printf("a[0]: %s\n", a[0]);
printf("a[1]: %s\n", a[1]);
}
#include <stdio.h>
#include <string.h>
char Jones(char, char);
int main() {
char name[]="Andrew";
char surname[]="Jones";
char result[80];
result=Jones(name, surname);
puts(result);
return 0;
}
char Jones(char name, char surname)
{
char result[80];
int length;
length = strlen(surname);
for (int i=0; i<50; i++)
{
result[length+i] = name[i];
}
return result;
}
The program does not compile and i dont know why. It is supposed to read two strings and swap their places. It should display eg. "Jones Andrew".
Here's one problem:
char name[]="Andrew";
char surname[]="Jones";
char result[80];
wynik=Jones(name, surname);
This calls Jones() with character arrays (which will decay to character pointers), but the function is declared to accept single characters only.
You should change the function to take char *name, char *surname, since it really does seem to expect strings.
Further, you can't return a character array like you're doing in Jones(), you need to read up quite a bit on how to work with strings in C.
Also, wynik looks undeclared, that'll also make it fail to build.
There's a few errors:
char Jones(char, char);
This takes just a single char, not a char * which you need for a string.
result=Jones(name, surname);
Here result is an array. In C, you cannot assign to an array.
char Jones(char name, char surname)
{ char result[80];
...
return result;
}
Here you return result which is a local variable. But to return a string, you'd need to return a char*. But that char* would point to a local variable within the Jones function, which is no longer valid when the function ends. One solution is to pass in a buffer where you write the result that the caller owns.
Your algorithm for combining the surename and name is also wrong, you never do anything with the surename.
You'll need to do this:
char *Jones(char*, char* , char *);
int main() {
char name[]="Andrew";
char surname[]="Jones";
char result[80];
char *p;
p = Jones(name, surname, result);
puts(p);
return 0;
}
char *Jones(char *name, char *surname, char *result)
{
int length;
int i,k;
length = strlen(surname);
for (i=0; i<length ; i++)
{
result[i] = surname[i];
}
result[i++] = ' '; //add a space
length = strlen(name);
for (k=0; k<length ; k++, i++)
{
result[i] = name[k];
}
result[i] = 0; //add nul terminator to end the string
return result;
}
The conatenation could be simplified in many ways, e.g. to
strcpy(result, surename);
strcat(result, " ");
strcat(result, name);
or the Jones function could just do:
sprintf(result, "%s %s", surename, name);
In all cases, the function is rather fragile, as it's easy to overflow the result buffer if you pass in something else that does not fit within the result buffer.
1) The name and surname are char array and not single char so you have to change the input parameters types of your function Jones() the input parameters types should be char name[] (char array) or char *name (pointer to array of char)
2) You can not return an array defined locally and statically in the function. and if you want to return a string from the function, the string should be constant or it should be a buffer allocated dynamically (with malloc, calloc, realloc) into the function And for both cases the function type should be char *Jonas() and not char Jonas()
Or you can pass the result array via input parametr. and in this case you can fill it into the function.
void Jones(char *name, char *surname, char *result)
and in the main:
char result[80];
Jones(names, surname, result);
3) The following for loop is missing some thing
for (int i=0; i<50; i++)
{
result[length+i] = name[i];
}
The result elements from element 0 to element length are containing garbage because the result array is not initiated. so when you printf the result array you will get garbages printed. You have to initiate elements between 0 to length in the result array
#include <stdio.h>
#include <string.h>
char* Jones(char*, char*);
int main() {
char name[]="Andrew";
char surname[]="Jones";
puts(Jones(name,surname));
return 0;
}
char* Jones(char *name, char *surname)
{
strcat(surname," ");
strcat(surname,name);
return surname;
}