memcpy uint32_t and char* into char* - c

this doesnt works for me:
char buff[11];
char* msg_ptr;
msg_ptr = buff;
uint8_t id;
uint32_t msg_length;
char msg[] = "hallo";
id = 77;
msg_length = 5;
memcpy(buff, &id, sizeof(uint8_t));
memcpy(buff+1, &msg_length, sizeof(uint32_t));
strcpy(buff+5, msg);
printf("id :%d\n",*(uint8_t*)msg_ptr);
msg_ptr++;
printf("msg_length: %d\n", *msg_ptr);
msg_ptr++;
printf("msg: %s\n", msg_ptr);
Id and msg_lentgh are shown on konsole, but after that i get a segmentation fault.
I am new to C please be as detailied as possible.
Regards

msg_ptr = msg+1
That's your problem. You should do *msg_ptr++* to go to next position (which is *msg_len*). Instead you change the pointer to point the 'a' within the msg string.
2 more bugs in the code:
You don't take into account the terminating '\0' of the string. You have 1 + 4 + 5 + 1, the last one being the terminating '\0'. Also, when working with strings use strncpy, which handles copying the string terminator. memcpy will copy exactly as much as you ask it to. You are corrupting your stack.
On the last line you must print the string as a a number. Use %s.
Here's what Wikipedia has to say about C strings and stack overflows while you are at it.

Related

How to copy the string that remains after using strncpy

I am learning C and want to learn how I can copy the remaining characters leftover in the string after using strncpy. I would like to have the string Hello World broken down into two separate lines.
For example:
int main() {
char someString[13] = "Hello World!\n";
char temp[13];
//copy only the first 4 chars into string temp
strncpy(temp, someString, 4);
printf("%s\n", temp); //output: Hell
}
How do I copy the remaining characters (o World!\n) in a new line to print out?
The one thing you should learn about strncpy is never use this function.
The semantics of strncpy are counter-intuitive and poorly understood by most programmers. It is confusing and error prone. In most cases, it does not do the job.
In your case, it copies the first 4 bytes and leaves the rest of temp uninitialized. You might have known this, but still invoked undefined behavior by passing temp to printf as a string argument.
If you want to manipulate memory, use memcpy and memmove and be careful about null terminators.
As a matter of fact, the string "Hello world!\n" has 13 characters and a null terminator, requiring 14 bytes in memory. Defining char someString[13] = "Hello World!\n"; is legal but it makes someString not a C string.
#include <stdio.h>
#include <string.h>
int main() {
char someString[14] = "Hello World!\n";
char temp[14];
memcpy(temp, someString, 4); //copy only the first 4 chars into string temp
temp[4] = '\0'; // set the null terminator
printf("%s\n", temp); //output: Hell\n
strcpy(temp + 4, someString + 4); // copy the rest of the string
printf("%s\n", temp); //output: Hello World!\n\n
memcpy(temp, someString, 14); //copy all 14 bytes into array temp
printf("%s\n", temp); //output: Hello World!\n\n
// Note that you can limit the number of characters to output for a `%s` argument:
printf("%.4s\n", temp); //output: Hell\n
return 0;
}
You can read more about strncpy here:
https://randomascii.wordpress.com/2013/04/03/stop-using-strncpy-already/
http://the-flat-trantor-society.blogspot.com/2012/03/no-strncpy-is-not-safer-strcpy.html
https://devblogs.microsoft.com/oldnewthing/?p=36773
What is the best alternative to strncpy()?
First of all, char someString[13] , you don't have enough space for the string Hello World\n, since you have 13 characters but you need at least size of 14, one extra byte for the NULL byte, '\0'. You better off let the compiler decide the size of the array, wouldn't be prone to UB that way.
To answer your question, you can just use printf() to display the remaining part of the string, you only need to specify a pointer to the element you want to start at.
In addition, strncpy() doesn't NULL terminate tmp, you are gonna have to do that manually if you want functions like printf() or puts() to function properly.
#include <stdio.h>
#include <string.h>
int main(void)
{
char someString[] = "Hello World!\n";
char temp[14];
strncpy(temp,someString,4);
temp[4] = '\0'; /* NULL terminate the array */
printf("%s\n",temp);
printf("%s",&someString[4]); /* starting at the 4th element*/
return 0;
}
In your case you could try something like:
char temp2[13];
strncpy(temp2, &someString[4], 9);
By the way you are missing a semicolon:
char someString[13] = "Hello World!\n";
The think you can do is to push your pointer of n character and copy the size - n caractere:
size_t n = 4; // nunmber caractere to copy first
size_t size = 13; // string length
char someString[size] = "Hello World!\n";
char temp[size];
char last[size - n]; // the string that contain the reste
strncpy(temp, someString, n); // your copy
strncpy(last, someString + n, 13 - n); // copy of reste of the string

Unexpected return value from string

I am trying to get just the phone number out of the string passed into getPhoneNumber(char[] str), but for some reason, i get some random character appended to it each time i run the code, please i need help.
source code
#include <stdio.h>
#include <string.h>
char* getPhoneNumber(char str[]);
int main(){
getPhoneNumber("AT+CMGR=5 \n+CMGR: \"REC READ\",\"+9349036332058\",\"samuel\",\"17/03/31,20:44:52+04\"\nHOW THINS fa OK");
return 0;
}
char* getPhoneNumber(char str[]){
char *temp = strchr(str, ',')+2;
const unsigned short len1 = strlen(temp);
printf("value in temp : %s\n\n",temp);
char *strPtr = strchr(temp, '\"');
const unsigned short len2 = strlen(strPtr);
printf("value in strPtr : %s\n\n",strPtr);
int phone_num_len = len1-len2;
char phone_num[phone_num_len];
strncpy(phone_num, temp,phone_num_len);
printf("Phone number : %s",phone_num);
}
I also printed out individual values of temp and strPtr for debugging purposes, but the returned values seems ok.
The output of the program is shown in the image below.
You're not setting aside enough space for phone_num. As a result, printf is reading past the end of the array. This invokes undefined behavior. That is why you see extra characters when running locally but it appears to work fine on ideone (it also appears to run fine for me).
You need one more byte for the null terminating character for the string. Also, you need to manually add that null terminator since the strncpy function won't do it for you since there's no null terminator within phone_num_len bytes of temp.
char phone_num[phone_num_len+1];
strncpy(phone_num, temp,phone_num_len);
phone_num[phone_num_len] = '\0';
From the man page for strncpy(char * dst, const char * src, size_t len):
If src is less than len characters long, the remainder of dst is filled with `\0' characters. Otherwise, dst is not terminated.
So it is not, as you seem to expect, terminating the "string" you are copying.

Segmentation fault? String tokenization

I'm trying to write a function will convert the characters from an array into ints so that I can produce a sum or other math process for each group. I know that first I have to use strtok to get rid of the spaces and '+'. I've been trying to first at least start with getting strtok to work but it keeps saying segmentation fault when I try to run it.
Any help?
#include <string.h>
#include <stdio.h>
int main(void)
{
char* string[] = { "10 + 20", "1 + 3 + 6 + 8" };
sum(string[0]);
}
int sum(char* s)
{
char *stringcopy = malloc( strlen(s) + 1 );
char* del = " +";
char* token;
int i;
stringcopy = s; /* 'copy' problem here */
token = strtok(stringcopy, del);
while( token ) {
printf("%s\n", token);
token = strtok(NULL, del);
}
return 11; /* placeholder until I get the sum */
}
There is a simple reason strtok gives you a segmentation fault:
You are running it on a string literal, which despite having type char[n] is an immutable object.
strtok modifies any string you run it on!
The work-around is simple: Run on a copy. Here a function for duplicating strings (most C libraries provide this non-standard function as char* strdup(const char*):
char* my_strdup(const char* s) {
size_t size = strlen(s)+1;
char* ret = malloc(size);
if(ret)
memcpy(ret, s, size);
return ret;
}
Don't forget to free() the copy later.
You tried doing so, but after getting off to a good start and reserving space for the string with malloc, you just discarded it (memory leak) by assigning a pointer to the literal to that same pointer.
This statement
textcopy = s; /* making copy for strtok */
does not do what you think.
In fact there us a memory leak because at first you allocated memory and textcopy got the address of the first byte of the storage
char *textcopy = malloc( strlen(s) + 1 );
and then you reassigned textcopy.
textcopy = s; /* making copy for strtok */
You have to use standard function strcpy instead
strcpy( textcopy, s ); /* making copy for strtok */
Also it would be better if the function would declared as
int stringSum(const char* s);
This line does not do what you thought it would:
textcopy = s; /* making copy for strtok */
No string is copied here. All that happens is that instead of pointing to the first byte of the block of memory that you just allocated for it (with malloc( strlen(s) + 1 )),
textcopy now points directly at the first byte of the literal string "10 + 20" that you passed to stringSum as s.
You probably wanted something like strcpy(textcopy, s). I had suggested strncpy earlier; strncpy(textcopy, s, strlen(s)) + 1 might work, but (as the comments explain) seems to be rather pointless to use in this context.
The line
textcopy = s; /* making copy for strtok */
doesn't make copy of s and put it in textcopy. Instead, you need to use:
strcpy(textcopy, s);

parsing a string using pointer pointing to a string without using strdup and strtok functions

I am writing a code in which i want to parse a incoming string(basically this is for embeddded project, but i want to test it first in C).The string can be a GPS output , basically a NMEA string.Even though i had done parsing using strdup and strtok function but i am, stucked up when i am doing parsing simply using a string and pointer pointing to that string.
#include<stdio.h>
int main()
{int i;
char inputstring[100]; //i assumed it to be input string, in this case enter by user.
char *ptr[12];
printf("Enter the string to be printed now.: \n");
scanf("%s",inputstring);
printf("the input string being received from the user is = \n %s \n", inputstring);
for(i=0;i<12;i++) /*used this for loop to get first 12 characters from inputstring copied into ptr[i] */
{
ptr[i] = &inputstring[i];
}
printf("value of store is = %s \n",*ptr);
return 0;
}
but the ouput of this is whole inputstring rather then the first 12 characters.I dig this out further and find that *ptr when points to inputstring, its points to the inputstring[0]
and will copy whole string in it rather then just copying first 12 characters.How can we limit this ?
Need help.I have a alternate way but need help to dig out this code of mine.
This:
char *ptr[12];
is an array of 12 character pointers, but you seem to want it to be an array of 12 characters. Remove the asterisk:
char ptr[12];
and re-name it, since ptr is a lousy name:
char tmp[12];
Then make sure that you terminate it, and have room for the terminator:
char tmp[13];
strlcpy(tmp, inputstring, sizeof tmp);
char ptr[12];
instead of
char *ptr[12];
char ptr[12]: is an array of characters with size = 12 elements of chars. the size of each element in the array is = the size of char (1 byte).
char *ptr[12]: is an array of pointers with size = 12 elements of pointers. the size of each element in the array is = the size of pointer (4 bytes for 32-bit systems and 8 bytes for 64-bit systems). each pointer in the array could point to a string (char array).
you should use the following code instead
for(i=0;i<12;i++)
{
ptr[i] = inputstring[i];
}
or more simple
memcpy(ptr, inputstring, 12);
and you have to add null charachter at the end of your ptr string before you print the ptr string.
So you have to add 1 element to the size of the ptr char array
char ptr[13];
memcpy(ptr, inputstring, 12);
ptr[12] = '\0';
printf("value of store is = %s \n",ptr);

Inserting char string into another char string

Ok, so I have a char stringA and char stringB, and I want to be able to insert stringB into stringA at point x.
char *stringA = "abcdef";
char *stringB = "123";
with a product of "ab123cdef"
does anyone know how to do this? Thanks in advance
char * strA = "Blahblahblah", * strB = "123", strC[50];
int x = 4;
strncpy(strC, strA, x);
strC[x] = '\0';
strcat(strC, strB);
strcat(strC, strA + x);
printf("%s\n", strC);
Explanation:
You declare the two strings you will be joining, plus a third string into which you will put them.
You declare an integer to tell the program after how many characters you wish to insert the second string into the first.
The strncpy function copies the first x characters into strC. You have to add the null ('\0') character at the end, otherwise you'll probably get rubbish.
Strcat to copy the second string.
Another strcat to copy the remaining part of the first string (strA + x).
Hope that helps.
Remark: remember to make strC long enough to contain both strA and strC, otherwise you'll produce a segmentation fault. You may do this by declaring the string as an array, like in my example.
stringA and stringB are both pointers - they contain the starting address for a blob of memory. The memory they are pointing to contain continuous strings of characters: "abcdef" and "123" respectively. Since strings are contiguous blocks memory (meaning that the memory location of a given character is one byte after the previous) you can't insert more characters into the middle of a string without first moving some characters. In your case you can't even really do this, since the amount of memory allocated for each string is exactly large enough to hold JUST that string (ignoring padding).
What you are going to have to do is copy the strings to another block of memory, one that you have allocated for that purpose, and copy them so that the second string starts x characters into the first string.
Several other SO users have posted code-solutions but I think you should try and find the exact solution on your own (and hopefully my high-level explanation of what's going on will help).
Here a more general solution.
Note that destination must have enough space in memory to add seed (e.g. an heap-allocated array of size grater than strlen(seed)+strlen(destination) ). So, concerning the question, you have to create a larger array.
/*
destination: a NULL terminated string
pos: where insert seed
seed: a NULL terminated string
*/
void insertString(char* destination, int pos, char* seed)
{
char * strC;
strC = (char*)malloc(strlen(destination)+strlen(seed)+1);
strncpy(strC,destination,pos);
strC[pos] = '\0';
strcat(strC,seed);
strcat(strC,destination+pos);
strcpy(destination,strC);
free(strC);
}
int insert_pos = 5;
int product_length = strlen(stringA) + strlen(stringB) + 1;
char* product = (char*)malloc(product_length);
strncpy(product, stringA, insert_pos);
product[insert_pos] = '\0';
strcat(product, stringB);
strcat(product, stringA + insert_pos);
...
free(product);
char *strInsert(char *str1, const char *str2, int pos) {
size_t l1 = strlen(str1);
size_t l2 = strlen(str2);
if (pos < 0) pos = 0;
if (pos > l1) pos = l1;
char *p = str1 + pos;
memmove(p + l2, p, l1 - pos);
memcpy (p, str2, l2);
return str1;
}

Resources