Convert double to char* in C - c

How can I convert double to char*.
#include <stdio.h>
int main() {
char * buf;
double number = 3.123;
sprintf(buf,"%f",number);
printf("%s",buf);
return 0;
}
This method is does not want to work and I cannot know why.

char* buf declares buf as a character pointer, but does not actually allocate any memory for it. You should declare buf as an array to allocate memory:
char buf[128];
double number = 3.123;
sprintf(buf, "%f", number);

What you probably want is a floating-point to string conversion. What you need is not a char*, but rather an array. The difference is that an array allocates some space for the string, while a pointer is supposed to point to an already existing string, but there is no such string in your code.
Because of this, your code is producing Undefined Behavior (or UB for short), because sprintf() is attempting to write at the address that the buf pointer references. The pointer was not assigned to point to anything, so it is an uninitialized (wild) pointer. This pointer probably contains a random non-sense value and sprintf() is trying to write to it - it won't work, or even worse, will appear to work until you find a problem in a totally different part of the code.
Here is how you should do it:
#include <stdio.h>
int main(void)
{
char buf[100];
double number = 3.123;
sprintf(buf, "%f", number);
printf("%s", buf);
}
First we declare a character array. It can be any length, but for simplicity I chose 100. We can then use this array in a similar way, by writing to it using sprintf().
Now, there may be another problem. It won't show up in this small piece of code, but if you use sprintf() a lot you will notice a lot of bugs if you don't pay attention to the length of the array. The array has only 100 characters, but sprintf() doesn't know that! The function will simply attempt to write past the end of the array, a bug which is called a buffer overflow, yet another case of UB, and also a very common exploit for malicious attacks.
To ease the programmer's life, C has another function that is safer, snprintf(), which works pretty much the same but takes an extra parameter, the maximum length of the array. Here is how it works:
#include <stdio.h>
int main(void)
{
char buf[100];
double number = 3.123;
snprintf(buf, 100, "%f", number);
printf("%s", buf);
}
Even if we tried to write more than 100 characters to the buffer, the function would only write 100 (actually, 99 and a null terminator), and will discard the rest of the contents. This means that, if you pass the correct value for the length of the array, a buffer overflow won't occur.

Related

Why do I need "&" in printf when I want to print a pointer

So I wrote this code where I scan 2 strings. One is declared as an array and one as a pointer.
Now to my question: Why do I need for printing text2 in the printf-statment the "&" before Text2 and when I print Text1 not?
I thought if I put "&" in printf before the variable it pirnts the memory address. I this case not, it prints the string.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char Text1[45];
char *Text2;
scanf("%s" , &Text1);
printf("Text1: %s\n", Text1);
scanf("%s" , &Text2);
printf("Text2: %s\n", &Text2);
return 0;
}
char Text1[45] is an array of characters. The compiler will allocate 45 bites in a program memory for use by the program. The value of the bytes is not known at the moment. So, scanf("%s" , Text1) will put input chars into this memory, assuming that there are less than 44 of them, or it will override the program stack and possibly crash. To prevent from this issue, you should use something like %44s.
There is no need to use & in this case. It does not do much with the array declared in such a way. Therefore you do not need it in printf("%s\n", Text1). But you can use it if you wish.
char *Text2 declares a pointer variable. It means that the compiler allocates enough space to contain the pointer value. The value of the pointer is not defined at the moment, so it does not point anywhere. If you plan to use it with characters, you need to allocate space for them or assign the space in a different way. For example, Text2 = malloc(45) will allocate 45 bytes for use and set a pointer to those bytes. Or you can do Text2 = Text1, assigning address of the first byte of the Text1 array as a pointer. This way the Text1 array will be used as a byte storage.
As a result, scanf("%s", Text2) will use the pointer to access bytes, either allocated by malloc or in the Text1. Now you need to printf("%s\n", Text2).
You should not use & on Text2. It will return an address of the pointer variable and not the address of the array of bytes. You need the latter. So print with &Text2 will return trash and could cause a crash.
BTW, if you used malloc it is a good idea to free the memory which was allocated if it is not needed any longer: free(Text2).
Let's get rid of the part dealing with Text1 for the moment, and focus solely on Text2. That leaves us with something like this:
char *Text2;
scanf("%s" , &Text2);
printf("Text2: %s\n", &Text2);
You've declared Text2 as a pointer, but you haven't initialized it to point to any available space. Then you pass the address of that pointer to scanf, and match it up with a format that tells scanf to read a string, and deposit it at the specified location, so instead of using the pointer as a pointer, scanf will try to use it as if it were an array of char.
To make this work sanely, we want to use the pointer as a pointer, and have it point at some available memory--and we want to tell scanf the size of that memory, so the user can't enter more data than we've provided space to store.
#define MAXSIZE 128
char *Text2 = malloc(MAXSIZE);
scanf("%127s", Text2); // note lack of ampersand here
printf("%s\n", Text2); // Now we don't need an ampersand here either.
Your program is exhibiting undefined behavior and although it is mostly pointless to speculate about undefined behavior, it may be interesting to consider the following:
$ cat a.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(void)
{
char text1[128] = {0};
char *text2;
char text3[128] = {0};
scanf("%44s" , &text2); /* Undefined behavior */
printf("Text1: %s\n", text1);
printf("Text3: %s\n", text3);
return 0;
}
$ echo abcdefghijklmnopHelloWorld | ./a.out
bash: child setpgid (96724 to 96716): Operation not permitted
Text1:
Text3: HelloWorld
The behavior shown above indicates that on my platform, the text that is being written to &text2 is overwriting the value of text3 (this is a stack overflow). This is simply because (on my platform), the variables text2 and text3 are placed 16 bytes apart in the stack when the program executes. To reiterate, the behavior of the code is undefined and the actual performance will vary greatly depending on where it is run, but despite mythical warnings about demons flying out of your nose it is not likely to cause any harm experimenting with it.

Storing a string in char pointer (using scanf)

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(){
char *s1;
char *s2;
printf("Enter the string : ");
scanf("%s",s1);
printf("Enter the string : ");
scanf("%s",s2);
return 0;
}
I'm facing problems in taking inputs in char pointer. Here I'm just taking 1 word as input but Scanf isn't taking any inputs at all when using char pointer, but works well with char arrays. Is it a code blocks bug?
A pointer is a variable that holds a memory address.
An uninitialized variable contains (generally) some random garbage number.
When you pass some random garbage number to scanf and tell it to store a string at that address, it's no surprise that (usually) the program crashes.
It makes no sense to tell scanf to store a string at an address where you don't know what the address is. It's like telling your friend to come over to your house and when they ask which house is yours, you click somewhere random on Google Maps. It's probably going to be in the middle of the ocean or something and they'll drown.
What you need to do is make a space to put the string (such as by declaring an array) and then tell scanf to put the string in that space that you specifically made to hold the string.
A pointer to a string does not hold the string. A pointer to a string is just a signpost saying "the string is over there --->", and you can change it if you want it to point to a different place, maybe holding a different string, but it's never going to hold a string itself.
This is a beginner-C-programmers' bug as old as the language itself.
There are two good solutions to your problem, either change the definitions of s1 and s2 to something like
char s1[BUFFER_LENGTH];
char s2[BUFFER_LENGTH];
...where BUFFER_LENGTH-1 is some sufficiently long string length, to tell the compiler to allocate enough memory on the stack, or manually allocate memory in the heap for them using malloc() like so:
char *s1 = malloc(BUFFER_LENGTH);
char *s2 = malloc(BUFFER_LENGTH);
But keep in mind that in both cases your code is unsafe because for any finite-length buffer, there is a string too long for it, which can cause your program to crash or overwrite something important in memory or give hackers access to stuff etc. etc.
A safe solution is to allocate memory for your strings in one of the two above ways, and only read strings that are small enough to fit into them. If you require the program to be able to handle a string of any length, your code will be much more complex, but there's still a safe way to do it.
#include <stdio.h>
#define BUFFER_LENGTH 20 //Arbitrary max string length + 1
int main(){
char s1[BUFFER_LENGTH]; //Can safely hold 19 chars for string and a null terminator
char s2[BUFFER_LENGTH];
printf("Enter the string : ");
scanf("%19s",s1); //%19s tells the function to only read max 19 characters
printf("Enter the string : ");
scanf("%19s",s2);
{
In the above example a string longer than 19 characters will be truncated, for instance "012345678901234567890" will be stored in s1 as "0123456789012345678" and s2 will have "90" since scanf will just use the leftover characters in the input buffer for the next call.

Why strncpy() is not respecting the given size_t n which is 10 in temp2?

This problem is blowing my mind...Can anyone please sort out the problem because i have already wasted hours on this.. ;(
#include <stdio.h>
#include <string.h>
int main(){
char string[] = "Iam pretty much big string.";
char temp1[50];
char temp2[10];
// strcpy() and strncpy()
strcpy(temp1, string);
printf("%s\n", temp1);
strncpy(temp2, temp1, 10);
printf("%s\n", temp2);
return 0;
}
Result
Iam pretty much big string.
Iam prettyIam pretty much big string.
Expected Result:
Iam pretty much big string.
Iam pretty
The strncpy function is respecting the 10 byte limit you're giving it.
It copies the first 10 bytes from string to temp2. None of those 10 bytes is a null byte, and the size of temp2 is 10, so there are no null bytes in temp2. When you then pass temp2 to printf, it reads past the end of the array invoking undefined behavior.
You would need to set the size given to strncpy to the array size - 1, then manually add the null byte to the end.
strncpy(temp2, temp1, sizeof(temp2)-1);
temp2[sizeof(temp2)-1] = 0;
The address of temp2 is just before the address of temp1 and because you do not copy the final 0, the printf will continue printing after the end of temp2.
As time as you do not insert the 0, the result of printf is undefined.
You invoke Undefined Behavior attempting to print temp2 as temp2 is not nul-terminated. From man strncpy:
"Warning: If there is no null byte among the first n bytes of src,
the string placed in dest will not be null-terminated." (emphasis in
original)
See also C11 Standard - 7.24.2.4 The strncpy function (specifically footnote: 308)
So temp2 is not nul-terminated.
Citation of the appropriate [strncpy] tag on Stack Overflow https://stackoverflow.com/tags/strncpy/info, which may help you to understand what happens exactly:
This function is not recommended to use for any purpose, neither in C nor C++. It was never intended to be a "safe version of strcpy" but is often misused for such purposes. It is in fact considered to be much more dangerous than strcpy, since the null termination mechanism of strncpy is not intuitive and therefore often misunderstood. This is because of the following behavior specified by ISO 9899:2011 7.24.2.4:
char *strncpy(char * restrict s1,
const char * restrict s2,
size_t n);
/--/
3 If the array pointed to by s2 is a string that is shorter than n characters, null characters
are appended to the copy in the array pointed to by s1, until n characters in all have been
written.
A very common mistake is to pass an s2 which is exactly as many characters as the n parameter, in which case s1 will not get null terminated. That is: strncpy(dst, src, strlen(src));
/* MCVE of incorrect use of strncpy */
#include <string.h>
#include <stdio.h>
int main (void)
{
const char* STR = "hello";
char buf[] = "halt and catch fire";
strncpy(buf, STR, strlen(STR));
puts(buf); // prints "helloand catch fire"
return 0;
}
Recommended practice in C is to check the buffer size in advance and then use strcpy(), alternatively memcpy().
Recommended practice in C++ is to use std::string instead.
From the manpage for strncpy():
Warning: If there is no null byte among the first n bytes of src, the string placed in dest will not be null-terminated.
Either your input is shorter than the supplied length, you add the terminating null byte yourself, or it won't be there. printf() expects the string to be properly null terminated, and thus overruns your allocated buffer.
This only goes to show that the n variants of many standard functions are by no means safe. You must read their respective man pages, and specifically look for what they do when the supplied length does not suffice.

gets and puts to get and print a string

i'm trying to get and print a string with gets and puts but i get a segmentation fault error when i use them togheter.
this is the code i'm trying to get this working. [i type the string "prova" to test it]
int main()
{
char *s;
gets(s);
puts(s);
return 0;
}
if i change "gets" with "scanf" i get the same error.
if i change "puts" with "printf("%s", s)" i get the output.
if i declare char *s = "prova" and then puts(s) i get the output.
i also tried to change char *s; with char s[] but i get the same error.
where i'm i wrong on this? ty very much
i know gets is bad, is just bc i'm writing exercise from "C how to program, fifth edition" by Deitel and Deitel
You have multiple problems with that piece of code. To start with gets have been deprecated since the C99 standard, and in the C11 standard it has been removed. The reason is that it's not very safe, and has no bounds-checking and so can write beyond the bounds of the memory you pass to it leading to buffer overflows.
Secondly, you use the uninitialized local variable s. The value of an uninitialized variable is indeterminate, and will be seemingly random. Using an uninitialized local variable leads to undefined behavior, which often leads to crashes.
Another problem is if you initialize s to point to a literal strings. Literals strings are constant (read-only) arrays of characters, and attempting to write to it will again lead to undefined behavior.
You need to allocate some room for the string:
char s[256];
gets(s);
puts(s);
But gets is bad. (It doesn't know how big your buffer is, so what happens if more than 255 characters are read?)
The most important mistake you have is that you are declaring a char pointer, but you are not reserving the space in memory where the characters will be stored, so you got a pointer that point to some random memory adress that you should'nt use. the "right" thing to do will be:
#include <stdio.h>
#include <stdlib.h>
#define LENGHT 20
int main()
{
char *s;
s=malloc(sizeof(char)*LENGHT); //here you make the pointer point to a memory adress that you can use
gets(s);
puts(s);
free (s);
return 0;
}
But also is strongly recommend to avoid using gets because that function doesn't check for the length of the input, so use fgets instead that allow you to do that, you will only need to set the data stream to stdin.
The code will be:
#include <stdio.h>
#include <stdlib.h>
#define LENGHT 20
int main()
{
char *s;
s=malloc(sizeof(char)*LENGHT);
fgets(s,20,stdin);
puts(s);
free(s);
return 0;
}

A user defined function which is equivalent of strlen() in C

I want a user defined function which is equivalent to strlen() function in C. In the below program it does the same function as strlen() but it has a limit to it. How can I make it count any length of text.
#include <stdio.h>
#include <conio.h>
void main()
{
int len(char *);
char s[20];
int l;
printf("Enter a string: ");
gets(s);
l=len(s);
printf("length of string is =%d",l);
getch();
}
int len(char *t)
{
int count=0;
while(*t!='\0')
{
count++;
t++;
}
return(count);
}
I think your "limit" is because you use gets() on a buffer of 20 bytes. You will experience issues due to a buffer overflow. Exactly what happens when you do that is not entirely predictable.
If you fix that, I think your function will work as you expect it to. (Read the other people's answers for insight on your length function.)
If you truly want "any length", you'll need an arbitrary-precision integer library (such as libgmp) for the counter. That's pretty unreasonable, though, since the string will have to fit into your memory, and each character actually has to have an address. That is to say, the length of any string that fits into addressable space can be expressed in a variable of type size_t (or unsigned long int, I suppose; it'll be something of the same size as the machine's register size).
(Please don't ask about how to form the one-past-the-end pointer of a string that fills out the entire addressable memory.)
Its limit is int bounds. if you increase it, use long. Also, make it unsigned to double the maximum. If you want to be sure that it fit, use size_t (which original strlen use)
BTW, never use gets.
What's the limit you want? Historically a string is terminated by '\0' because its the only way to know where the string ends, otherwise you could actually read the whole stack or heap way past the true length of the string. A method used by other functions to identify the end of a string, to prevent crash not as a feature is to stop reading when a value outside the charset is found.
Edit:
Obviously I misunderstood the question.
int main(){
int Length = 0;
char StrArray[10] = "Hello";
while (StrArray[Length] != '\0')
{
StrArray[Length];
Length++;
}
std::cout << Length;
std::cin.get();
}

Resources