Replace a character in char* for double value - c

I have a char * and I need to replace a character for a double value (unknown number of digits). So I believe that I need to count the number of digits then make a realloc() and replace the characters. I'm just not sure how to count the number of digits and make this replacement.
For example:
char *c = strdup("a+b");
double d = 10;
//I'd like to replace 'a' for 10.
//then 'c' would be : 10+b.
//Next iteration I need to change the 'b' value then I get:
//c = 10 + 3

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
const char* s = "a+b";
double d = 10.23142;
//determine the string length needed for printing d
size_t n = snprintf(NULL, 0, "%g", d);
// old string length + n - 1 for replaced b + 1 for '\0'
char* new_s = malloc( strlen(s) + n - 1 + 1);
//write the double
sprintf(new_s, "%g", d);
//skip the first byte (where b is) at the source and the double's length at the destination
strcpy(new_s + n, s + 1);
printf("%s\n", new_s); //prints 10.2314+b
free(new_s);
return 0;
}
It's easy to make an off-by-one error in this kind of pointer arithmetic, so something like gcc's mudflap or AddressSanitizer are really useful in checking to make sure the program doesn't go into undefined behavior in some place.
Better yet, if you can, use C++ and you won't have to worry about this kind of stuff:
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
string s = "a+b";
double d = 10.23142;
s.replace(0,1,to_string(d));
cout<<s<<endl;
return EXIT_SUCCESS;
}

The problem with realloc is that you may not necessarily get back the same address, so technically you may not so much replace the character as create a new string.
You could measure the size of double by printing it into a static buffer, and taking strlen:
char buf[32];
sprintf(buf, "%f", dbl);
size_t Len = strlen(buf);
Demo
Now you can allocate more space, move the content to the back, and then copy characters from buf into reallocated space.

Related

How to print an int and a string with spaces after using printf?

I usually use printf("%-8d",a); for example for 8 spaces after (and including) an integer.
My code:
#include <stdio.h>
#include <string.h>
int main()
{
int a = 10;
char b = "Hello";
}
How can I print: '#10-Hello '
with 16 spaces (8 is the integer and the string, and 8 spaces after)?
Do it in two steps. First combine the number and string with sprintf(), then print that resulting string in a 16-character field.
int a = 10;
char *b = "Hello";
char temp[20];
sprintf(temp, "#%d-%s", a, b);
printf("%-16s", temp);
A tab is 8 spaces, so, you can add \t\t
The below is a super basic way to print what you wanted.
printf('#' + a + '-' + b + '\t\t');
I'm not as familiar with the syntax of C so it may be :
printf('#', a, '-', b, '\t\t');
Also, as mentioned in a previous answer, "Hello" is not a char but either an array of char or a String.
#include <stdio.h>
#include <string.h>
int main()
{
int a = 10;
char b[] = "Hello";
printf("#%d-%-17s",a,b);
}
this should get the job done, adjust your spacing as needed
Could do this with 2 printf()s. Use the return value of the first to know its print length, then print spaces needed to form a width of 16. No temporary buffer needed.
#include <assert.h>
#include <stdio.h>
int main(void) {
int width = 16;
int a = 10;
char *b = "Hello"; // Use char *
int len = printf("#%d-%s", a, b);
assert(len <= width && len >= 0);
printf("%*s", width - len, ""); // Print spaces
}

Converting string to one with escape sequences

I have a char string containing hexadecimal characters (without 0x or \x):
char *A = "0a0b0c";
from which I want to obtain
const char *B = "\x0a\x0b\x0c";
Is there an efficient way to do this? Thanks!
EDIT: To be clear, I want the resultant string to contain the 3 characters \x0a, \x0b, \x0c, not a 12 character string that says "\x0a\x0b\x0c" where the \ and x are read as individual characters.
This is what I have tried:
const char *B[12];
for (j = 0; j < 4; ++j) {
B[4 * j + 0] = '\\';
B[4 * j + 1] = 'x';
B[4 * j + 2] = A[2 * j];
B[4 * j + 3] = A[2 * j + 1];
};
B[12] = '\0';
which gives me a 12 character string "\x0a\x0b\x0c", but I want B to be as if it was assigned thus:
const char *B = "\x0a\x0b\x0c";
There are multiple confusions in your code:
the input string has 6 characters and a null terminator
the output string should be defined as const char B[3]; or possibly const char B[4]; if you intend to set a null terminator after the 3 converted bytes.
the definition const char *B[12]; in your code defines an array of 12 pointers to strings, which is a very different beast.
The for is fine, but it does not do what you want at all. You want to convert the hexadecimal encoded values to byte values, not insert extra \ and x characters.
the trailing ; after the } is useless
you set a null terminator at B[12], which is beyond the end of B.
Here is a corrected version using sscanf:
const char *A = "0a0b0c";
const char B[4] = { 0 };
for (j = 0; j < 3; j++) {
sscanf(&A[j * 2], "%2hhx", (unsigned char *)&B[j]);
}
The conversion format %2hhx means convert at most the first 2 bytes at A[j * 2] as an unsigned integer encoded in hexadecimal and store the resulting value into the unsigned char at B[j]. The cast is only necessary to avoid a compiler warning.
You can write a function that would sprintf the desired into a string, and then concat that with the destination string.
Something along these lines...
#include <stdio.h>
#include <string.h>
void createB (char B[10], const char *start)
{
char temp[10];
sprintf(temp, "\\x%c%c", start[0], start[1]);
strcat(B, temp);
}
int main ()
{
char A[] = "0a0b0c";
char B[10] = {'\0'};
for (int i=0; A[i] != '\0'; i = i+2)
{
createB(B, A+i);
}
printf("%s\n", B);
return 0;
}
$ ./main.out
\x0a\x0b\x0c
You can modify that to suit your needs or make it more efficient as you feel.
Please make edits as you please; to make it safer with necessary checks. I have just provided a working logic.
If you simply want to add "\x" before each '0' in the string-literal A with the result in a new string B, a simple and direct loop is all that is required, and storage in B sufficient to handle the addition for "\x" for each '0' in A.
For example:
#include <stdio.h>
#define MAXC 32
int main (void) {
char *A = "0a0b0c",
*pa = A,
B[MAXC],
*pb = B;
do { /* loop over all chars in A */
if (*pa && *pa == '0') { /* if chars remain && char is '0' */
*pb++ = '\\'; /* write '\' to B, adv ptr */
*pb++ = 'x'; /* write 'x' to B, adv ptr */
}
*pb++ = *pa; /* write char from A, adv ptr */
} while (*pa++); /* while chars remain (writes nul-termining char) */
puts (B); /* output result */
}
You cannot simply change A to an array with char A[] = 0a0b0c"; and then write back to A as there would be insufficient space in A to handle the character addition. You can always declare A large enough and then shift the characters to the right by two for each addition of "\x", but it makes more sense just to write the results to a new string.
Example Use/Output
$ ./bin/straddescx
\x0a\x0b\x0c
If you need something different, let me know and I'm happy to help further. This is probably one of the more direct ways to handle the addition of the character sequence you want.
#include <stdio.h>
int main(void)
{
char str1[] = "0a0b0c";
char str2[1000];
int i, j;
i = j = 0;
printf("sizeof str1 is %d.\n", sizeof(str1)-1);
for(i = 0; i < sizeof(str1)-1; i += 2)
{
str2[j] = '\\';
str2[j+1] = 'x';
str2[j+2] = str1[i];
str2[j+3] = str1[i+1];
j+=4;
}
str2[j] = '\0';
printf("%s\n", str2);
return 0;
}
I think you can do like this.
Assuming no bad input, assuming 'a' to 'f' are sequentially in order, assuming no uppercase:
// remember to #include <ctype.h>
char *input = "0a0b0c";
char *p = input;
while (*p) {
v = (isdigit((unsigned char)*p) ? *p-'0' : *p-'a'+10) * 16;
p++;
v += isdigit((unsigned char)*p) ? *p-'0' : *p-'a'+10;
p++;
printf("0x%d", v); // use v
}
While using char A[] = "0a0b0c";, as proposed by kiran, would make it possible to change the string, it wil not yet allow to insert characters. Because that would make the string longer and hence not fit into the available memory. This in turn is a problem, if you cannot create the target string right away with the needed size.
You could know the needed size in advance, if the input is always of the same length and always requires the same number of inserted characters, e.g. if like in your example, the target string is double the size of the input string. For a simple character array definition, you would need to know the size already at compile time.
char A[7] = "0a0b0c"; /* not 6, because size for the termianting \0 is needed */
char B[13] = ""; /* 2*6+1 */
So you can stay with char *A = "0a0b0c"; and make your life easier by setting up memory of appropriate size to serve as target. For that you need to first determine the length of the needed memory, then allocate it.
Determining the size if easy, if you know that it will be twice the input size.
/* inside a function, this does not work as a variable definition */
int iLengthB = 2*length(A);
char* B = malloc(iLengthB+1); /* mind the terminator */
Then loop over A, copying each two characters to B, prepending them with the two characters "\x". I assume that this part is obvious to you. Otherwise please show how you setup the program as described above and make a loop outputting each character from A separatly. Then, after you demonstrated that effort, I can help more.

String traversal using pointers

I am trying to print every fourth character of a string using pointers.
I was able to achieve it using the following code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[]){
char* string = "WhatTheeHell";
char* p = string;
while(*p != '\0'){
printf("%c\n", *p);
p += 4;
}
return 0;
}
This correctly gives the output to me as:
W
T
H
Now, I tried another way to do it, which according to my knowledge of pointer arithmetic, should have worked, since the size of int on my machine is 4 bytes.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[]){
char* string = "WhatTheeHell";
int* p = (int*)string;
while(*p != '\0'){
printf("%c\n", *p);
p += 1;
}
return 0;
}
When I print the output for this, it gives me WTH followed by four newlines.
My question, why are the four newlines being printed? Shouldn't it be that after the H is printed, the *p gives a NULL character present at the end of the string literal and the loop gets terminated?
For starters the first program is invalid. If a string has the number of characters that is not divisible by 4 you will have undefined behavior because the pointer can point to beyond the string using the pointer arithmetic
p += 4;
A valid approach can look the following way as it is shown in the demonstrative program
#include <stdio.h>
int main( void )
{
const char *s = "WhatTheeHell";
const size_t STEP = 4;
if ( *s )
{
const char *p = s;
do
{
printf( "%c\n", *p );
for ( size_t i = 0; i < STEP && *p; ++i, ++p );
} while ( *p );
}
}
Its output is
W
T
H
The second your program is also invalid. For starters it is not necessary thet a string literal is aligned by sizeof( int ) (moreover in general the sizeof( int ) can be greater or less than 4). So the program already has undefined behavior.
In this condition
*p != '\0'
there are compared sizeof( int ) bytes (not a single byte ) with the integer constant '\0'. So the comparison will be always true when the pointer points inside the string (and even beyond the string if there are no zero bytes).
By the way also pay attention to that in C sizeof( '\0' ) is equal to sizeof( int ).
When you compare *p to \0, *p is not a single char but a (presumably) four-byte value (the char is promoted to integer before comparison).
Nothing guaranties that after the \0 of your string there are other zero bytes: this is undefined behaviour.
Thus your loop continues until it reaches by chance a zero integer.
When printing with "%c\n", only the lower byte of the integer is considered; if its value is zero (nothing is guaranteed) it does not print anything visible, just the following \n

XOR two strings from argv in C

Want to XOR two strings fetched from argv.
I checked this question How to xor two string in C? but it could not solve it for me.
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[]) {
char output[]="";
int i;
for (i=0; i<strlen(argv[1]); i++){
char temp = argv[1][i]^argv[2][i];
output[i]= temp;
}
output[i] = '\0';
printf("XOR: %s\n",output);
return 0;
}
When I use lldb to debug my output ("(lldb) print output") it is /a/x16/t/x13 but it can not be printed by printf(). I know that it is not a string anymore. Can you help me how to make it able to be printf:ed.
The text that is printed in the terminal is "XOR: "
There's some memory bugs in your code. Perhaps the following would work better:
#include <stdio.h>
#include <string.h>
#define min(i, j) ((i) < (j) ? (i) : (j))
int main(int argc, char const *argv[])
{
char *output;
int i;
/* Allocate a buffer large enough to hold the smallest of the two strings
* passed in, plus one byte for the trailing NUL required at the end of
* all strings.
*/
output = malloc(min(strlen(argv[1]), strlen(argv[2])) + 1);
/* Iterate through the strings, XORing bytes from each string together
* until the smallest string has been consumed. We can't go beyond the
* length of the smallest string without potentially causing a memory
* access error.
*/
for(i = 0; i < min(strlen(argv[1]), strlen(argv[2])) ; i++)
output[i] = argv[1][i] ^ argv[2][i];
/* Add a NUL character on the end of the generated string. This could
* equally well be written as
*
* output[min(strlen(argv[1]), strlen(argv[2]))] = 0;
*
* to demonstrate the intent of the code.
*/
output[i] = '\0';
/* Print the XORed string. Note that if characters in argv[1]
* and argv[2] with matching indexes are the same the resultant byte
* in the XORed result will be zero, which will terminate the string.
*/
printf("XOR: %s\n", output);
return 0;
}
As far as printf goes, keep in mind that x ^ x = 0 and that \0 is the string terminator in C.
Best of luck.

C convert section of char array to double

I want to convert a section of a char array to a double. For example I have:
char in_string[] = "4014.84954";
Say I want to convert the first 40 to a double with value 40.0. My code so far:
#include <stdio.h>
#include <stdlib.h>
int main(int arg) {
char in_string[] = "4014.84954";
int i = 0;
for(i = 0; i <= sizeof(in_string); i++) {
printf("%c\n", in_string[i]);
printf("%f\n", atof(&in_string[i]));
}
}
In each loop atof it converts the char array from the starting pointer I supply all the way to the end of the array. The output is:
4
4014.849540
0
14.849540
1
14.849540
4
4.849540
.
0.849540
8
84954.000000 etc...
How can I convert just a portion of a char array to a double? This must by modular because my real input_string is much more complicated, but I will ensure that the char is a number 0-9.
The following should work assuming:
I will ensure that the char is a number 0-9.
double toDouble(const char* s, int start, int stop) {
unsigned long long int m = 1;
double ret = 0;
for (int i = stop; i >= start; i--) {
ret += (s[i] - '0') * m;
m *= 10;
}
return ret;
}
For example for the string 23487 the function will do this calculations:
ret = 0
ret += 7 * 1
ret += 8 * 10
ret += 4 * 100
ret += 3 * 1000
ret += 2 * 10000
ret = 23487
You can copy the desired amount of the string you want to another char array, null terminate it, and then convert it to a double. EG, if you want 2 digits, copy the 2 digits you want into a char array of length 3, ensuring the 3rd character is the null terminator.
Or if you don't want to make another char array, you can back up the (n+1)th char of the char array, replace it with a null terminator (ie 0x00), call atof, and then replace the null terminator with the backed up value. This will make atof stop parsing where you placed your null terminator.
Just use sscanf. Use the format "ld" and check for return value is one.
What about that, insert NULL at the right position and then revert it back to the original letter? This means you will manipulate the char array but you will revert it back to the original at the end.
You can create a function that will make the work in a temporary string (on the stack) and return the resulting double:
double atofn (char *src, int n) {
char tmp[50]; // big enough to fit any double
strncpy (tmp, src, n);
tmp[n] = 0;
return atof(tmp);
}
How much simpler could it get than sscanf?
#include <assert.h>
#include <stdio.h>
int main(void) {
double foo;
assert(sscanf("4014.84954", "%02lf", &foo) == 1);
printf("Processed the first two bytes of input and got: %lf\n", foo);
assert(sscanf("4014.84954" + 2, "%05lf", &foo) == 1);
printf("Processed the next five bytes of input and got: %lf\n", foo);
assert(sscanf("4014.84954" + 7, "%lf", &foo) == 1);
printf("Processed the rest of the input and got: %lf\n", foo);
return 0;
}

Resources