difference between strncpy and strxfrm - c

I can't seem to get my head around this, what is the basic difference between these two functions:
char *strncpy(char *str1, const char *str2, size_t count);
and
size_t strxfrm(char *str1, const char *str2, size_t count);
To me it seems they both copy count characters from str2 to str1. What I really want to know is, when should I use either of them?

The difference is in the return value:
The strcpy() and strncpy() functions return a pointer to the destination string.
Upon successful completion, strxfrm() shall return the length of the transformed string (not including the terminating null byte). If the value returned is n or more, the contents of the array pointed to by s1 are unspecified.

Related

memcpy and string literal. does it check and consider null termination -- C

I have a code
char str1[15];
char str2[15];
memcpy(str1,"abcdef",6);
memcpy(str2,"abcdef",6);
so str1 should have null termination at index 7.
but when I do printf("--%d--",strlen(str1)); it prints --9-- which is why its making me think that memcpy is not considering null termination when copy into str1 the string literal `"abcdef".
so shouldnt it also read null termination or is something I did in printf gives me print --9--?
memcpy just copy a number of bytes, whatever they are. In your case, it copies 6 bytes from a string of 6 characters and hence do not copy the null byte at the end of string.
Better code could be written.
Given:
char str1[15];
char str2[15];
char *p = "abcdef";
This will copy "abcdef" and the nul byte to str1 and str2:
memcpy(str1, p, strlen(p) + 1);
memcpy(str2, p, strlen(p) + 1);
But this is not very good because str1 and str2 array could be overflown if the string is to long!
It is much better to use strncpy which copies the string, taking account of the nul terminating byte, the length of the string and the maximum length of the destination:
strncpy(str1, p, sizeof(str1));
strncpy(str2, p, sizeof(str2));
Warning: If there is no null byte among the first n bytes of the source, the string placed in destination will not be null-terminated. See strncpy man page.
void * memcpy( void *destination, const void *source, size_t num ); just copies num bytes of memory, pointed by source, to another memory pointed by destination pointer.
The methods which deal with copying of null-terminated strings are
char * strcpy ( char *destination, const char *source);
char * strncpy ( char *destination, const char *source, size_t num);
Based on your example, you need to use strncpy:
char str1[15];
char str2[15];
strncpy(str1,"abcdef",7);
strncpy(str2,"abcdef",7);
str1 and str2 will hold "abcdef" at the end.
If you just want to copy the whole string up to the size of str1 or str2 then you can do the following
#define STR_LEN 15
char str1[STR_LEN];
char str2[STR_LEN];
strncpy(str1,"abcdef", STR_LEN);
strncpy(str2,"abcdef", STR_LEN);
NOTE:
As the documentation of strncpy states:
No null-character is implicitly appended at the end of destination if source is longer than num. Thus, in this case, destination shall not be considered a null terminated C string (reading it as such would overflow).

How to copy data from string to fields in struct

I know this code is sloppy, I'm trying to relearn string manipulation in C. If I have a string ABBCCCD and I want to store the separate letters in a struct, is there an efficient way to do so? I have some code down below to demonstrate the long way of what I'm trying to do. (Also, do I have to manually add the null-terminator when I'm doing a strncpy?)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct dst_struct {
char a[2];
char b[3];
char c[4];
char d[2];
} dst_struct_t;
int main(void) {
char* test = "ABBCCCD";
char* src = malloc(strlen(test)+1);
strncpy(src, test, strlen(test)+1);
printf("%s\n", src);
dst_struct_t dst;
strncpy(dst.a, src, 1);
strncpy(dst.b, src+1, 2);
strncpy(dst.c, src+3, 3);
strncpy(dst.d, src+6, 1);
printf("dst.a: %s\n", dst.a);
printf("dst.b: %s\n", dst.b);
printf("dst.c: %s\n", dst.c);
printf("dst.d: %s\n", dst.d);
free(src);
}
There isn't really any better way to do this, except that you don't need to copy test to src first.
You also need to add the null terminators to all the strings. It would probably be best to write a function that does both steps: strncpy() and adding the null terminator.
function copy_n(char *dest, char *src, size_t offset, size_t len) {
strncpy(src+offset, dest, len);
dest[len] = '\0';
}
int main(void) {
char* test = "ABBCCCD";
copy_n(dst.a, test, 0, 1);
copy_n(dst.b, test, 1, 2);
copy_n(dst.c, test, 3, 3);
copy_n(dst.d, test, 6, 1);
printf("dst.a: %s\n", dst.a);
printf("dst.b: %s\n", dst.b);
printf("dst.c: %s\n", dst.c);
printf("dst.d: %s\n", dst.d);
}
From the strcpy/strncpy man page:
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
The strcpy() function copies the string pointed to by src, including the terminating null byte ('\0'), to the buffer pointed to by dest. The strings may not overlap, and the destination string dest must be large enough to receive the copy. Beware of buffer overruns! (See BUGS.)
The strncpy() function is similar, except that at most n bytes of src are copied. Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated.
The n argument of strncpy is generally meant to be the length of the destination buffer, as the point of the function is to be like strcpy but prevent overflowing the destination buffer if the source string is too long or not NULL-terminated. If used in that manner, your destination string will be NULL-terminated if the source string fits that length, otherwise the final byte of the buffer will contain the nth character of the source string.
However, the way you seem to be using strncpy is to set the exact number of characters you want to copy from the source buffer to place in the destination buffer. That is not really the intended purpose of strncpy. Instead, what you'd want to use is memcpy, since you are really not concerned with the zero-termination of the source string, but rather just copying a set number of characters from a set location. And yes, you will have to manually add the null-terminator if you use memcpy.

Catenating chars in c: argument of type "char" is incompatible with parameter of type "const char*" [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 4 years ago.
Improve this question
I'm trying to write a program that catenate 2 values in C without using strcat().
char cat (char s1, char s2){
char s3[200];
strcpy(s3,s1);
strcpy(s3+strlen(s1),s2);
return s3;
}
This is my code but it's giving this error:
argument of type "char" is incompatible with parameter of type "const char*"
What should l do?
(I recently start to learn C so please answer me in an easy way)
In your function, the parameters s1 and s2 are of type char which means a single character. Inorder for them to be strings, they must be character arrays. So
char cat (char s1[], char s2[]){
or
char cat (char *s1, char *s2){
instead of
char cat (char s1, char s2){
After this correction, you could just use sprintf() if the destination string is large enough like
sprintf(s3, "%s%s", s1, s2);
And in your program,
s3 is allocated on the stack as it is an automatic variable.
It goes out of scope when the program control exits the cat() function. If you really need to return the string, either allocate memory for s3 on the heap using malloc() and return a pointer to that memory as in
char* cat (char s1[], char s2[]){
char *s3 = NULL;
if( (s3=malloc(sizeof(char)*( strlen(s1)+strlen(s2)+1 )))==NULL )
{
perror("Not enough memory");
return NULL;
}
sprintf(s3, "%s%s", s1, s2);
return s3;
}
or create the s3 character array in the calling function and pass it to cat() as in
char s3[200];
cat(s3, s1, s2);
........
void cat (char s3[], char s1[], char s2[]){
if( strlen(s1) + strlen(s2) < 200 )//where 200 is the size of s3
{
sprintf(s3, "%s%s", s1, s2);
}
else
{
printf("\nInput strings too large");
}
}
See Returning C string from a function.
You're taking chars as arguments and using it as a return value. You probably want s1, s2 to be const char *:
char *cat (const char *s1, const char *s2){
You will have to return a char * too, which means you will have to allocate something that isn't on the stack.
char *cat (const char *s1, const char *s2){
char *s3 = (char*)malloc(200);
strcpy(s3,s1);
strcpy(s3+strlen(s1),s2); // strcat(s3, s1);
return s3;
}
A char is a small integer type (a byte), which can hold just a single encoded character, not a string. Strings in C don't have a dedicated type, they're just defined as a sequence of characters, ending with a 0 byte. So, you naturally store strings in arrays of char. E.g. the array
char str[30];
Can store a string of up to 29 characters (one more is needed for the terminating 0).
Furthermore, you have to know that arrays can't be passed to or returned from functions in C. Instead, pointers are used. If you write arrays as function arguments or return values, these types are automatically adjusted to the corresponding pointer types. It's common to say the array "decays" as a pointer. So, in your code, you attempt to return an array. Instead, a pointer to the first array element is returned. Because this array is local to your function, it doesn't exist any more after the return, so you are returning an invalid pointer.
That's why the library function strcat expects the caller to give a pointer to the result, instead of returning the result. A typical simple strcat function could look like this (not the original, returning nothing here to make the code simple):
void mystrcat(char *s, const char *append)
{
while (*s) ++s; // search end of s
while ( (*s++ = *append++) ); // copy until end of append
}
To understand this code, you have to know that 0 is false in C when evaluated in a boolean context, and any other value is true. ++ increments, so applied to pointers, moves them to point to the next element. Therefore, this code examines each character in *s until it finds a 0 byte and then starts copying characters from *append there until the 0 byte in *append is hit.
If you absolutely want to return the result, you have to dynamically allocate memory for it in your function. This could look like the following:
char *concatenate(const char *s1, const char *s2)
{
size_t resultlen = strlen(s1) + strlen(s2) + 1; // one more for the 0 byte
char *result = malloc(resultlen);
if (!result) return 0; // allocation failed, out of memory
char *p = result;
while ( (*p = *s1++) ) ++p; // copy from s1 until 0
while ( (*p++ = *s2++) ); // copy from s2 until 0
return result;
}
Of course, in this case, the caller has to free() the result when it's no longer needed.

How does strchr implementation work

I tried to write my own implementation of the strchr() method.
It now looks like this:
char *mystrchr(const char *s, int c) {
while (*s != (char) c) {
if (!*s++) {
return NULL;
}
}
return (char *)s;
}
The last line originally was
return s;
But this didn't work because s is const. I found out that there needs to be this cast (char *), but I honestly don't know what I am doing there :( Can someone explain?
I believe this is actually a flaw in the C Standard's definition of the strchr() function. (I'll be happy to be proven wrong.) (Replying to the comments, it's arguable whether it's really a flaw; IMHO it's still poor design. It can be used safely, but it's too easy to use it unsafely.)
Here's what the C standard says:
char *strchr(const char *s, int c);
The strchr function locates the first occurrence of c
(converted to a char) in the string pointed to by s. The
terminating null character is considered to be part of the string.
Which means that this program:
#include <stdio.h>
#include <string.h>
int main(void) {
const char *s = "hello";
char *p = strchr(s, 'l');
*p = 'L';
return 0;
}
even though it carefully defines the pointer to the string literal as a pointer to const char, has undefined behavior, since it modifies the string literal. gcc, at least, doesn't warn about this, and the program dies with a segmentation fault.
The problem is that strchr() takes a const char* argument, which means it promises not to modify the data that s points to -- but it returns a plain char*, which permits the caller to modify the same data.
Here's another example; it doesn't have undefined behavior, but it quietly modifies a const qualified object without any casts (which, on further thought, I believe has undefined behavior):
#include <stdio.h>
#include <string.h>
int main(void) {
const char s[] = "hello";
char *p = strchr(s, 'l');
*p = 'L';
printf("s = \"%s\"\n", s);
return 0;
}
Which means, I think, (to answer your question) that a C implementation of strchr() has to cast its result to convert it from const char* to char*, or do something equivalent.
This is why C++, in one of the few changes it makes to the C standard library, replaces strchr() with two overloaded functions of the same name:
const char * strchr ( const char * str, int character );
char * strchr ( char * str, int character );
Of course C can't do this.
An alternative would have been to replace strchr by two functions, one taking a const char* and returning a const char*, and another taking a char* and returning a char*. Unlike in C++, the two functions would have to have different names, perhaps strchr and strcchr.
(Historically, const was added to C after strchr() had already been defined. This was probably the only way to keep strchr() without breaking existing code.)
strchr() is not the only C standard library function that has this problem. The list of affected function (I think this list is complete but I don't guarantee it) is:
void *memchr(const void *s, int c, size_t n);
char *strchr(const char *s, int c);
char *strpbrk(const char *s1, const char *s2);
char *strrchr(const char *s, int c);
char *strstr(const char *s1, const char *s2);
(all declared in <string.h>) and:
void *bsearch(const void *key, const void *base,
size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
(declared in <stdlib.h>). All these functions take a pointer to const data that points to the initial element of an array, and return a non-const pointer to an element of that array.
The practice of returning non-const pointers to const data from non-modifying functions is actually an idiom rather widely used in C language. It is not always pretty, but it is rather well established.
The reationale here is simple: strchr by itself is a non-modifying operation. Yet we need strchr functionality for both constant strings and non-constant strings, which would also propagate the constness of the input to the constness of the output. Neither C not C++ provide any elegant support for this concept, meaning that in both languages you will have to write two virtually identical functions in order to avoid taking any risks with const-correctness.
In C++ you wild be able to use function overloading by declaring two functions with the same name
const char *strchr(const char *s, int c);
char *strchr(char *s, int c);
In C you have no function overloading, so in order to fully enforce const-correctness in this case you would have to provide two functions with different names, something like
const char *strchr_c(const char *s, int c);
char *strchr(char *s, int c);
Although in some cases this might be the right thing to do, it is typically (and rightfully) considered too cumbersome and involving by C standards. You can resolve this situation in a more compact (albeit more risky) way by implementing only one function
char *strchr(const char *s, int c);
which returns non-const pointer into the input string (by using a cast at the exit, exactly as you did it). Note, that this approach does not violate any rules of the language, although it provides the caller with the means to violate them. By casting away the constness of the data this approach simply delegates the responsibility to observe const-correctness from the function itself to the caller. As long as the caller is aware of what's going on and remembers to "play nice", i.e. uses a const-qualified pointer to point to const data, any temporary breaches in the wall of const-correctness created by such function are repaired instantly.
I see this trick as a perfectly acceptable approach to reducing unnecessary code duplication (especially in absence of function overloading). The standard library uses it. You have no reason to avoid it either, assuming you understand what you are doing.
Now, as for your implementation of strchr, it looks weird to me from the stylistic point of view. I would use the cycle header to iterate over the full range we are operating on (the full string), and use the inner if to catch the early termination condition
for (; *s != '\0'; ++s)
if (*s == c)
return (char *) s;
return NULL;
But things like that are always a matter of personal preference. Someone might prefer to just
for (; *s != '\0' && *s != c; ++s)
;
return *s == c ? (char *) s : NULL;
Some might say that modifying function parameter (s) inside the function is a bad practice.
The const keyword means that the parameter cannot be modified.
You couldn't return s directly because s is declared as const char *s and the return type of the function is char *. If the compiler allowed you to do that, it would be possible to override the const restriction.
Adding a explicit cast to char* tells the compiler that you know what you're doing (though as Eric explained, it would be better if you didn't do it).
UPDATE: For the sake of context I'm quoting Eric's answer, since he seems to have deleted it:
You should not be modifying s since it is a const char *.
Instead, define a local variable that represents the result of type char * and use that in place of s in the method body.
The Function Return Value should be a Constant Pointer to a Character:
strchr accepts a const char* and should return const char* also. You are returning a non constant which is potentially dangerous since the return value points into the input character array (the caller might be expecting the constant argument to remain constant, but it is modifiable if any part of it is returned as as a char * pointer).
The Function return Value should be NULL if No matching Character is Found:
Also strchr is supposed to return NULL if the sought character is not found. If it returns non-NULL when the character is not found, or s in this case, the caller (if he thinks the behavior is the same as strchr)
might assume that the first character in the result actually matches (without the NULL return value
there is no way to tell whether there was a match or not).
(I'm not sure if that is what you intended to do.)
Here is an Example of a Function that Does This:
I wrote and ran several tests on this function; I added a few really obvious sanity checks to avoid potential crashes:
const char *mystrchr1(const char *s, int c) {
if (s == NULL) {
return NULL;
}
if ((c > 255) || (c < 0)) {
return NULL;
}
int s_len;
int i;
s_len = strlen(s);
for (i = 0; i < s_len; i++) {
if ((char) c == s[i]) {
return (const char*) &s[i];
}
}
return NULL;
}
You're no doubt seeing compiler errors anytime you write code that tries to use the char* result of mystrchr to modify the string literal being passed to mystrchr.
Modifying string literals is a security no-no, because it can lead to abnormal program termination and possibly denial-of-service attacks. Compilers may warn you when you pass a string literal to a function taking char*, but they aren't required to.
How do you use strchr correctly? Let's look at an example.
This is an example of what not to do:
#include <stdio.h>
#include <string.h>
/** Truncate a null-terminated string $str starting at the first occurence
* of a character $c. Return the string after truncating it.
*/
const char* trunc(const char* str, char c){
char* pc = strchr(str, c);
if(pc && *pc && *(pc+1)) *(pc+1)=0;
return str;
}
See how it modifies the string literal str via the pointer pc? That's no bueno.
Here's the right way to do it:
#include <stdio.h>
#include <string.h>
/** Truncate a null-terminated string $str of $sz bytes starting at the first
* occurrence of a character $c. Write the truncated string to the output buffer
* $out.
*/
char* trunc(size_t sz, const char* str, char c, char* out){
char* c_pos = strchr(str, c);
if(c_pos){
ptrdiff_t c_idx = c_pos - str;
if((size_t)n < sz){
memcpy(out, str, c_idx); // copy out all chars before c
out[c_idx]=0; // terminate with null byte
}
}
return 0; // strchr couldn't find c, or had serious problems
}
See how the pointer returned by strchr is used to compute the index of the matching character in the string? The index (also equal to the length up to that point, minus one) is then used to copy the desired part of the string to the output buffer.
You might think "Aw, that's dumb! I don't want to use strchr if it's just going to make me memcpy." If that's how you feel, I've never run into a use case of strchr, strrchr, etc. that I couldn't get away with using a while loop and isspace, isalnum, etc. Sometimes it's actually cleaner than using strchr correctly.

Add String to Char Pointer in C

I want to add a string to char pointer, how can i do?
For example:
char pointer is char * process_name;
and i have an char array named second. It contains several chars.
I want to copy second to process_name.
If you know the size of the buffer to which process_name points, you can use strncpy().
char * strncpy ( char * destination, const char * source, size_t num );
For example:
strncpy( process_name, second, process_name_size );
process_name[ process_name_size - 1 ] = '\0';
You can use 'strcat' or 'strncat' to concatenate two strings. But your process_name buffer has to be big enough to contain both strings. strcat will handle the \0-bytes for you but i'd still suggest you use strncat with fixed length.
char *strcat(char *restrict s1, const char *restrict s2);
char *strncat(char *restrict s1, const char *restrict s2, size_t n);
Example usage would be:
process_name = realloc(process_name, strlen(process_name) + strlen(second));
strncat(process_name, second, strlen(second));
This might not be the best example but it should show the general direction.
Strictly speaking, you cannot 'add a string' to a char pointer.
You can add a string to a buffer pointed to by a char pointer IF there is sufficient allocated space in the buffer (plus one for the terminating '\0') using a standard library call such as strncpy() [depends on your precise requirements, insert versus append etc].
I resolve this problem with strdup() function.

Resources