Here's my code
#include <stdio.h>
#include <string.h>
int main(){
char pal[8] = "ciaooaic";
char pal1[7] = "ciaoaic";
int lenPal = strlen(pal);
int lenPal1 = strlen(pal1);
printf("strlen('%s'): %d\n", pal, lenPal);
printf("strlen('%s'): %d\n", pal1, lenPal1);
return 0;
}
The problem is that when I run this code the output is:
strlen('ciaooaicP#'): 11
strlen('ciaoaic'): 7
The first string has also another non-printable char between P and #. I'm a noob, so maybe I missed something obvious. Can someone help me?
edit:
just give one extra space like char pal[9] = "ciaooaic"; char pal1[8] = "ciaoaic";
It works, but why? I understand that there should be a space for \0, but "ciaoaic" works without it...
1. You don't leave room for a null terminator, as you pass them to strlen(), therefore your code exhibits undefined behaviour -
char pal[8] = "ciaooaic";
char pal1[7] = "ciaoaic";
Leave a space for '\0'. Declare and initialize like this -
char pal[9] = "ciaooaic";
char pal1[8] = "ciaoaic";
2. And strlen() returns size_t not int , so write like this -
size_t lenPal = strlen(pal);
size_t lenPal1 = strlen(pal1);
and use %zu specifier to print both these variables.
You have not kept space for the NULL terminating character \0.
Either increase the size of the array by 1
char pal[9] = "ciaooaic";
char pal1[8] = "ciaoaic";
OR
Do not specify the length at all
char pal[] = "ciaooaic";
char pal1[] = "ciaoaic";
Both the above answers are sufficient to solve your doubts.
Increase the the length of both pal and pal1 by one as there there is no space for the assignment of the null character( '\0') at the end.
However there is small trick to print the non null terminated character using printf
printf("strlen('%.*s'): %d\n",8, pal, lenPal);
printf("strlen('%.*s'): %d\n",7, pal1, lenPal1);
Link for the above trick:BRILLIANT
Related
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.
I am appending a string using single character, but I am not able to get it right. I am not sure where I am making mistake. Thank you for your help in advance. The original application of the method is in getting dynamic input from user.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void main(){
int j;
char ipch=' ';
char intext[30]="What is the problem";
char ipstr[30]="";
printf("Input char: ");
j=0;
while(ipch!='\0'){
//ipch = getchar();
ipch = intext[j];
printf("%c", ipch);
strcat(ipstr,&ipch);
j++;
}
puts("\n");
puts(ipstr);
return;
}
Following is the output I am getting.
$ ./a.out
Input char: What is the problem
What is h e
p
oblem
change
strcat(ipstr,&ipch);
to
strncat(ipstr, &ipch, 1);
this will force appending only one byte from ipch. strcat() will continue appending some bytes, since there's no null termination character after the char you are appending. as others said, strcat might find somewhere in memory \0 and then terminate, but if not, it can result in segfault.
from manpage:
char *strncat(char *dest, const char *src, size_t n);
The strncat() function is similar to strcat(), except that
it will use at most n characters from src; and
src does not need to be null-terminated if it contains n or more characters.
strcat requires its second argument to be a pointer to a well-formed string. &ipch does not point to a well-formed string (the character sequence of one it points to lacks a terminal null character).
You could use char ipch[2]=" "; to declare ipch. In this case also use:
strcat(ipstr,ipch); to append the character to ipstr.
ipch[0] = intext[j]; to change the character to append.
What happens when you pass &ipch to strcat in your original program is that the function strcat assumes that the string continues, and reads the next bytes in memory. A segmentation fault can result, but it can also happen that strcat reads a few garbage characters and then accidentally finds a null character.
strcat() is to concatenate strings... so passing just a char pointer is not enough... you have to put that character followed by a '\0' char, and then pass the pointer of that thing. As in
/* you must have enough space in string to concatenate things */
char string[100] = "What is the problem";
char *s = "?"; /* a proper '\0' terminated string */
strcat(string, s);
printf("%s\n", string);
strcat function is used to concatenate two strings. Not a string and a character. Syntax-
char *strcat(char *dest, const char *src);
so you need to pass two strings to strcat function.
In your program
strcat(ipstr,&ipch);
it is not a valid statement. The second argument ipch is a char. you should not do that. It results in Segmentation Fault.
This is to convert from char pointer into char.
I followed the codes from another topic but it seems like it's not working to me.
I am using Open VMS Ansi C compiler for this. I don't know what's the difference with
another Platform.
main(){
char * field = "value1";
char c[100] = (char )field;
printf("c value is %s",&c);
}
the output of this is
c value is
which is unexpected for me I am expecting
c value is value1
hope you can help me.
strcpy(c, field);
You must be sure c has room for all the characters in field, including the NUL-terminator. It does in this case, but in general, you will need an if check.
EDIT: In C, you can not return an array from a function. If you need to allocate storage, but don't know the length, use malloc. E.g.:
size_t size = strlen(field) + 1; // If you don't know the source size.
char *c = malloc(size);
Then, use the same strcpy call as before.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char * field = "value";
char c[100]="";
strncpy(c,field,100);
printf("c value is %s",c);
return 0;
}
In C, the char type holds a single character, not a string. char c[100]; doesn't allocate a char of length 100, it allocates an array of 100 consecutive chars, each one byte long, and that array can hold a string.
So what you seem to want to do is to fill an array of chars with the same char values that are at the location pointed at by a char *. To do that, you can use strncpy() or any of several other functions:
strncpy(c,field,100); /* copy up to 100 chars from field to c */
c[99] = '\0'; /* ..and make sure the last char in c is '\0' */
..or use strcpy() since you know the string will fit in c (better in this case):
strcpy(c,field);
..or:
snprintf(c,100,"%s",field);
Help me in solving 2 questions on pointers:
1)Please tell me why do I get 'segmentation fault' when I run following snippet
main()
{
char *str1 = "united";
char *str2 ="front";
char *str3;
str3 = strcat(str1,str2);
printf("\n%s",str3);
}
2)Why don't I get output in following code:
main()
{
char str[10] = {0,0,0,0,0,0,0,0,0,0};
char *s;
int i;
s = str;
for(i=0 ; i<=9;i++)
{
if(*s)
printf("%c",*s);
s++;
}
}
Thank u.
You should review how strcat works. It will attempt to rewrite the memory at the end of your str1 pointer, and then return the destination pointer back to you. The compiler only allocated enough memory in str1 to hold "united\0" (7 chars), which you are trying to fill with "unitedfront\0" (12 chars). str1 is pointing to only 7 allocated characters, so there's no room for the concatenation to take place.
*s will dereference s, effectively giving you the first character in the array. That's 0, which will evaluate to false.
1) compiles to something like:
const char _str1[7] = "united";
const char _str2[6] ="front";
char *str1 = _str1;
char *str2 = _str2;
strcat(str1,str2);
str3 = str1;
str1 points to a buffer which is exactly 7 bytes long and is filled with 6 characters. The strcat put another 5 bytes into that buffer. 7 bytes cannot hold 11 characters.
The C there is no magic! If you do not explicitly allocate space for something, no one else does it either.....
2) isn't going to print anything. It steps through an array, every element of which is 0. It then tests if the current item (*s) is not 0 (if(*s)) , and if so, prints that item as a character. However, since the item always is 0, it always fails to test.
for question 2, think about what the following line does:
if(*s)
I have a string:
char * someString;
If I want the first five letters of this string and want to set it to otherString, how would I do it?
#include <string.h>
...
char otherString[6]; // note 6, not 5, there's one there for the null terminator
...
strncpy(otherString, someString, 5);
otherString[5] = '\0'; // place the null terminator
Generalized:
char* subString (const char* input, int offset, int len, char* dest)
{
int input_len = strlen (input);
if (offset + len > input_len)
{
return NULL;
}
strncpy (dest, input + offset, len);
return dest;
}
char dest[80];
const char* source = "hello world";
if (subString (source, 0, 5, dest))
{
printf ("%s\n", dest);
}
char* someString = "abcdedgh";
char* otherString = 0;
otherString = (char*)malloc(5+1);
memcpy(otherString,someString,5);
otherString[5] = 0;
UPDATE:
Tip: A good way to understand definitions is called the right-left rule (some links at the end):
Start reading from identifier and say aloud => "someString is..."
Now go to right of someString (statement has ended with a semicolon, nothing to say).
Now go left of identifier (* is encountered) => so say "...a pointer to...".
Now go to left of "*" (the keyword char is found) => say "..char".
Done!
So char* someString; => "someString is a pointer to char".
Since a pointer simply points to a certain memory address, it can also be used as the "starting point" for an "array" of characters.
That works with anything .. give it a go:
char* s[2]; //=> s is an array of two pointers to char
char** someThing; //=> someThing is a pointer to a pointer to char.
//Note: We look in the brackets first, and then move outward
char (* s)[2]; //=> s is a pointer to an array of two char
Some links:
How to interpret complex C/C++ declarations and
How To Read C Declarations
You'll need to allocate memory for the new string otherString. In general for a substring of length n, something like this may work for you (don't forget to do bounds checking...)
char *subString(char *someString, int n)
{
char *new = malloc(sizeof(char)*n+1);
strncpy(new, someString, n);
new[n] = '\0';
return new;
}
This will return a substring of the first n characters of someString. Make sure you free the memory when you are done with it using free().
You can use snprintf to get a substring of a char array with precision:
#include <stdio.h>
int main()
{
const char source[] = "This is a string array";
char dest[17];
// get first 16 characters using precision
snprintf(dest, sizeof(dest), "%.16s", source);
// print substring
puts(dest);
} // end main
Output:
This is a string
Note:
For further information see printf man page.
You can treat C strings like pointers. So when you declare:
char str[10];
str can be used as a pointer. So if you want to copy just a portion of the string you can use:
char str1[24] = "This is a simple string.";
char str2[6];
strncpy(str1 + 10, str2,6);
This will copy 6 characters from the str1 array into str2 starting at the 11th element.
I had not seen this post until now, the present collection of answers form an orgy of bad advise and compiler errors, only a few recommending memcpy are correct. Basically the answer to the question is:
someString = allocated_memory; // statically or dynamically
memcpy(someString, otherString, 5);
someString[5] = '\0';
This assuming that we know that otherString is at least 5 characters long, then this is the correct answer, period. memcpy is faster and safer than strncpy and there is no confusion about whether memcpy null terminates the string or not - it doesn't, so we definitely have to append the null termination manually.
The main problem here is that strncpy is a very dangerous function that should not be used for any purpose. The function was never intended to be used for null terminated strings and it's presence in the C standard is a mistake. See Is strcpy dangerous and what should be used instead?, I will quote some relevant parts from that post for convenience:
Somewhere at the time when Microsoft flagged strcpy as obsolete and dangerous, some other misguided rumour started. This nasty rumour said that strncpy should be used as a safer version of strcpy. Since it takes the size as parameter and it's already part of the C standard lib, so it's portable. This seemed very convenient - spread the word, forget about non-standard strcpy_s, lets use strncpy! No, this is not a good idea...
Looking at the history of strncpy, it goes back to the very earliest days of Unix, where several string formats co-existed. Something called "fixed width strings" existed - they were not null terminated but came with a fixed size stored together with the string. One of the things Dennis Ritchie (the inventor of the C language) wished to avoid when creating C, was to store the size together with arrays [The Development of the C Language, Dennis M. Ritchie]. Likely in the same spirit as this, the "fixed width strings" were getting phased out over time, in favour for null terminated ones.
The function used to copy these old fixed width strings was named strncpy. This is the sole purpose that it was created for. It has no relation to strcpy. In particular it was never intended to be some more secure version - computer program security wasn't even invented when these functions were made.
Somehow strncpy still made it into the first C standard in 1989. A whole lot of highly questionable functions did - the reason was always backwards compatibility. We can also read the story about strncpy in the C99 rationale 7.21.2.4:
The strncpy function
strncpy was initially introduced into the C library to deal with fixed-length name fields in
structures such as directory entries. Such fields are not used in the same way as strings: the
trailing null is unnecessary for a maximum-length field, and setting trailing bytes for shorter
5 names to null assures efficient field-wise comparisons. strncpy is not by origin a “bounded
strcpy,” and the Committee preferred to recognize existing practice rather than alter the function
to better suit it to such use.
The Codidact link also contains some examples showing how strncpy will fail to terminate a copied string.
I think it's easy way... but I don't know how I can pass the result variable directly then I create a local char array as temp and return it.
char* substr(char *buff, uint8_t start,uint8_t len, char* substr)
{
strncpy(substr, buff+start, len);
substr[len] = 0;
return substr;
}
strncpy(otherString, someString, 5);
Don't forget to allocate memory for otherString.
#include <stdio.h>
#include <string.h>
int main ()
{
char someString[]="abcdedgh";
char otherString[]="00000";
memcpy (otherString, someString, 5);
printf ("someString: %s\notherString: %s\n", someString, otherString);
return 0;
}
You will not need stdio.h if you don't use the printf statement and putting constants in all but the smallest programs is bad form and should be avoided.
Doing it all in two fell swoops:
char *otherString = strncpy((char*)malloc(6), someString);
otherString[5] = 0;
char largeSrt[] = "123456789-123"; // original string
char * substr;
substr = strchr(largeSrt, '-'); // we save the new string "-123"
int substringLength = strlen(largeSrt) - strlen(substr); // 13-4=9 (bigger string size) - (new string size)
char *newStr = malloc(sizeof(char) * substringLength + 1);// keep memory free to new string
strncpy(newStr, largeSrt, substringLength); // copy only 9 characters
newStr[substringLength] = '\0'; // close the new string with final character
printf("newStr=%s\n", newStr);
free(newStr); // you free the memory
Try this code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char* substr(const char *src, unsigned int start, unsigned int end);
int main(void)
{
char *text = "The test string is here";
char *subtext = substr(text,9,14);
printf("The original string is: %s\n",text);
printf("Substring is: %s",subtext);
return 0;
}
char* substr(const char *src, unsigned int start, unsigned int end)
{
unsigned int subtext_len = end-start+2;
char *subtext = malloc(sizeof(char)*subtext_len);
strncpy(subtext,&src[start],subtext_len-1);
subtext[subtext_len-1] = '\0';
return subtext;
}