Right justifying with printf() with additional character - c

In a table I am making, I have to print an integer representing cost right justified so that it takes up six characters in total which is okay, but I also need to insert a '$' character before the number. Is there a way to do this without making a new string that is just the integer with the $ in front of it?

This will print [ $26]. Brackets are there just to show the leading space.
snprintf() will return the number of characters needed to print the formatted string.
%*c will print a character after first getting an argument for the width.
#include<stdio.h>
#include<stdlib.h>
int main ( ) {
int cost = 26;
printf ( "[%*c%d]\n", 6 - snprintf ( NULL, 0, "%d", cost), '$', cost);
return 0;
}

I'm assuming you're doing the normal printf call:
printf("%d", cost);
just add it in front?
printf("$%d", cost);
more help here: https://www.gnu.org/software/gawk/manual/html_node/Printf-Examples.html

Related

Weird result from random character generator in C

I am trying to write a program in C that spits out random characters. Following instructions I found here, I wrote this program.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void) {
srandom((unsigned) time(NULL));
printf("Tests various aspects of random\n");
char misc;
int num, index;
printf("Enter number of chars: ");
scanf("%d", &num);
printf("\n");
for (int i = 0; i < num; i++) {
index = random() % 26;
misc = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[index];
printf("%d:%s\n", index, &misc);
}
}
However, it doesn't behave as I expect. When entering a small number of characters for it to generate, like 10, it makes the expected output.
My expected output is a set of
rand_int:char
pairs printed to the screen.
Here is an example of normal operation
Tests various aspects of random
Enter number of chars:
7:H
4:E
23:X
2:C
4:E
17:R
22:W
11:L
9:J
4:E
However, if I input a large value such as 100, it outputs very strange things like:
Tests various aspects of random
Enter number of chars:
18:Sd
3:Dd
21:Vd
10:Kd
19:Td
19:Td
14:Od
7:Hd
15:Pd
22:Wd
24:Yd
22:Wd
12:Md
[rest omitted for brevity...]
So the question is, why does it behave this way?
What might be a better approach to avoid this?
The comments made by Jabberwocky and Federico klez Culloca got it right.
I was trying to print the character as a string. This was wrong and did weird things.
I needed to use:
printf("%d:%c\n", index, misc);
instead of
printf("%d:%s\n", index, &misc);
All is very simple. The program has undefined behavior. You are using the format string %s that is used to output strings.
printf("%d:%s\n", index, &misc);
However the variable misc is not a character array that contains a string. It is just a single character. So the function printf outputs all characters beyond the variable misc until a zero-terminating character is encountered.
And it seems that the variable num is allocated next to the variable misc. So the printf call outputs also bytes of the variable num that contains the value 100. If to output this value stored in a byte as an ASCII character then you will get the character 'd'.
Here is a demonstrative program.
#include <stdio.h>
int main(void)
{
char c = 100;
putchar( c );
putchar( '\n' );
return 0;
}
Its output is
d
Instead of the format %s use the format %c in the printf call. For example
printf("%d:%c\n", index, misc);

How to split string (character) and variable in 1 line on C?

How can I split character and variable in 1 line?
Example
INPUT
car1900food2900ram800
OUTPUT
car 1900
food 2900
ram 800
Code
char namax[25];
int hargax;
scanf ("%s%s",&namax,&hargax);
printf ("%s %s",namax,hargax);
If I use code like that, I need double enter or space for make output. How can I split without that?
You should be able to use code like this to read one name and number:
if (scanf("%24[a-zA-Z]%d", namax, &hargax) == 2)
…got name and number OK…
else
…some sort of problem to be reported and handled…
You would need to wrap that in a loop of some sort in order to get three pairs of values. Note that using &namax as an argument to scanf() is technically wrong. The %s, %c and %[…] (scan set) notations all expect a char * argument, but you are passing a char (*)[25] which is quite different. A fortuitous coincidence means you usually get away with the abuse, but it is still not correct and omitting the & is easy (and correct).
You can find details about scan sets etc in the POSIX specification of scanf().
You should consider reading a whole line of input with fgets() or POSIX
getline(), and then processing the resulting string with sscanf(). This makes error reporting and error recovery easier. See also How to use sscanf() in loops.
Since you are asking this question which is actually easy, I presume you are somewhat a beginner in C programming. So instead of trying to split the input itself during the input which seems to be a bit too complicated for someone who's new to C programming, I would suggest something simpler(not efficient when you take memory into account).
Just accept the entire input as a String. Then check the string internally to check for digits and alphabets. I have used ASCII values of them to check. If you find an alphabet followed by a digit, print out the part of string from the last such occurrence till the current point. And while printing this do the same with just a slight tweak with the extracted sub-part, i.e, instead of checking for number followed by letter, check for letter followed by digit, and at that point print as many number of spaces as needed.
just so that you know:
ASCII value of digits (0-9) => 48 to 57
ASCII value of uppercase alphabet (A-Z) => 65 to 90
ASCII value of lowercase alphabets (a-z)
=> 97 to 122
Here is the code:
#include<stdio.h>
#include<string.h>
int main() {
char s[100];
int i, len, j, k = 0, x;
printf("\nenter the string:");
scanf("%s",s);
len = strlen(s);
for(i = 0; i < len; i++){
if(((int)s[i]>=48)&&((int)s[i]<=57)) {
if((((int)s[i+1]>=65)&&((int)s[i+1]<=90))||(((int)s[i+1]>=97)&&((int)s[i+1]<=122))||(i==len-1)) {
for(j = k; j < i+1; j++) {
if(((int)s[j]>=48)&&((int)s[j]<=57)) {
if((((int)s[j-1]>=65)&&((int)s[j-1]<=90))||(((int)s[j-1]>=97)&&((int)s[j-1]<=122))) {
printf("\t");
}
}
printf("%c",s[j]);
}
printf("\n");
k = i + 1;
}
}
}
return(0);
}
the output:
enter the string: car1900food2900ram800
car 1900
food 2900
ram 800
In addition to using a character class to include the characters to read as a string, you can also use the character class to exclude digits which would allow you to scan forward in the string until the next digit is found, taking all characters as your name and then reading the digits as an integer. You can then determine the number of characters consumed so far using the "%n" format specifier and use the resulting number of characters to offset your next read within the line, e.g.
char namax[MAXNM],
*p = buf;
int hargax,
off = 0;
while (sscanf (p, "%24[^0-9]%d%n", namax, &hargax, &off) == 2) {
printf ("%-24s %d\n", namax, hargax);
p += off;
}
Note how the sscanf format string will read up to 24 character that are not digits as namax and then the integer that follows as hargax storing the number of characters consumed in off which is then applied to the pointer p to advance within the buffer in preparation for your next parse with sscanf.
Putting it altogether in a short example, you could do:
#include <stdio.h>
#define MAXNM 25
#define MAXC 1024
int main (void) {
char buf[MAXC] = "";
while (fgets (buf, MAXC, stdin)) {
char namax[MAXNM],
*p = buf;
int hargax,
off = 0;
while (sscanf (p, "%24[^0-9]%d%n", namax, &hargax, &off) == 2) {
printf ("%-24s %d\n", namax, hargax);
p += off;
}
}
}
Example Use/Output
$ echo "car1900food2900ram800" | ./bin/fgetssscanf
car 1900
food 2900
ram 800

Confusion regarding a printf statement

So I was running this code
#include<stdio.h>
int add(int x, int y)
{
return printf("%*c%*c",x ,' ',y,' ');
}
int main()
{
printf("Sum = %d", add(3,4));
return 0;
}
And can't seem to understand how does the following statement works
return printf("%*c%*c",x ,' ',y,' ');
So I tried writing a simple code
int x=3;
printf("%*c",x);
and I got a weird special character (some spaces before it) as output
printf("%*c",x,' ');
I am getting no output. I have no idea what is happening? Please Help. Thank you.
This code
int x=3;
printf("%*c",x,'a');
makes use of the minimum character width that can be set for each input parameter to printf.
What the above does is print out the a character, but specifies that the minimum width will be x characters - so the output will be the a character preceded by 2 spaces.
The * specifier tells printf that the width of the part of the output string formed from this input parameter will be x characters minimum width where x must be passed as additional argument prior to the variable that is to be printed. The extra width (if required) is formed from blank spaces output before the variable to be printed. In this case the width is 3 and so the output string is (excluding the quotes which are just there to illustrate the spaces)
" a"
With your code here
printf("%*c",x);
you have passed the length value, but forgotten to actually pass the variable that you want printed.
So this code
return printf("%*c%*c",x ,' ',y,' ');
is basically saying to print the space character but with a minimum width of x characters (with your code x = 3), then print the space character with a minimum of y characters (in your code y = 4).
The result is that you are printing out 7 blank space characters. This length is the return value of printf (and hence your add function) which is confirmed by the output of
Sum = 7
from the printf inside main().
If you change your code to
return printf("%*c%*c",x ,'a',y,'b');
you would see the string (obviously excluding the quotes)
" a b"
printed which would make what is happening more clear.
Try to print that in the correct way. %d is for printing integer, %c is for printing char.
In your code:
int x=3;
printf("%*c",x);
The x is how much spaces the char will get, you write 3. But you didn't put the char you want to print, so it print garbage.
When you write:
printf("%*c",x,' ');
You printing space ' ' char inside 3 chars space.
Same thing when you do
printf("%*c",x, ' ',y,' '); - just 7 blank spaces. The result is correct because printf returns how many characters it writes.
Look here for extra printf formats.

What does the n stand for in `sscanf(s, "%d %n", &i, &n)`?

The man page states that the signature of sscanf is
sscanf(const char *restrict s, const char *restrict format, ...);
I have seen an answer on SO where a function in which sscanf is used like this to check if an input was an integer.
bool is_int(char const* s) {
int n;
int i;
return sscanf(s, "%d %n", &i, &n) == 1 && !s[n];
}
Looking at !s[n] it seems to suggest that we check if sscanf scanned the character sequence until the termination character \0. So I assume n stands for the index where sscanf will be in the string s when the function ends.
But what about the variable i? What does it mean?
Edit:
To be more explicit: I see the signature of sscanf wants a pointer of type char * as first parameter. A format specifier as seconf parameter so it knows how to parse the character sequence and as much variables as conversion specifiers as next parameters. I understand now that i is for holding the parsed integer.
Since there is only one format specifier, I tried to deduce the function of n.
Is my assumption above for n correct?
Looks like the op has his answer already, but since I bothered to look this up for myself and run the code...
From "C The Pocket Reference" (2nd Ed by Herbert Shildt) scanf() section:
%n Receives an integer of value equal to the number of characters read so far
and for the return value:
The scanf() function returns a number equal to the number of the number of fields
that were successfully assigned values
The sscanf() function works the same, it just takes it's input from the supplied buffer argument ( s in this case ). The "== 1" test makes sure that only one integer was parsed and the !s[n] makes sure the input buffer is well terminated after the parsed integer and/or that there's really only one integer in the string.
Running this code, an s value like "32" gives a "true" value ( we don't have bool defined as a type on our system ) but s as "3 2" gives a "false" value because s[n] in that case is "2" and n has the value 2 ( "3 " is parsed to create the int in that case ). If s is " 3 " this function will still return true as all that white space is ingored and n has the value of 3.
Another example input, "3m", gives a "false" value as you'd expect.
Verbatim from sscanf()'s man page:
Conversions
[...]
n
Nothing is expected; instead, the number of characters
consumed thus far from the input is stored through the next pointer,
which must be a pointer to int. This is not a
conversion, although it can be suppressed with the * assignment-suppression character. The C
standard says: "Execution of
a %n directive does not increment the assignment count returned at the completion of
execution" but the Corrigendum seems to contradict this. Probably it is wise not
to make any assumptions on the effect of %n conversions on the return value.
I would like to point out that the original code is buggy:
bool is_int(char const* s) {
int n;
int i;
return sscanf(s, "%d %n", &i, &n) == 1 && !s[n];
}
I will explain why. And I will interpret the sscanf format string.
First, buggy:
Given input "1", which is the integer one, sscanf will store 1 into i. Then, since there is no white space after, sscanf will not touch n. And n is uninitialized. Because sscanf set i to 1, the value returned by sscanf will be 1, meaning 1 field scanned. Since sscanf returns 1, the part of the expression
sscanf(s, "%d %n", &i, &n) == 1
will be true. Therefore the other part of the && expression will execute. And s[n] will access some random place in memory because n is uninitialized.
Interpreting the format:
"%d %n"
Attempts to scan a number which may be a decimal number or an integer or a scientific notation number. The number is an integer, it must be followed by at least one white space. White space would be a space, \n, \t, and certain other non-printable characters. Only if it is followed by white space will it set n to the number of characters scanned to that point, including the white space.
This code might be what is intended:
static bool is_int(char const* s)
{
int i;
int fld;
return (fld = sscanf(s, "%i", &i)) == 1;
}
int main(int argc, char * argv[])
{
bool ans = false;
ans = is_int("1");
ans = is_int("m");
return 0;
}
This code is based on, if s is an integer, then sscanf will scan it and fld will be exactly one. If s is not an integer, then fld will be zero or -1. Zero if something else is there, like a word; and -1 if nothing is there but an empty string.
variable i there means until it has read an integer vaalue.
what are you trying to ask though? Its not too clear! the code will (try to ) read an integer from the string into 'i'

Using printf with a non-null terminated string

Suppose you have a string which is NOT null terminated and you know its exact size, so how can you print that string with printf in C? I recall such a method but I can not find out now...
There is a possibility with printf, it goes like this:
printf("%.*s", stringLength, pointerToString);
No need to copy anything, no need to modify the original string or buffer.
Here is an explanation of how %.*s works, and where it's specified.
The conversion specifications in a printf template string have the general form:
% [ param-no $] flags width [ . precision ] type conversion
or
% [ param-no $] flags width . * [ param-no $] type conversion
The second form is for getting the precision from the argument list:
You can also specify a precision of ‘*’. This means that the next argument in the argument list (before the actual value to be printed) is used as the precision. The value must be an int, and is ignored if it is negative.
— Output conversion syntax in the glibc manual
For %s string formatting, precision has a special meaning:
A precision can be specified to indicate the maximum number of characters to write; otherwise characters in the string up to but not including the terminating null character are written to the output stream.
— Other output conversions in the glibc manual
Other useful variants:
"%*.*s", maxlen, maxlen, val will right-justify, inserting spaces before;
"%-*.*s", maxlen, maxlen, val will left-justify.
You can use an fwrite() to stdout!
fwrite(your_string, sizeof(char), number_of_chars, stdout);
This way you will output the first chars (number defined in number_of_chars variable ) to a file, in this case to stdout (the standard output, your screen)!
printf("%.*s", length, string) will NOT work.
This means to print UP TO length bytes OR a null byte, whichever comes first. If your non-null-terminated array-of-char contains null bytes BEFORE the length, printf will stop on those, and not continue.
printf("%.5s", pointerToNonNullTerminatedString);
The string length will be 5.
#include<string.h>
int main()
{
/*suppose a string str which is not null terminated and n is its length*/
int i;
for(i=0;i<n;i++)
{
printf("%c",str[i]);
}
return 0;
}
I edited the code,heres another way:
#include<stdio.h>
int main()
{
printf ("%.5s","fahaduddin");/*if 5 is the number of bytes to be printed and fahaduddin is the string.*/
return 0;
}

Resources