Format a string using sprintf in c - c

I am using sprintf for string formation in C.
I need to insert '+' and '-' sign before float value.
This positive and negative signs are inserted by checking a flag after that i insert the float value.
Now i want to make this whole number in right alignment along with positive or negative sign.
Currently this is my formatted string:
+300.00
-200.00
+34.60
I want output like following,
+300.00
+233.45
-20.34
I have written following code:
char printbuff[1000], flag = 1;
double temp=23.34, temp1= 340.45;
sprintf(printBuff, "%c%-lf\n%c%-lf",
(Flag == 1) ? '+' : '-',
temp,
(Flag == 1) ? '+' :'-',
temp1);
I am getting following output:
+23.34
+340.45
Instead of the desired:
+23.45
+340.45
How can I do this?

use like this
sprintf(outputstr, "%+7.2f", double_number);
E.g.
#include <stdio.h>
#include <string.h>
#include <math.h>
void output_string(char output_buffer[], double nums[], size_t size){
/* use '+' flag version
int i,len=0;
for(i=0;i<size;++i)
len += sprintf(output_buffer + len, "%+7.2f\n", nums[i]);
*/ //handmade version
int i, len=0;
for(i=0;i<size;++i){
char sign = nums[i] < 0 ? '-' : '+';
char *signp;
double temp = abs(nums[i]);
len += sprintf(signp = output_buffer + len, "%7.2f\n", temp);
signp[strcspn(signp, "0123456789")-1] = sign;//The width including the sign is secured
}
}
int main(){
double nums[] = {
+300.00,
-200.00,
+34.60,
+300.00,
+233.45,
-20.34
};
char output_buffer[1024];
int size = sizeof(nums)/sizeof(*nums);
output_string(output_buffer, nums, size);
printf("%s", output_buffer);
return 0;
}

int main()
{
char s[100];
double x=-100.00;
sprintf(s,"%s%f",x<0?"":"+",x);
printf("\n%s",s);
x = 1000.01;
sprintf(s,"%s%f",x<0?"":"+",x);
printf("\n%s",s);
return 0;
}
Here is the code.
Its O/p is ::
-100.000000
+1000.010000

you need a separate buffer, in which you sprintf your number with your sign, and that resulting string you can sprintf into the rightjustified resultbuffer.

You need something like:
char str[1000];
double v = 3.1415926;
sprintf(str, "%+6.2f", v);
The + indicates "show sign".
A more complete bit of code:
#include <stdio.h>
int main()
{
double a[] = { 0, 3.1415, 333.7, -312.2, 87.8712121, -1000.0 };
int i;
for(i = 0; i < sizeof(a)/sizeof(a[0]); i++)
{
printf("%+8.2f\n", a[i]);
}
return 0;
}
Output:
+0.00
+3.14
+333.70
-312.20
+87.87
-1000.00
Obviously, using sprintf, there would be a buffer involved, but I believe this shows the solution more easily.

Related

Converting a char array with decimal numbers to different float

Hello I´m fairly new to C programming and i want to convert a char array looking like
char numberlist[]="9,8 2,3 5,4 2,7 1,3";
to a float that would be 9.8 ,i used
float a;
a=atof(numberlist);
printf("%.1f\n",a);
but that gave me 9.0 in return because it is 9,8 instead of 9.8 in the char array. How could i easily fix that, without touching the char array?
Thanks in advance :)
For example
char numberlist[]="9,8 2,3 5,4 2,7 1,3";
float convertFirstNumber(const char *str, char delim)
{
char z[256];
size_t index = 0;
while(*str && *str != delim)
{
if(*str == ',') z[index++] = '.';
else z[index++] = *str;
str++;
}
z[index] = 0;
return atof(z);
}
int main()
{
printf("%.1f\n",convertFirstNuber(numberlist, ' '));
}
This can be done with int sscanf(const char *restrict s, const char *restrict format, ...); and atof i have chossed sscanf to show u different approach. you can replace it with atof if you wish.
int main(){
float f, resd;
int i = 0;
char numberlist[]="9,8 2,3 5,4 2,7 1,3";
sscanf(numberlist,"%f",&f);
while(numberlist[i] != ','){
++i;
}
sscanf(&numberlist[i],",%f",&resd);
printf("%f\n", resd);
printf("%f",f+resd/10.0);
return 0;
}
If your string uses a comma as decimal point, you could set the locale to a useful value before parsing:
/* Set number locale to german */
setlocale(LC_NUMERIC, "de_DE.utf8");
double a; /* Never use floats */
sscanf("3,14", "%lf", &a);
/* It is better to not hardcode "C" but use the locale saved before the
previous `setlocale` */
setlocale(LC_NUMERIC, "C");
/* Should print "3.14" */
printf("%lf\n", a);
Just remember that setlocale has issues with multithreaded software. And you should reconsider if you really want to store your data with comma as the decimal point.
Adam gave a good answer.
You can also iterate the string and create the number manually.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
char numberlist[] = "9,8 2,3 5,4 2,7 1,3";
int main() {
int len = strlen(numberlist);
int total = 0;
int count = 0;
for(int i = len; i >= 0; i--){
char c = numberlist[i];
if(isdigit(c)){
int number = atoi(&c);
total += round(pow(10, count)) * number;
count++;
}
}
float value = total / round(pow(10, count-1));
printf("%.2f\n", value);
}

Calculating hamming distance by appending '0' to lesser length string

I have to find the hamming distance between two codes.
For example if I input:
a= 10
b= 1010
Automatically a should be made equal to the length of the string b by appending 0's.
So the input should become:
a=0010
b=1010
But I'm getting instead:
a = 001010
b = 1010
Here is my code:
#include<stdio.h>
#include<string.h>
void main()
{
char a[20],b[20],len1,len2,i,diff,count=0,j;
printf("Enter the first binary string\n");
scanf("%s",a);
printf("Enter the second binary string\n");
scanf("%s",b);
len1 = strlen(a);
len2 = strlen(b);
if(len1>len2)
{
diff = len1-len2;
for(i=0;i<len1;i++)
{
b[i+diff]=b[i];
}
j=i+diff;
b[j]='\0';
for(i=0;i<diff;i++)
{
b[i]='0';
}
}
else
{
diff = len2-len1;
for(i=0;i<len2;i++)
{
a[i+diff]=a[i];
}
j=i+diff;
a[j]='\0';
for(i=0;i<diff;i++)
{
a[i]='0';
}
}
printf("\nCodes are\n");
printf("a=%s\n",a);
printf("\nb=%s\n",b);
for(i=0;a[i]!='\0';i++)
{
if(a[i]!=b[i])
{
count++;
}
}
printf("hammung distance between two code word is %d\n",count);
}
Can anyone help me to fix this issue?
In your two for loop where you are moving the content of your old tab to the right to insert the zeros, you inverted the lengths.
First loop should be:
for(i=0;i<len2;i++)
{
b[i+diff]=b[i];
}
And second:
for(i=0;i<len1;i++)
{
a[i+diff]=a[i];
}
After trying it:
Codes are
a=0010
b=1010
hammung distance between two code word is 1
Also, the main function should return an int, not void. As stated in the comments, you should also change the type of your len1, len2, i, diff, count and j because you use them as number values, not as characters. You can for instance either use the int or size_t types for that.
int main()
{
char a[20],b[20];
int len1, len2, i, diff, count=0, j;
// Rest of your code
}
Here is a method that does not prepend zeros to the shortest binary string, and avoids the limitations of strtol() by comparing the elements of the string directly, starting with the last characters. The intricacies of using strtol() are traded for more complexity in handling the array indices. Note that care must be taken to avoid counting down to a negative value since size_t types are used. This method is not limited by the capacity of long types, but rather by size_t.
#include <stdio.h>
#include <string.h>
int main(void)
{
char a[20], b[20];
printf("Enter first binary string: ");
scanf("%19s", a);
printf("Enter second binary string: ");
scanf("%19s", b);
size_t a_len = strlen(a);
size_t b_len = strlen(b);
size_t max_len = a_len > b_len ? a_len : b_len;
size_t hamming_dist = 0;
for (size_t i = 0; i < max_len; i++) {
if (a_len - i > 0 && b_len - i > 0) {
if (a[a_len - i - 1] == b[b_len - i - 1]) {
continue;
}
}
if ((a_len - i > 0 && a[a_len - i - 1] == '1') ||
(b_len - i > 0 && b[b_len - i - 1] == '1')) {
++hamming_dist;
}
}
printf("bstring_1: %s\n", a);
printf("bstring_2: %s\n", b);
printf("Hamming distance: %zu\n", hamming_dist);
return 0;
}
A way that doesn't need to pad one of the parameters with zeroes:
#include <stdio.h>
#include <stdlib.h>
int main ()
{
char *a = "1010";
char *b = "10";
long unsigned int xorab;
unsigned int hammingDistance = 0;
xorab = strtoul(a, NULL, 2) ^ strtoul(b, NULL, 2);
while (xorab) {
hammingDistance += xorab & 1;
xorab >>= 1;
}
printf("%u\n", hammingDistance);
}
It uses strtoul to convert the binary strings to unsigned long int using a base 2, then you only have to use bitwise operators (xor, and, shift) to calculate the Hamming distance without to take care of the size difference.
Obviously, this way stops to work if you want to test binary strings with values greater than an unsigned long int.

Reverse a character array without changing value of number?

I have for example a string (mathematical equation in postfix notation) that looks like this: The numbers are 5.33,5.32,6.33,3.22
5.335.32*6.333.22++
I'm looking to make it into prefix notation but simply reversing the string won't work due to the fact it has to retain the value of the number.
I've thought of doing a normal character by character swap in a for loop, and when encountering a digit make that into a substring and place it on afterwards but I haven't gotten it to work properly and now I'm stuck.
My end-goal is to make a binary expression tree out of that, so if there's an easier way than doing this also please let me know.
A stack-based approach:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *postfix_to_prefix(const char *string) {
char operator, *stack[1024];
int s = 0, number, fraction;
const char *tokens = string;
while (1) {
if (sscanf(tokens, "%1d.%2d", &number, &fraction) == 2) {
stack[s] = malloc(sizeof("1.00"));
(void) sprintf(stack[s++], "%4.2f", number + (fraction / 100.0));
tokens += strlen("1.00");
} else if (sscanf(tokens, "%c", &operator) == 1) {
char *operand1 = stack[--s];
char *operand2 = stack[--s];
stack[s] = malloc(strlen(operand1) + strlen(operand1) + sizeof(operator) + sizeof('\0'));
(void) sprintf(stack[s++], "%c%s%s", operator, operand1, operand2);
free(operand1);
free(operand2);
tokens += sizeof(operator);
} else {
break;
}
}
return stack[--s];
}
int main() {
const char *string = "5.335.32*6.333.22++";
printf("%s\n", string);
char *inverted = postfix_to_prefix(string);
printf("%s\n", inverted);
free(inverted);
return 0;
}
OUTPUT
> ./a.out
5.335.32*6.333.22++
++3.226.33*5.325.33
>
This is a bare bones implementation with no real error checking nor other finishing touches. You'll want to check that non-communitive operations like subtraction and division come out with the operands in the correct order and reverse them if not.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void) {
char exp[] = "5.335.32*6.333.22++";
size_t len = strlen(exp);
char temp[len];
char *p = temp;
for(int i = len-1; i >= 0; ){
if(isdigit(exp[i])){
memcpy(p, &exp[i-4+1], 4);//all number have a length of 4
p += 4;
i -= 4;
} else {
*p++ = exp[i--];//length of op is 1
}
}
memcpy(exp, temp, len);//Write back
puts(exp);//++3.226.33*5.325.33
return 0;
}

print double in scientific format with no integer part

A simple problem but I can't get documentation about this kind of format: I want to print a float in a Fortran scientific notation, with its integer part always being zero.
printf("%0.5E",data); // Gives 2.74600E+02
I want to print it like this:
.27460E+03
How can I get this result as clean as possible?
If you only care about the integer part being 0 and not really leaving out the 0, i.e. if you're fine with 0.27460E+03 instead of .27460E+03 you could do something similar to this:
#include <stdio.h>
#include <stdlib.h>
void fortran_printf();
int main(void)
{
double num = 274.600;
fortran_printf(num);
exit(EXIT_SUCCESS);
}
void fortran_printf(double num)
{
int num_e = 0;
while (num > 1.0) {
num /= 10;
num_e++;
}
printf("%.5fE+%02d", num, num_e);
}
Otherwise you have to take a detour over strings. Note that the code above is only meant to get you started. It certainly doesn't handle any involved cases.
I tried doing this with log10() and pow(), but ended up having problems with rounding errors. So as commented by #Karoly Horvath, string manipulation is probably the best approach.
#include <stdlib.h>
char *fortran_sprintf_double(double x, int ndigits) {
char format[30], *p;
static char output[30];
/* Create format string (constrain number of digits to range 1–15) */
if (ndigits > 15) ndigits = 15;
if (ndigits < 1) ndigits = 1;
sprintf(format, "%%#.%dE", ndigits-1);
/* Convert number to exponential format (multiply by 10) */
sprintf(output, format, x * 10.0);
/* Move the decimal point one place to the left (divide by 10) */
for (p=output+1; *p; p++) {
if (*p=='.') {
*p = p[-1];
p[-1] = '.';
break;
}
}
return output;
}
A string manipulation approach:
int printf_NoIntegerPart(double x, int prec) {
char buf[20 + prec];
sprintf(buf, "%+.*E", prec - 1, x * 10.0); // use + for consistent width output
if (buf[2] == '.') {
buf[2] = buf[1];
buf[1] = '.';
}
puts(buf);
}
int main(void) {
printf_NoIntegerPart(2.74600E+02, 5); // --> +.27460E+03
}
This will print "INF" for |x| > DBL_MAX/10
printf() will not meet OP’s goal in one step using some special format. Using sprintf() to form the initial textual result is a good first step, care must be exercised when trying to do “math” with string manipulation.
Akin to #user3121023 deleted answer.
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
int printf_NoIntegerPart(double x, int prec) {
assert(prec >= 2 && prec <= 100);
char buffer[prec + 16]; // Form a large enough buffer.
sprintf(buffer, "%.*E", prec - 1, x);
int dp = '.'; // Could expand code here to get current local's decimal point.
char *dp_ptr = strchr(buffer, dp);
char *E_ptr = strchr(buffer, 'E');
// Insure we are not dealing with infinity, Nan, just the expected format.
if (dp_ptr && dp_ptr > buffer && E_ptr) {
// Swap dp and leading digit
dp_ptr[0] = dp_ptr[-1];
dp_ptr[-1] = dp;
// If x was not zero …
if (x != 0) {
int expo = atoi(&E_ptr[1]); // Could use `strtol()`
sprintf(&E_ptr[1], "%+.02d", expo + 1);
}
}
return puts(buffer);
}
int main(void) {
printf_NoIntegerPart(2.74600E+02, 5); // ".27460E+03"
return 0;
}
Faced same issue while fortran porting.
DId not found std C format :(
Implemented both approaches - with log10/pow and with string manipulation.
#include <ansi_c.h>
#define BUFFL 16
// using log10 , 3 digits after "."
char* fformat1(char* b, double a) {
int sign = 1;
double mant;
double order;
int ord_p1;
if (a<0) {
sign =-1;
a = -a;
}
order=log10 (a);
if (order >=0) ord_p1 = (int) order +1; // due sto property of int
else ord_p1 = (int) order;
mant=a/(pow(10,ord_p1));
sprintf(b,"%.3fE%+03d",mant,ord_p1);
if (sign==-1) b[0]='-';
return b;
}
// using string manipulation
char* fformat2(char* b, double a) {;
int sign = 1;
int i;
int N=3;
if (a<0) {
sign =-1;
a = -a;
}
sprintf(b,"%0.3E",a*10); // remember - we *10 to have right exponent
b[1]=b[0]; // 3.123 => .3123
b[0]='.';
for (i=N; i>=0; i--) // and shif all left
b[i+1]=b[i];
b[0]='0'; // pad with zero 0.312
if (sign==-1) b[0]='-'; // sign if needed
return b;
}
int main () {
char b1[BUFFL]; // allocate buffer outside.
char b2[BUFFL];
char b3[BUFFL];
char b4[BUFFL];
char b5[BUFFL];
printf("%s %s %s %s %s \n", fformat(b1,3.1), fformat(b2,-3.0), fformat(b3,3300.),
fformat(b4,0.03), fformat(b5,-0.000221));
printf("%s %s %s %s %s \n", fformat2(b1,3.1), fformat2(b2,-3.0), fformat2(b3,3300.),
fformat2(b4,0.03), fformat2(b5,-0.000221));
return 1;
}

convert int to string with decimals

I want to write my own function in C for various reasons that converts an int to a string of decimals, just like sprintf.
Example:
int number = 254;
char string[10];
sprintf(string, "%d", number);
The string should look like this after the function I want to write:
[0] 2
[1] 5
[2] 4
[3] '\0'
Just to clarify even further, I want to program the actual convertion of an int to a string of chars. I don't want to use sprintf or itoa etc to do it. I want to know how it is done and be able to program it myself and do small adjustments to it.
Additional clarification:
I don't want to use itoa or sprintf, but pretty much program these myself.
#include <stdio.h>
#include <stdlib.h>
int i2a(char *s, int n){
div_t qr;
int pos;
if(n == 0) return 0;
qr = div(n, 10);
pos = i2a(s, qr.quot);
s[pos] = qr.rem + '0';
return pos + 1;
}
char* my_itoa(char *output_buff, int num){
char *p = output_buff;
if(num < 0){
*p++ = '-';
num *= -1;
} else if(num == 0)
*p++ = '0';
p[i2a(p, num)]='\0';
return output_buff;
}
int main(void){
int number = -254;
char string[12];
printf("%s", my_itoa(string, number));
return 0;
}
int number = 254;
int back=0,i=0;
char ch='\0';
char string[10];
for(i=0;(number/10)==0;i++){
back=number%10;
ch=(back*pow(10,i)+48);
string[i]=ch;
}
divide number per 10
get the rest( with % ) the rest is the digit you want starting from the right
cast the digit to char +48(ascii 0)
add to string

Resources