My task is like this: I should implement the strcpy function under the following constraints:
The function should use pointer expression (*(d+i))
I should implement it without using <string.h>
I'm programming in Visual Studio 2019.
I searched some source code in google and run them, but my program has a logical error. The program ends right away, each time. I don't know what I'm doing wrong.
Here's my code in Visual Studio 2019 on Windows. Please tell me what's wrong.
#include <stdio.h>
void strcpy(char*, char*);
int main()
{
char* sen1 = "Hello";
char* sen2 = "Friends";
strcpy(sen1, sen2);
printf("The result: %s\n", sen1);
return 0;
}
void strcpy(char* str1, char* str2)
{
int i = 0;
while (*(str2 + i) != '\0')
{
*(str1 + i) = *(str2 + i);
i++;
}
*(str1 + i) = '\0';
}
In addition to needing to provide writable storage for sen1, you should also check to ensure str2 != NULL in your function before dereferencing str2 (otherwise, even if you fix all other errors -- a segfault will likely result)
For example, in your code you can define a constant to use in setting the size of a sen1 array (or you can allocate storage with malloc(), calloc(), or realloc() -- save that for later). Using an array you can do, e.g.
#include <stdio.h>
#include <stdlib.h>
#define MAXC 64 /* if you need a constant, #define one (or more) */
...
int main (void)
{
char sen1[MAXC] = "Hello";
char *sen2 = "Friends";
mystrcpy (sen1, sen2);
printf ("The result: %s\n", sen1);
}
In your strcpy function, check that str2 isn't NULL before using str2 in your function, e.g.
char *mystrcpy (char *dest, const char *src)
{
char *p = dest;
if (!src || !dest) { /* ensure src or dest is not NULL */
fputs ("error: src or dest parameters NULL in mystrcpy().\n", stderr);
exit (EXIT_FAILURE);
}
do /* loop */
*p++ = *src; /* copy each char in src to dest */
while (*src++); /* (including the nul-termianting char) */
return dest; /* return pointer to dest */
}
Now you will copy your source string to your destination string in your (renamed) mystrcpy() function, receiving the results you expect:
Example Use/Output
$ ./bin/mystrcpy
The result: Friends
Look things over and let me know if you have further questions.
Two problems, at least:
String literals are not writable in C. Often the symptom is a crash (SIGSEGV).
You are not allowed to use the identifier strcpy for your own function. Use another name.
Three clean code issues, at least:
Turn int main() into int main(void) to make it properly typed.
str1 and str2 are too generic names. They don't indicate which is the source and which is the destination pointer. What about my_strcpy(char *dest, char *src)?
I'd use size_t i for the index counter instead of int, because that's the type all the string length functions and the sizeof operator return. It's also an unsigned type and can copy really long strings :-) The size_t is available after #include <stddef.h>.
You want this:
...
char* source = "Hello";
// or char source[] = "Hello";
char destination[1000]; // destination buffer long enough for playing around
my_strcpy(destination, source);
printf("%s\n", destination); // should print "Hello" if my_strcpy is corect
...
For the rest read Jens's answer.
Among the other good answers, just regarding the implementation of your strcpy function and not a detailed issue analyze of your actual code, another approach is this:
char * n_strcpy(char * dest, char const * src)
{
if (dest == NULL || src == NULL)
{
return NULL;
}
char *ptr = dest;
while ((*dest++ = *src++));
return ptr;
}
Related
i ma new c and i am trying sprintf along with pointers. all i get in console is return buf; as is please help me with this code.
#include <stdio.h>
char* stringa(char* str);
int main()
{
char* ss = "123";
stringa(ss);
return 0;
}
char* stringa( char* str)
{
char buf [100] ;
sprintf(buf,"hello %s", str);
return buf;
}
i tried many other ways too like sprintf_c and my computer shut down for serious. i am learning c.
Maybe this is what you want
#include <stdio.h>
char* stringa(char* dest, char* src)
int main()
{
char buf [100] ;
char* ss = "123";
printf("%s\n", stringa(buf, ss));
return 0;
}
char* stringa(char* dest, char* src)
{
sprintf(dest,"hello %s", src);
return dest;
}
In function 'char* stringa(char* str)' you are not allocating space in the heep for the char array 'buf' you are allocating space on the stack for that variable. (meaning after the function finishes, the variable 'buf' will be wiped away because it will be out of scope) therefore you must ask the compiler to allocate space in memory for this array, I recommend using malloc()
ex:
char* stringa( char* str)
{
char *buf = (char*)malloc(sizeof(char) * 100);
sprintf(buf,"hello %s", str);
return buf;
}
char* stringa( char* str)
{
char buf [100] ;
sprintf(buf,"hello %s", str);
return buf;
}
The problem with this code is that the buf char array is local to the stringa function. When the function returns, the memory occupied by the buf array is not valid anymore (for example, it could be reused later to store the content of other variables, arrays, etc.).
So when the function returns, you are giving the caller a pointer to garbage memory, to invalid data. The C compiler is trying to help you with that warning message; it's telling you: "Sorry, you are trying to pass back to the caller the address of a local variable (i.e. the buf char array) that is not valid anymore when the function terminates."
To fix this problem one option could be to allocate the char array for the output string at the call site, and let the invoked stringa function write into the caller-provided array:
#include <stdio.h>
char* stringa(char* dest, const char* str);
int main()
{
const char* ss = "123";
char buf[100];
stringa(buf, ss);
return 0;
}
/* Write the final message into 'dest'.
* Return the same dest address.
*/
char* stringa(char* dest, const char* str)
{
/* Note: better using a safe string function
* to prevent buffer overflows (e.g. sprintf_s),
* passing the maximum destination array size as well.
*/
sprintf(dest,"hello %s", str);
return dest;
}
Note that I also added some consts in your code to enforce some const-correctness for read-only input strings.
I'm not sure if I even worded the title correctly, but basically. I want to know if there is a way to add to the buff array from the hey function using the pointers in the arguments and why does it work if it does?
buf[100].
example:
int main(){
char buf[100];
hey("320244",buf);
printf("%s", buf);
}
void hey(char* s, char* result){
/*
some code that appends to result using pointers
do some stuff with s and get the result back in buf without using return.
*/
}
I have modified your code with some comments :-
#define LEN 100 //Use a macro instead of error prone digits in code
void hey(char* s, char* result); //Fwd declaration
int main(){
char buf[LEN] = {0}; //This will initialize the buffer on stack
hey("320244",buf);
printf("%s", buf);
hey("abc", buf); //Possible future invocation
printf("%s", buf);
}
void hey(char* s, char* result){
if(strlen(result) + strlen(s) < LEN ) //This will check buffer overflow
strcat(result, s); //This will concatenate s into result
else
//Do some error handling here
}
Let's do the right thing, and use a structure to describe a dynamically allocated, grow-as-needed string:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
struct mystring {
char *ptr; /* The actual string */
size_t len; /* The length of the string */
size_t max; /* Maximum number of chars allocated for */
};
#define MYSTRING_INIT { NULL, 0, 0 }
If we want to append something to a struct mystring, we define a function that takes a pointer to the structure the function can modify. (If it only needed a char pointer instead of a structure, it'd take a char **; a pointer to a char pointer.)
void mystring_append(struct mystring *ms, const char *s)
{
const size_t slen = (s) ? strlen(s) : 0;
/* Make sure ms points to a struct mystring; is not NULL */
if (!ms) {
fprintf(stderr, "mystring_append(): No struct mystring specified; ms == NULL!\n");
exit(EXIT_FAILURE);
}
/* Make sure we have enough memory allocated for the data */
if (ms->len + slen >= ms->max) {
const size_t max = ms->len + slen + 1;
char *ptr;
ptr = realloc(ms->ptr, max);
if (!ptr) {
fprintf(stderr, "mystring_append(): Out of memory!\n");
exit(EXIT_FAILURE);
}
ms->max = max;
ms->ptr = ptr;
}
/* Append. */
if (slen > 0) {
memmove(ms->ptr + ms->len, s, slen);
ms->len += slen;
}
/* We allocated one char extra for the
string-terminating nul byte, '\0'. */
ms->ptr[ms->len] = '\0';
/* Done! */
}
The (s) ? strlen(s) : 0; expression uses the ?: conditional operator. Essentially, if s is non-NULL, the expression evaluates to strlen(s), otherwise it evaluates to 0. You could use
size_t slen;
if (s != NULL)
slen = strlen(s);
else
slen = 0;
instead; I just like the concise const size_t slen = (s) ? strlen(s) : 0 form better. (The const tells the compiler that the slen variable is not going to be modified. While it might help the compiler generate better code, it is mostly a hint to other programmers that slen will have this particular value all through this function, so they do not need to check if it might be modified somewhere. It helps code maintenance in the long term, so it is a very good habit to get into.)
Normally, functions return success or error. For ease of use, mystring_append() does not return anything. If there is an error, it prints an error message to standard output, and stops the program.
It is a good practice to create a function that releases any dynamic memory used by such a structure. For example,
void mystring_free(struct mystring *ms)
{
if (ms) {
free(ms->ptr);
ms->ptr = NULL;
ms->len = 0;
ms->max = 0;
}
}
Often, you see initialization functions as well, like
void mystring_init(struct mystring *ms)
{
ms->ptr = NULL;
ms->len = 0;
ms->max = 0;
}
but I prefer initialization macros like MYSTRING_INIT, defined earlier.
You can use the above in a program like this:
int main(void)
{
struct mystring message = MYSTRING_INIT;
mystring_append(&message, "Hello, ");
mystring_append(&message, "world!");
printf("message = '%s'.\n", message.ptr);
mystring_free(&message);
return EXIT_SUCCESS;
}
Notes:
When we declare a variable of the structure type (and not as a pointer to the structure, i.e. no *), we use . between the variable name and the field name. In main(), we have struct mystring message;, so we use message.ptr to refer to the char pointer in the message structure.
When we declare a variable as a pointer to a structure type (as in the functions, with * before the variable name), we use -> between the variable name and the field name. For example, in mystring_append() we have struct mystring *ms, so we use ms->ptr to refer to the char pointer in the structure pointed to by the ms variable.
Dynamic memory management is not difficult. realloc(NULL, size) is equivalent to malloc(size), and free(NULL) is safe (does nothing).
In the above function, we just need to keep track of both current length, and the number of chars allocated for the dynamic buffer pointed to by field ptr, and remember that a string needs that terminating nul byte, '\0', which is not counted in its length.
The above function reallocates only just enough memory for the additional string. In practice, extra memory is often allocated, so that the number of reallocations needed is kept to a minimum. (This is because memory allocation/reallocation functions are considered expensive, or slow, compared to other operations.) That is a topic for another occasion, though.
If we want a function to be able to modify a variable (be that any type, even a structure) in the callers scope -- struct mystring message; in main() in the above example --, the function needs to take a pointer to variable of that type, and modify the value via the pointer.
The address-of operator, &, takes the address of some variable. In particular, &message in the above example evaluates to a pointer to a struct mystring.
If we write struct mystring *ref = &message;, with struct mystring message;, then message is a variable of struct mystring type, and ref is a pointer to message; ref being of struct mystring * type.
If I have understood you correctly you mean the following
#include <string.h>
//...
void hey(char* s, char* result)
{
strcpy( result, s );
}
Here is a demonstrative program
#include <stdio.h>
#include <string.h>
void hey( const char* s, char* result);
int main(void)
{
char buf[100];
hey( "320244", buf );
printf( "%s\n", buf );
return 0;
}
void hey( const char* s, char* result )
{
strcpy( result, s );
}
Its output is
320244
If the array buf already stores a string then you can append to it a new string. For example
#include <string.h>
//...
char buf[100] = "ABC";
strcat( buf, "320244" );
Take into account that the function hey should be declared before its usage and according to the C Standard the function main shall be declared like
int main( void )
I wrote a substr function in c, I can get the returned value inside the substr function, but can not get the returned value in main function. Below is all the code:
#include <stdio.h>
#include <string.h>
char* substr(char *source, int start, int length)
{
char result[10];
char *r = result;
strncpy(result, source+start, length);
printf("substr: %s\n", r);
return r;
}
int main()
{
printf("main: %s\n", substr("HELLO", 1, 2));
}
and the output is:
substr: EL
main:
I'm not familiar with c, anybody get the idea to fix this, thanks in advance.
result only exists during the call to your substr.
Your main is referencing bad memory.
you could fix it by:
making result static in substr.
dynamically allocating result (remember to free)
making result global
As cthulhu ( "Ph'nglui mglw'nafh Cthulhu R'lyeh wgah'nagl fhtagn" ) points out: even if you applied one of my fixes: your string isn't nul terminated.
Also since you have a fixed size result buffer, you could cause problems by asking for a substring longer than 10 - either check your arguments, or don't use a fixed size buffer.
I haven't tested this, so there may well be an "off by one" problem or two lurking in the corners...
/*
* Caller must free the results if they are non null
*/
char* substr(char *source, int start, int length)
{
/* If the input is NULL, return NULL */
if (source == NULL) return NULL;
int len = strlen(source);
/* If the requested start is off the end of the string, return NULL */
if (start > len) return NULL;
/* If the requested length is 0 or less, return NULL */
if (length <= 0) return 0;
char *r = (char*)malloc(length + 1); /* allow space for null terminator */
if (r != NULL) {
int i = 0;
while(source[start] != '\0' && i < length) {
r[i++] = source[start++];
}
r[i] = '\0';
printf("substr: %s\n", r);
}
return r;
}
If you're going to be expecting to return a value to the caller then you should pass the place where the string will be stored to the function. Standard library functions like strcpy do this. Here is a very simple example. It assumes dest is already declared and is big enough to store it.
char * substr(char * dest, char * src, int start, int length)
{
// Move substring into passed destination pointer
strncpy(dest, src + start, length);
// Append null to the end to terminate string
dest[length] = 0;
// Return string pointer that can be used in printf and other places
return dest;
}
int main(int argc, char const *argv[])
{
char * test = "This is a test.";
char * dest = malloc(10);
printf("%s", substr(dest, test, 5, 2));
free(dest);
return 0;
}
Output:
is
Edit: To all the people returning values that are malloc'd inside the function, how do you expect people to free the memory if they just use it in a print statement? They receive no pointer to free and the memory will just be left hanging there.
The below code allocate memory on the heap. Just free your memory when you are done. strlcpy always NUL-terminate its strings as others have pointed out.
#include <string.h>
char *
substr(char *s, int start, int len)
{
char *ss;
if(strlen(s) < start + len)
return NULL;
if((ss = malloc(len + 1)) == NULL)
return NULL;
strlcpy(ss, s + start, len);
return ss;
}
int
main(void)
{
char *s = substr("Hello World!", 6, 5);
printf("%s\n", s);
free(s);
return 0;
}
Should print World.
To use strlcpy in Debian Linux use:
gcc -lcext -o prog prog.c
If your operating system doesn't provide strlcpy just include it yourself in your source. It is licensed under the BSD license, that means free to use, sell, etc, as long you include the license itself.
The implementation of strlcpy can be found on OpenBSD's CVS Web.
Dynamic and Static Variables in C
Variable declarations can be outside all functions or inside a function
Declarations outside all functions are global and in fixed memory locations
The static declaration declares a variable outside a function to be a “file global” (cannot be referenced by code in other source files)
Declarations within a block statement {} (function body or block statement nested within a function body):
Are dynamically allocated, unless declared static
Are allocated memory when program execution enters the block
Memory is released when execution exits the block
If a function calls itself (directly or indirectly), it gets a new set of dynamic variables (called a stack frame)
This is handled no differently from any other call to the function
You have problem, the variable result[] is a variable that has been allocated in side the function — whose lifetime extends across the entire run of the function(allocated at the stack!) because of that you need to make the result Dynamic variable
Fix code:
#include <stdio.h>
#include <string.h>
char* substr(char *source, int start, int length)
{
char* result;
char *r;
result=(char*)malloc(sizeof(char)*10);
r = result;
strncpy(result, source+start, length);
printf("substr: %s\n", r);
return r;
}
int main()
{
char* r=substr("HELLO", 1, 2);
printf("main: %s\n",r );
free(r)//Don't forget to free it!
}
OR you can make result[] global variable like this:
#include <stdio.h>
#include <string.h>
char result[10];//<======Global
char* substr(char *source, int start, int length)
{
char *r=result;
r = result;
strncpy(result, source+start, length);
printf("substr: %s\n", r);
return r;
}
int main()
{
printf("main: %s\n",substr("HELLO", 1, 2));
}
I want to know how to alloacte memory for a char pointer in a function using double pointer and write into the pointer.
I tried to write the following code but it crashes. What is the bug in this?
#include <stdio.h>
void myfunc(const char* src, char** dest)
{
*dest = (char*)malloc(200);
while(*(*dest++) = (*src++ != '\0'));
*(*(++dest)) = '\0';
}
void main()
{
char* src = "hello";
char* dest = null;
myfunc(src, &dest);
printf("%s\n",dest);
}
You've written a compare loop instead of a copy loop ('==' vs '='), and you are incrementing the wrong pointer when you write:
while(*(*dest++) == *src++);
(The additional line:
*(*(++dest)) = '\0';
is a late-breaking addition to the question. I'm not sure I want to try parsing that at all. It is not a part of the solution to the problem. See the discussion below.)
The easiest way to get that correct is probably:
char *tgt = *dest;
while ((*tgt++ = *src++) != '\0')
;
We can correct your code in phases (and I did so like this):
static void myfunc(const char* src, char** dest)
{
*dest = (char *)malloc(200);
char *tgt = *dest;
while ((*(tgt++) = *(src++)) != '\0')
;
}
This parenthesises the expressions in the loop fully. We can now substitute *dest for tgt:
static void myfunc(const char* src, char** dest)
{
*dest = (char *)malloc(200);
char *tgt = *dest;
while ((*((*dest)++) = *(src++)) != '\0')
;
printf("1: %s\n", tgt);
}
And this prints 1: hello, but the main program prints an empty line because you've modified *dest so it points to the NUL '\0' at the end of the copied string. So, you'd need to do:
static void myfunc(const char* src, char** dest)
{
*dest = (char *)malloc(200);
char *tgt = *dest;
while ((*((*dest)++) = *(src++)) != '\0')
;
printf("1: %s\n", tgt);
*dest = tgt;
}
And then main() will print the correct answer. But, if you're doing that dinking with tgt (an abbreviation for 'target'; I usually use dst for destination, but that is too close to your dest), you may as well avoid the complexity of incrementing *dest in the first place.
In fact, you should consider using:
#include <string.h>
...
strcpy(*dest, src);
to copy the string. Using strcpy() is probably better, as in 'faster' and 'simpler' and unequivocally correct.
Also, you should have:
#include <stdlib.h>
to declare malloc().
And the correct return type for main() is int:
int main()
{
...
return(0);
}
In C99, the return is (regrettably) optional and zero (success) will be assumed if it is missing; this matches the behaviour of C++98. In earlier versions of C, the return was not optional.
There are so many problems in that little snippet, I don't know where to start... To sum it up, you have made the code needlessly complex and therefore it ended up full of bugs.
Things to fix to make this code compile:
Unless this is code for an embedded system, or unless you are writing an operative
system, main must return int.
NULL is an upper-case constant in C. It is found in the library stddef.h.
The malloc function is found in stdlib.h, which must be included.
Serious bugs:
Never typecast the result of malloc. More info in the C FAQ and on this SO post.
Always free the memory allocated by malloc.
You assign the boolean result (true/false) of *src++ != '\0' to a character.
Widely-recognized bad & dangerous practice that leads to bugs:
Always declare pointers to string literals as const.
Never use assignment inside conditions. (MISRA-C:2004 13.1).
Never use ++ operators inside complex expressions (MISRA-C:2004 12.13).
Never put a semicolon at the end of a row containing a loop statement. (MISRA-C:2004 14.9)
Never use any statement without braces {} (MISRA-C:2004 14.8).
Poor style:
main() should always return.
Avoid "magic numbers", particularly when passing parameters to malloc.
Always check the result of malloc().
Useful hints:
calloc sets all of the allocated memory to zero, unlike malloc. If you use calloc you don't have to set them to zero manually.
Fixed code:
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#define DYNAMIC_BUF_SIZE 200
void make_string (const char* src, char** dest)
{
*dest = calloc(DYNAMIC_BUF_SIZE, sizeof(char));
if(*dest == NULL)
{
/* error handling here */
}
char* dst = *dest;
*dst = *src;
while(*src != '\0')
{
dst++;
src++;
*dst = *src;
}
}
void delete_string (char* str)
{
free(str);
}
int main()
{
const char* src = "hello";
char* dest = NULL;
make_string (src, &dest);
printf("%s\n",dest);
delete_string(dest);
return 0;
}
EDIT: New version without strcpy(), as requested by OP.
//It seems that you don't understand the nature of char* and char**.
char *str = "hello! I am from China and i want to make friends with foreigners";
char **ptr = {"hello!","i want to learn spoken English","sinalym#163.com"};
//Allocate memory for a char** variable. Two steps as follows:
int length[3] = {6,31,16};
char **ptr2 = new char*[3];
for(int i = 0;i < length[i];i++)
*(ptr2 + i) = new char [length[i]];
//delete according to a reverse order.
Language: C
I am trying to program a C function which uses the header char *strrev2(const char *string) as part of interview preparation, the closest (working) solution is below, however I would like an implementation which does not include malloc... Is this possible? As it returns a character meaning if I use malloc, a free would have to be used within another function.
char *strrev2(const char *string){
int l=strlen(string);
char *r=malloc(l+1);
for(int j=0;j<l;j++){
r[j] = string[l-j-1];
}
r[l] = '\0';
return r;
}
[EDIT] I have already written implementations using a buffer and without the char. Thanks tho!
No - you need a malloc.
Other options are:
Modify the string in-place, but since you have a const char * and you aren't allowed to change the function signature, this is not possible here.
Add a parameter so that the user provides a buffer into which the result is written, but again this is not possible without changing the signature (or using globals, which is a really bad idea).
You may do it this way and let the caller responsible for freeing the memory. Or you can allow the caller to pass in an allocated char buffer, thus the allocation and the free are all done by caller:
void strrev2(const char *string, char* output)
{
// place the reversed string onto 'output' here
}
For caller:
char buffer[100];
char *input = "Hello World";
strrev2(input, buffer);
// the reversed string now in buffer
You could use a static char[1024]; (1024 is an example size), store all strings used in this buffer and return the memory address which contains each string. The following code snippet may contain bugs but will probably give you the idea.
#include <stdio.h>
#include <string.h>
char* strrev2(const char* str)
{
static char buffer[1024];
static int last_access; //Points to leftmost available byte;
//Check if buffer has enough place to store the new string
if( strlen(str) <= (1024 - last_access) )
{
char* return_address = &(buffer[last_access]);
int i;
//FixMe - Make me faster
for( i = 0; i < strlen(str) ; ++i )
{
buffer[last_access++] = str[strlen(str) - 1 - i];
}
buffer[last_access] = 0;
++last_access;
return return_address;
}else
{
return 0;
}
}
int main()
{
char* test1 = "This is a test String";
char* test2 = "George!";
puts(strrev2(test1));
puts(strrev2(test2));
return 0 ;
}
reverse string in place
char *reverse (char *str)
{
register char c, *begin, *end;
begin = end = str;
while (*end != '\0') end ++;
while (begin < --end)
{
c = *begin;
*begin++ = *end;
*end = c;
}
return str;
}