use strcat with strcpy occur problems - c

I have a problem when use strcat function. I have no idea.please help me.thanks
char dst[5]="hello";
char *a = "12345";
char *b = "54321";
//work
strcat(strcpy(dst, a), b);
printf("one==%s\n",dst);
//error
strcpy(dst, a);
strcat(dst, b);
printf("two==%s\n",dst);

The problem with both versions is that you are writing past the end of dst. Both a and b require six bytes including the NUL terminator; dst only has space for five.
This results in undefined behaviour.
The nature of undefined behaviour is such that it may or may not manifest itself. If it does, it could be in fairly arbitrary ways.

You dont allocate correctly your memory on your dst pointer, here is a working code:
int main()
{
char *dst;
char *a = strdup("12345");
char *b = strdup("54321");
dst = malloc(100);
dst = strdup("hello");
strcat(strcpy(dst, a), b);
printf("one==%s\n",dst);
strcpy(dst, a);
strcat(dst, b);
printf("two==%s\n",dst);
}

PROGRAM:
#include<string.h>
#include<stdio.h>
int main()
{
char dst[15]="hello";
char *a = "12345";
char *b = "54321";
//work
strcat(strcpy(dst, a), b);
printf("one==%s\n",dst);
//error
strcpy(dst, a);
strcat(dst, b);
printf("two==%s\n",dst);
return 0;
}
OUTPUT:
# 1: hide clone input 8 seconds ago
result: success time: 0s memory: 2684 kB returned value: 0
input: no
output:
one==1234554321
two==1234554321
EDIT:
Instead of 15 you can use 11 as well.. hope you understood the purpose of your code..

Related

Swap strings using strcpy() in a function

i know this is a very simple question but i'm new and a bit down here.. i'm learning more about how to use functions, and i can get this to work if it was simply in main, or i can use another way, but i'm trying to solve it using strcpy(), and i dont want to change the main, everythijg should be in the function, any help is very much appreciated.
char swap_char(char *s1, char *s2) {
printf("before swapping : swap_char(\"%s\", \"%s\")\n", s1, s2);
char temp[50];
strcpy(temp, s1);
strcpy(s1, s2);
strcpy(s2, temp);
printf("After swapping : swap_char(\"%s\", \"%s\")\n", s1, s2);
}
main() {
swap_char("please","work");
}
"please" has 7 characters (including the terminator), but "work" only has 5 characters. There is enough space for the first string to contain "work", but the second string does NOT have enough space to contain "please" in it.
Your code has literal strings "please" and "work", which means they are very likely in READ ONLY memory, and cannot be changed or overwritten.
Fixing these two problems I get:
char swap_char(char *s1, char *s2) {
printf("before swapping : swap_char(\"%s\", \"%s\")\n", s1, s2);
char temp[50];
strcpy(temp, s1);
strcpy(s1, s2);
strcpy(s2, temp);
printf("After swapping : swap_char(\"%s\", \"%s\")\n", s1, s2);
}
int main() {
char alpha[20] = "please"; // Declare space 20: MORE than enough space for either string
char beta[20] = "work"; // Also, use a local array, which is NOT read-only, and can be changed.
swap_char(alpha,beta);
return 0;
}
Output
Success #stdin #stdout 0s 5524KB
before swapping : swap_char("please", "work")
After swapping : swap_char("work", "please")
The first step is reading the docs to see how it can be used and see if they have any helpful examples.
The first issue here is we don't know if we will have enough space to complete this task. Instead we can malloc space dynamically to make sure we don't run into issues.
// We don't need to return a char
void swap_char(char *s1, char *s2) {
printf("before swapping : swap_char(\"%s\", \"%s\")\n", s1, s2);
// Allocate on the heap so we know we will never run out of space on a long input
char temp = malloc(strlen(s1) + 1);
strcpy(temp, s1);
strcpy(s1, s2);
strcpy(s2, temp);
// Free temporary buffer
free(temp);
printf("After swapping : swap_char(\"%s\", \"%s\")\n", s1, s2);
}
However, there is a bigger problem here. We don't know if both pointers have enough memory allocated. This is why this approach is not all that practical. Also by passing the string pointers directly instead of using a pointer to a buffer on the stack or heap risks attempting to mutate read-only memory. String constants are loaded along with the assembly instructions in each function into read-only memory on most modern systems. This is good since it prevents a malicious actor or undefined behavior from modifying the function assembly.
char *a = "please";
char *b = "work";
// Create new buffers with the required space to use instead
unsigned int buffer_len = imax(strlen(a), strlen(b)) + 1;
char *a_buffer = malloc(buffer_len);
char *b_buffer = malloc(buffer_len);
// Copy the input strings into our new buffers
strcpy(a_buffer, a);
strcpy(b_buffer, b);
// Finally swap the buffers
swap_char(a_buffer, b_buffer);
As you can see, it isn't very practical but it is possible. A more practical approach is to just swap the pointers held by variables.
void swap_strings(char **s1, char **s2) {
char *temp = *s1;
*s1 = *s2;
*s2 = temp;
}
char *a = "please";
char *b = "work";
printf("Before swapping : swap_char(\"%s\", \"%s\")\n", a, b);
swap_strings(&a, &b);
printf("After swapping : swap_char(\"%s\", \"%s\")\n", a, b);

C: printf("%s\n", str) produces gibberish? [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 3 years ago.
I have some C code that is supposed to call a function and return a string. Somewhere I read this is difficult due to memory allocation not being constant or something? Anyway, I was told I should rather return the pointer to the string. However, I can't explain why printf sometimes produces gibberish, and sometimes not:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char * execTasks() {
int d, m, y;
char str[6] = {};
d = 10; m = 5; y = 18;
memset(&str, 0, sizeof(str));
sprintf(str, "%02d%02d%02d", d, m, y);
printf("Works fine: %s\n", str); // Works fine even with additions
char *s_ptr = str;
return s_ptr;
}
int main() {
char * str;
str = execTasks();
printf("%s", str); // works fine!
printf("%s\n", str); // produces gibberish!
printf("%s,%s", str, str); // also gibberish!
return 0;
}
Can somebody explain to me why printf("%s", str); works fine, while printf("%s\n", str); and variations print out gibberish?
Or am I doing something wrong with returning the pointer? Essentially the function should return a date as string in the format DDMMYY. I need this string later in the main function to append it to another string.
The array char str[6] is local to the execTasks function. After execTasks returns, that memory is reclaimed and can be used by other code. It happens that the last two printfs in main use that memory and corrupt the string, whereas the first printf in main doesn't. However, this code is still invalid (as in Undefined Behavior) as it can also produce gibberish or crash in the right circumstances (e.g. a different compiler, architecture, or standard library implementation).
To fix that you shall not return pointers to local variables, and instead either use a dynamically allocated copy of the string:
char * execTasks() {
int d, m, y;
char str[7] = {};
// ...
return strdup(str); // mallocs a copy of str
}
int main() {
char * str = execTasks();
printf("%s,%s", str, str);
free(str); // reclaim memory
}
Or use a variable that is local to main:
int execTasks(char *str, size_t size) {
int d, m, y;
d = 10; m = 5; y = 18;
return snprintf(str, size, "%02d%02d%02d", d, m, y);
}
int main() {
char str[7];
execTasks(str, sizeof(str));
printf("%s,%s", str, str);
}
Here execTasks returns the amount of characters (not including the null terminator) that would be needed to hold the result. It can be used to detect when the provided buffer is too small, though I don't do that in this simple example (if it's too small the string will simply be truncated).
Notice also that the amount of the memory required for the string is seven chars, because you need an extra byte for the null terminator.

c pointers in string array

I'm trying to copy a char array into another char array using pointer arithmetic. It seems to be correct within the copy() but then I don't understand what happens after it gets to main. char a[] does not get the value of char b[] even if I called the function. Am I missing something? Hehehe
#include <stdio.h>
void copy(char a[], char b[]){
int *apoint = &a;
printf("%d\n", apoint);
printf("%d\n", &a);
*apoint = b;
printf("%d\n", *apoint);
printf("%s\n", a);
printf("%s\n", b);
}
int main(void){
char a[100];
char b[] = "bluhbluh";
copy(a,b);
printf("%d\n", a);
}
That's really not very meaningful C. I suspect it didn't even compile without warnings?
First you take the address of array a, then you take the address of array b, convert it to an integer (without a cast!), and then write that integer into the array a. Then, at the end of main, you try to print the char array as an integer.
Pointer arithmetic doesn't quite work like that. :)
I think you really mean to do something like this:
void copy(char a[], char b[]){
char *ptr_a = a;
char *ptr_b = b;
while (*ptr_b != '\0') {
*ptr_a = *ptr_b;
ptr_a++;
ptr_b++;
}
*ptr_a = '\0';
}
int main(void){
char a[100];
char b[] = "bluhbluh";
copy(a,b);
printf("%s\n", a);
}
Of course, the proper way to do it is like this:
#include <string.h>
int main(void){
char a[100];
char b[] = "bluhbluh";
strncpy(a, b, 100);
printf("%s\n", a);
}
As ams points out in his/her answer, if you want a copy of the array, you need to duplicate each entry. Assuming you don't want to duplicate the array, but instead want a to point at b:
apoint doesn't do anything - it can't change the pointers of a or b. If you wanted to modify the address that a or b pointed to, you'd have to pass the address of them to your function. This won't work, however, as arrays are not pointers - it's why you can't reassign arrays in C. You can modify pointers though - the following is an example of modifying a pointer to a to point at b:
#include <stdio.h>
void redirect(char** a, char* b){
*a = b;
}
int main(void){
char a[100];
char b[] = "bluhbluh";
char* apt = a;
redirect(&apt,b);
printf("a=%s, b=%s", apt,b);
}
apoint should be a char*, don't you have a warning about this pointer assignment?
Moreover you're not iterating on all chars of the string...
Maybe the line int *apoint = &a is wrong, &a is pointer to pointer to char, while apoint is int *. Don't you have compile errors?
You have some major errors in your code specially this line is incorrect int *apoint = &a; it should be char* *apoint = &a;
//Corrected Code:
#include <stdio.h>
void copy(char a[], char b[]){
char* *apoint = &a;
printf("%d\n", apoint);
printf("%d\n", &a);
*apoint = b;
printf("%d\n", *apoint);
printf("%s\n", a);
printf("%s\n", b);
}
int main(void){
char a[100];
char b[] = "bluhbluh";
copy(a,b);
printf("%d\n", a);
}
This will solve the major code issues though I don’t think your copy function would still give your desire results as approach doesn’t seem very right.
Method of copying the char is not good if you enable -Wall or -Werror in gcc you will see so many errors.
The thing you want, which is possible just by copying the pointers in main no need to call copy (a,b);
char *a;
char b[]="bluhbluh"
a=b;
now a started pointing to string "bluhbluh"
But I think that you dont want you want each and every character of array b to be copied into array a
you will have to do like this
void copy(char *a,char *b)
{
while(*b!='\0')
*a++=*b++;
}
int main()
{
char a[100];
char b[]="bluhbluh";
copy(a,b);
printf("%s\n",a);
}

C segmentation fault-char pointers

I need help figuring out why I am getting a segmentation fault here. I have gone over it and I think I am doing something wrong with the pointers, but I can figure out what.
My Program:
#include <stdlib.h>
#include <stdio.h>
void encrypt(char* c);
//characters are shifted by 175
int main(){
char* a;
*a = 'a';
/*SEGMENTATION FAULT HERE!*/
encrypt(a);
printf("test:%c/n",*a);
return 0;
};
void encrypt(char* c){
char* result;
int i=(int)(*c);
i+=175;
if(i>255)
{
i-=256;
}
*c=(char)i;
};
The problem is here:
char *a;
*a = 'a'
Since the variable "a" is not initialized, *a = 'a' is assigning to a random memory location.
You could do something like this:
char a[1];
a[0] = 'a';
encrypt(&a[0]);
Or even just use a single character in your case:
int main(){
char a = 'a';
encrypt(&a);
printf("test:%c/n",a);
return 0;
};
char* a;
*a = 'a';
/*SEGMENTATION FAULT HERE!*/
There isn't any "there" there. You've declared a and left it uninitialized. Then you tried to use it as an address. You need to make a point to something.
One example:
char buffer[512];
char *a = buffer;
(Note buffer has a maximum size and when it falls out of scope you cannot reference any pointers to it.)
Or dynamic memory:
char *a = malloc(/* Some size... */);
if (!a) { /* TODO: handle memory allocation failure */ }
// todo - do something with a.
free(a);
That pointer a does not get the actual space where to store the data. You just declare the pointer, but pointing to where? You can assign memory this way:
char *a = malloc(1);
Then it won't segfault. You have to free the variable afterwards:
free(a);
But in this case, even better,
char a = 'a';
encript(&a);

Swapping two string pointers

i have to char[] in C and i wanted to swap between them, by only swaping the pointer
to the array and not one char at a time so i wrote this code:
#include <stdio.h>
void fastSwap (char **i, char **d)
{
char *t = *d;
*d = *i;
*i = t;
}
int main ()
{
char num1[] = "012345678910";
char num2[] = "abcdefghujk";
fastSwap ((char**)&num1,(char**)&num2);
printf ("%s\n",num1);
printf ("%s\n",num2);
return 0;
}
I get this output (note the last 4 characters)
abcdefgh8910
01234567ujk
When I expect:
abcdefghujk
012345678910
NOTE: I am working on a 64 bit Linux System.
You can't modify the addresses of num1 and num2, your code should work if your test was instead:
int main ()
{
char num1[] = "012345678910";
char num2[] = "abcdefghujk";
char *test1 = num1;
char *test2 = num2;
fastSwap (&test1,&test2);
printf ("%s\n",test1);
printf ("%s\n",test2);
return 0;
}
Arrays are not pointers. While they decay to pointers when you call your fastSwap(), these pointers are not the actual arrays. The fact that you need a cast should give you a hint that something is wrong.
This would work:
void fastSwap (const char **i, const char **d)
{
const char *t = *d;
*d = *i;
*i = t;
}
const char* num1 = "012345678910";
const char* num2 = "abcdefghujk";
fastSwap (&num1,&num2);
printf ("%s\n",num1);
printf ("%s\n",num2);
This will work:
int main ()
{
char *num1 = "012345678910";
char *num2 = "abcdefghujk";
fastSwap (&num1,&num2);
printf ("%s\n",num1);
printf ("%s\n",num2);
return 0;
}
num1 is an array, and &num1 is the address of the array itself - it is not an address of a pointer.
The address of an array itself is the same location in memory as the address of the first element of the array, but it has a different type. When you cast that address to char **, you are claiming that it points at a char * value - but it does not. It points at a block of 13 chars. Your swap function then accesses that array of 13 chars as if it were a char * - since the latter is the same size as 8 chars on your platform, you end up swapping the first 8 chars of each array.
Your fastSwap only seems to work. You're invoking undefined behavior by casting '&num1' and '&num2' (which are pointers to the characters of num1 and num2) to pointers to pointers of characters (char**).
char *t = *d
t will point to whatever d's contents are pointing to, however d is pointing to the actually characters of num2 ("abcdefghujk" or 0x61 0x62 0x63 0x64 0x65 0x66 0x67 0x68 0x75 0x6B 0x00). This means that '*d' is actually copying the contents of 'num2' and not the pointer to num2 as you probably expected.
't' then is a bad pointer however since it is never dereferenced you avoid a crash/segment fault.
Because you're on a 64 bit machine/OS pointers are 8 bytes the value of 't' is now the first 8 bytes of 'num2' and this is what gets put into num1 after
*i = t
If you intend to swap pointers you must first create pointer variables as Mark did
char *test1 = num1;
char *test2 = num2;
fastSwap (&test1,&test2);
Or change num1 and num2 into pointers (char *) rather than arrays (char[]) as sb1/Karl did
char *num1 = "012345678910";
char *num2 = "abcdefghujk";
fastSwap (&num1,&num2);
I've had the same situation and solved it with the following trick:
p.s. windows platform, vs-2012
void FastSwap (void **var1, void **var2) {
void *pTmp = *var1;
*var1 = *var2;
*var2 = pTmp;
}
int main () {
char *s1 = "1234567890123456";
char *s2 = "abcdefghij";
printf ("s1 before swap: \"%s\"\n", s1);
printf ("s2 before swap: \"%s\"\n", s2);
// if you change arguments in the FastSwap definition as (char **)
// then you can erase the (void **) part on the line below.
FastSwap ((void **) &s1, (void **) &s2);
printf ("s1 after swap : \"%s\"\n", s1);
printf ("s2 after swap : \"%s\"\n", s2);
return (0);
}
Change fastSwap to:
void fastSwap (char *i, char *d)
{
while ((*i) && (*d))
{
char t = *d;
*d = *i;
*i = t;
i ++;
d ++;
}
}
then call fastSwap (num1, num2);
int swap(char *a, char *b){
char *temp = (char *)malloc((strlen(a) + 1)*sizeof(char));
strcpy(temp, a);
strcpy(a, b);
strcpy(b, temp);
}
int main(){
char a[10] = "stack";
char b[10] = "overflow";
swap(a, b);
printf("%s %s", a, b);
}
While given answers already showed how to do it right (and hinted to undefined behaviour), you still might be interested in the details...
At very first, you have to character arrays. Applying the addressof operator to won't give you a pointer to pointer, but a pointer to array:
int(*ptr1)[10] = &num1;
Syntax might look strange, but that's C. The important thing here now is: You have a pointer with one level of indirection. But you cast it to a pointer with two levels of indirection (char**).
What now happens in fastSwap is:
char* t = *d;
This will copy as many bytes of *d into t as pointers on your system have size. Solely: In reality, you do not have a pointer to pointer, but a pointer to array which only has been casted. So the first sizeof(void*) bytes of the array will be copied into t. Similarly for the other assignments, explaining the results you get.
If now your arrays were shorter than the size of pointers, then memory after the arrays would have been read:
int a[] = "123";
int b[] = "456";
int c[] = "789";
fastSwap ((char**)&a, char**(&b));
printf("%s %s %s", a, b, c);
would have printed on your system (as pointer size is 8 bytes):
456 789 456
Explanation:
char *t = *d;
// copied the four bytes of b into t - AND the next four bytes (those of c!!!)
*d = *i;
// copied the eight bytes of a AND b int b AND c
// b contains "123", c "456"
*i = t;
// copied the eight bytes that were copied from b and c into a and b
// the "123" in b now got overwritten, that's why you never see them...
Be aware that you don't have guarantee for such result, it is just the most likely one. You invoked undefined behaviour, anything might happen instead, you even might switch off the sun by accident (if your compiler happened to produce the appropriate code...).

Resources