Need to understand how char * strcpy (char *cad1, const char *cad2) works in C - strcpy

Can't get how a method with this head: char * strcpy (char *cad1, const char *cad2), works in C in this sample:
'char * strcpy (char *cad1, const char *cad2){
char *aux = cad1;
for( ; *cad1++ = *cad2++; );
return cad1;
}'

Starting from the method signature or prototype, that tells a lot about the how it works: we have two parameters together with their respective types and a return type. All parameters in this case are pointers to char, more known as char pointers. Those char pointers are what is used in "C" as strings of characters. One parameter is a const, because that value must not be changed in the function, it MUST keep, the original value.
Strings in "C" have some peculiarities, once the pointer is created to a string it always points to the first characters in the string or index 0, the same as char *v = var[0], and can be incremented passing to the next char in the string such as v++. Other peculiarity in "C" is that all strings represented by char arrays end with a 0 character (ASCII null = 0).
The strcpy version account on that concepts and makes a for loop to copy each element in the char *cad2 to *cad1, that variables MUST be allocated statically or dynamically (malloc) before calling the function, and the return of the function in the code above is a pointer to the original variable (in that case *cad1, normally they return the copied one). In your function it was changed, I mean it is returning the original instead of the copied what looks wrong since you catch in the aux the pointer to the first element of the copied variable and you did not use it.
One good point to observe is the for loop:
for( ; *cad1++ = *cad2++; );
How it works is tricky, the first interesting point is that the for loop has tree parameters, and in "C" all are optional. The first is to initialize, the second is a boolean condition to continuing iterating, and the last one is to increment or decrement.
Next, tricky is is *cad1++ = *cad2++ a boolean expression? The answer is yes, it is. Since in "C" the value 0 (zero) is false, and anything else is true. Remember that I have said strings in "C" finishes always with a 0 (zero), so when evaluating and assigning to the copy the value of a pointer (using *cad1 will return the value pointed by a pointer variable, the star in the begin makes that magic) and reaches the end of the string that will return false and finish the iteration loop.
One point is interesting here, first the evaluation has less priority than the assignment in this case, what makes first the value being copied to the copy variable, then evaluating the boolean expression.
"C" is like this you writes a small code that have large meaning behind it. I hope you have understood the explanation. For further information have a look in "C" pointers at : https://www.tutorialspoint.com/cprogramming/c_pointers.htm.

char * strcpy (char *cad1, const char *cad2){
for( ; *cad1++ = *cad2++;);
return cad1;
}
the way this works, at the calling side, it can be used in two ways, but always requires a buffer to write to so the use is simmilar.
char arr[255];
memset(arr,0,sizeof(char) * 255); // clear the garbage initialized array;
strcpy(arr, "this is the text to copy that is 254 characters long or shorter.");
puts(arr);
or
char arr[255];
memset(arr,0,sizeof(char) * 255);
puts(strcpy(arr,"hello C!"));
sense the function returns the pointer to the buffer this works as well.

Related

Will an array of pointers be equal to an array of chars?

I have got this code:
import std.stdio;
import std.string;
void main()
{
char [] str = "aaa".dup;
char [] *str_ptr;
writeln(str_ptr);
str_ptr = &str;
*(str_ptr[0].ptr) = 'f';
writeln(*str_ptr);
writeln(str_ptr[0][1]);
}
I thought that I am creating an array of pointers char [] *str_ptr so every single pointer will point to a single char. But it looks like str_ptr points to the start of the string str. I have to make a decision because if I am trying to give access to (for example) writeln(str_ptr[1]); I am getting a lot of information on console output. That means that I am linking to an element outside the boundary.
Could anybody explain if it's an array of pointers and if yes, how an array of pointers works in this case?
What you're trying to achieve is far more easily done: just index the char array itself. No need to go through explicit pointers.
import std.stdio;
import std.string;
void main()
{
char [] str = "aaa".dup;
str[0] = 'f';
writeln(str[0]); // str[x] points to individual char
writeln(str); // faa
}
An array in D already is a pointer on the inside - it consists of a pointer to its elements, and indexing it gets you to those individual elements. str[1] leads to the second char (remember, it starts at zero), exactly the same as *(str.ptr + 1). Indeed, the compiler generates that very code (though plus range bounds checking in D by default, so it aborts instead of giving you gibberish). The only note is that the array must access sequential elements in memory. This is T[] in D.
An array of pointers might be used if they all the pointers go to various places, that are not necessarily in sequence. Maybe you want the first pointer to go to the last element, and the second pointer to to the first element. Or perhaps they are all allocated elements, like pointers to objects. The correct syntax for this in D is T*[] - read from right to left, "an array of pointers to T".
A pointer to an array is pretty rare in D, it is T[]*, but you might use it when you need to update the length of some other array held by another function. For example
int[] arr;
int[]* ptr = &arr;
(*ptr) ~= 1;
assert(arr.length == 1);
If ptr wasn't a pointer, the arr length would not be updated:
int[] arr;
int[] ptr = arr;
ptr ~= 1;
assert(arr.length == 1); // NOPE! fails, arr is still empty
But pointers to arrays are about modifying the length of the array, or maybe pointing it to something entirely new and updating the original. It isn't necessary to share individual elements inside it.

swapping address values of pointers

Below is code and I want to ask, why I am not getting swapped number as a result, because instead of swapping numbers I tried to swap their addresses.
int *swap(int *ptr1,int *ptr2){
int *temp;
temp = ptr1;
ptr1= ptr2;
ptr2=temp;
return ptr1,ptr2;
}
int main(){
int num1=2,num2=4,*ptr1=&num1,*ptr2=&num2;
swap(ptr1,ptr2);
printf("\nafter swaping the first number is : %d\t and the second number is : %d\n",*ptr1,*ptr2);
}
I can see two problems in your code.
First, within the swap function, ptr1 and ptr2 are local copies of the pointers in main with the same name. Changing them in swap only changes those copies, not the originals.
Second, the return statement doesn't do anything useful. The function swap is declared as returning a single int *. The return statement actually only returns ptr2 - for why that is, look up the "comma operator" in C. But you ignore the return value in main anyway, so it makes no odds.

std::bad_alloc being thrown when I create a new char**

I am creating an array of c strings from a vector of strings. I want the resulting array to skip the first element of the vector. The function I am using for this is as follows:
char** vectortoarray(vector<string> &thestrings)
{
//create a dynamic array of c strings
char** temp = new char*[thestrings.size()-2];
for(int i = 1; i < thestrings.size(); i++)
temp[i-1] = (char*)thestrings[i].c_str();
return temp;
}
I know that this code works, as I tested it in a smaller program without error. However, when are run in inside of a marginally larger program, I get the error terminate called after throwing an instance of 'std::bad_alloc' what(): std::bad_alloc.
How do I keep this from happening?
I cannot say for certain, but your code CAN throw a bad_alloc when you call new with negative value. If you pass your function an empty vector for example, you are effectively calling
char** temp = new char*[-2];
so you should check this before calling new. From a logical perspective this inclusion of -2 makes little sense anyway. I would also suggest reading this question and answer Why new[-1] generates segfault, while new[-2] throws bad_alloc?
That -2 definitely should not be there. Observe also that you have only allocated an array of pointers to each character array. You also need to allocate memory for the character arrays themselves.

why do strings have pointers as there return type?

I know what pointers are but when it comes to strings/arrays I get really confused. If someone has an answer or a website that explains it that would be great. For example:
char * strncopy (char*dest, char * source, size_t);
Why the pointer? what is it pointing to? Does it a pointer usually store an address?
It is sayed in my textbook that each string building function is of type pointer char*.
Also I was trying to see if I could write a program that would clear things up, but it didn't work. Can someone tell me how to fix it, or what I'm doing wrong.
#include <stdio.h>
#include <string.h>
char * getname ()
{
char name [10];
scanf ("%s", name);
return (name);
}
int main (void)
{
char name[10];
printf ("Enter your name\n");
name[] = getname();
printf ("Hi %s", name);
return (0);
}
Inside of your getname function, when you return a pointer to the name array because it's allocated on the stack it gets destroyed leaving you with an invalid pointer. Dereferencing such a pointer causes many, many problems.
You should allocate the name array inside of getname on the heap, with malloc/calloc so that when you return the pointer the data won't be destroyed.
With regards to functions like strncpy, they tend to return a pointer to the resulting string; e.g.: strncpy returns a pointer to the destination.
Pointer itself represents an address, e.g. if you have a pointer typed char *pstr, you can always check the underlying address with printf("address of my pointer %p\n", pstr);
In C programming language, a string is an array of char. If you have a good knowledge of array and its memory layout, it's not too hard for you to understand c-styled string. Generally speaking, an array in C is a continuous chunk of memory with name of array represent address of the first element in the array. So is string who is a chunk of memory with name of the char array address of the first character. In addition, c-styled string terminates with character \0, so if you want to manage memory for string yourself, remember one extra byte for the tailing \0.
As to your second problem, your name in function getname is a local variable whose life time ends when function returns. However, you still want to access name outside the function which is inappropriate. You can solve this be dynamically allocated memory like in dasblinkenlight's and others' post.
Good luck.

Storing a char in a char pointer

I have a global variable that is a *char. My main function header reads as int main(int argc, char* argv[argc]){...}. These two lines of code have to remain the way they are. The first argument of my main function is a number of type *char, that I convert to a char using atoi(...);. I am basically changing the ASCII value to its corresponding character. Now I want to store this local variable character I have into the global variable that is a char pointer. I know the problem is related to allocation of memory, but I am not sure how to go about this.
My code:
char* delim;
int main(int argc, char* argv[argc])
{
char delimCharacter;
if (isdigit(*(argv[3])) == 0) delim = argv[3]; //you can pass in a character or its ascii value
else { //if the argument is a number, then the ascii value is taken
delimCharacter = atoi((argv[3]));
printf("%s\t,%c,\n", argv[3], delimCharacter);
//sprintf( delim, "%c", delimCharacter ); // a failed attempt to do this
*delim = delimCharacter;
//strncpy(delim, delimCharacter, 1); // another failed attempt to do this
}
//printf("%s\n",delim);
This yields a seg fault.
You need to verify you have got (at least) 3 arguments before you start using them.
if (argc < 4)
{
printf("Need 3 args");
exit(1);
}
Then you need to allocate some memory to put the character in.
delim = malloc(2);
// TODO: Should check the result of malloc before using it.
*delim = delimCharacter;
delim[1] = 0; // Need to NULL terminate char*
You're dereferencing an uninitialized pointer. delim never gets initialized when it goes into the else block.
char delim[] = ","; // anything really, as long as as it's one character string
...
delim[0] = delimCharacter;
In addition to your memory issue, I think you are confused about what atoi does. It parses a string representation of a number and returns the equivalent int value, e.g. "10000" => 10,000. I think that you think it will give you the ASCII value of a character, e.g. "A" =>65.
Since you have a char *, and you are (I think) assuming that it contains a single character, you could simply do this:
delimCharacter = *(argv[3]);
However, there really seems to be no need to use the intermediate step of assigning this value to a char variable at all. If the end goal is to have delim point to the char that is the delimiter, then it seems this is all you need to do:
delim = argv[3];
Not only does this remove unnecessary code, but it means you would no longer need to allocate additional memory for delim to point to.
I would also declare delim as a const char * since I assume there is no reason to change it.

Resources