I have a char array in C
#define BUFSIZE 2048
unsigned char buf[BUFSIZE];
char request[10];
strcat(request "GET key01");
request[10] = '\0';
buf = request;
The request is coming from a the network with a client-server socket simulation, but I did not include that here to keep it simple.
Anyways, I have to tokenize the buf string, but also keep an untokenized copy. I tried this:
char* buf_for_token = buf;
printf("What is the buf before tokenization? %s\n", buf);
const char s[2] = " ";
char *token;
token = strtok(buf_for_token, s);
token = strtok(NULL, s);
printf("What is the buf after tokenization? %s\n", buf);
My output is:
What is the buf before tokenization? GET key01
What is the buf after tokenization? GET
I would instead like:
What is the buf before tokenization? GET key01
What is the buf after tokenization? GET key01
How can I get the value of a string from a char array and save a copy that I can manipulate without affecting the original value?
You can use the C <string.h> function:
strcpy(const char *dest, const char *src);
Which will copy from src until '\0' char, into dest, and include the '\0' char.
OR
use:
strcat(const char *dest, const char *src);
Which will append to the end of the already existent string, starting at null terminate '\0' of dest, adding all chars until and including '\0'.
OR
use:
strncpy(const char *dest, const char *src, int size);
Which wil copy n chars from char *src into char *dest.
strtok is destructive; it will modify the contents of your buffer as you tokenize it by overwriting the delimiters with a zero byte. If you need to preserve the original buffer contents, then you will either need to copy to another buffer and tokenize that second buffer, or you will need to use something besides strtok (which is often the right answer anyway).
Look at functions like strchr or strpbrk. You'll need to figure out how to extract and save the individual tokens to another buffer, but that's not that hard.
Related
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 do I convert char pointer into a string?
I know it's a pointer to a string, but I don't want a pointer.
For example:
char* token;
char strings[50];
char strings[50] is a char string.
What is easiest way to turn *token into a string?
mbtowc turns *token in a single char, I don't want single char. Entire String.
The sad fact is that most C string library functions like strcpy(), strncpy() and memcpy() are somewhat lacking in terms of safely, reliably, and/or simply copying a C string into a char array.
Here's one way to do it:
size_t len = strlen(token);
if (len < sizeof(strings)) {
memcpy(strings, token, len); // assumes token doesn't point inside strings, else use memmove()
strings[len] = '\0';
} else {
// input string was too long, handle the error somehow
}
As you can imagine, many projects implemented in C will define a few functions to handle C strings efficiently in whatever way they need, with appropriate error handling.
/*until C99*/
char *token = "test";
char strings[50];
/* copy to sized buffer: */
strncpy ( strings, token, sizeof(strings) );
strings[sizeof(strings) - 1] = 0;
/*since C11*/
char *token = "test";
char strings[50];
/* returns zero on success, returns non-zero on error.*/
int r1 = strncpy_s(strings, sizeof(strings), token, strlen(token));
/*use strlen_s if not sure whether token is not null poiter*/
I have uni project, I need to check if the syntax is right. I get pointer to a string, and check if the first token acceptable. In case it's OK, i move forward. But in case it's not OK, i need to print what is wrong.
What i did is to create a buffer since i can't change the original string.
After that i use strtok to cut the buffer, and look if the token i got is acceptable.
char *str = "sz = 12345";
printf("The check of MACRO: %d\n", isMacro(str));
int isMacro(char *str)
{
char buf = NULL;
char *token;
strcpy(&buf,str);
token = strtok(&buf," ");
printf("You here, value token is %s\n",token);
}
I expected that printf would print the 'sz' but it prints:
You here, value str is sz<▒R
char buf = NULL;
This is a type error. buf is a single character, but NULL is a pointer value. You can't store a pointer in a char.
strcpy(&buf,str);
This code has undefined behavior (unless str happens to be an empty string). buf is not a buffer, it is a single char, so it does not have room to store a whole string.
If you want to make a copy of a string, you need to allocate enough memory for all of its characters:
You could use strdup (which is in POSIX, but not standard C):
char *buf = strdup(str);
if (!buf) {
... handle error ...
}
...
free(buf);
You could replicate strdup manually:
char *buf = malloc(strlen(str) + 1);
if (!buf) {
... handle error ...
}
strcpy(buf, str);
...
free(buf);
You could use a variable-length array (but you're limited by the size of your stack and you have no way to check for errors):
char buf[strlen(str) + 1];
strcpy(buf, str);
...
buf is a single char instead of a pointer to a char. In fact, if you're planning to do strcpy to copy a string to it, you need to allocate memory first using malloc. Instead I'd suggest you to use a function like strdup instead of strcpy to create a copy of the original string to modify it using strtok. Remember to free the strduped string later.
Something like this.
int isMacro(char *str)
{
char *buf = NULL;
char *token;
buf = strdup(str);
token = strtok(buf," ");
printf("You here, value of token is %s\n",token);
free(buf);
}
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.
#include <stdio.h>
#include <string.h>
char *replace_str(char *str, char *orig, char *rep)
{
static char buffer[4096];
char *p;
if(!(p = strstr(str, orig))) // Is 'orig' even in 'str'?
return str;
strncpy(buffer, str, p-str);
// Copy characters from 'str' start to 'orig' st$
buffer[p-str] = '\0';
sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig)); // <-- here
return buffer;
}
int main(void)
{
puts(replace_str("Hello, world!", "world", "Miami"));
return 0;
}
How this code work, please explain thoroughly...
I am not able to recognize the working of p+strlen(orig).
The sprintf command has the following declaration:
sprintf(char *str, const char *format, ...);
your declaration in question is:
sprintf(buffer+(p-str), "%s%s", rep, p+strlen(orig));
The sprintf command writes to the character pointer str, the values rep and p+strlen(orig) in accordance with the format string "%s%s". Essentially, it is simply combining (or concatenating) rep and p+strlen(orig) in buffer+(p-str).
Note that str (in the sprintf declaration) is of type char * meaning that buffer+(p-str) must also be type char * (a character pointer). buffer has a pointer address, say 1000 as an example. To that address, we will add the difference p-str (say 25). So the sprintf command will combine the two strings rep and p+strlen(orig) in memory beginning at the address 1000 + 25 = 1025
We also know from the format string "%s%s" that both rep and p+strlen(orig) will likewise be type char * pointers. The address of rep is whatever it is, but the next char * pointer p+strlen(orig) will be p (say 1500) + strlen(orig) (the length of orig assume is 20 chars. So sprintf will read the string value beginning at address 1520 along with the string rep into buffer at address buffer+(p-str) (or 1025 for this example).
Lets say the pointers point to the following strings:
rep = "In the beginning"
p = "the sky was blue and there was light!"
Lets also say that strlen(orig) = 20
p+strlen(orig) = p[20] = " there was light!"
So the resulting string in buffer at (my fake address 1025) is:
buffer+(p-str) = "In the beginning there was light!"