Left-pad printf with spaces - c

How can I pad a string with spaces on the left when using printf?
For example, I want to print "Hello" with 40 spaces preceding it.
Also, the string I want to print consists of multiple lines. Do I need to print each line separately?
EDIT: Just to be clear, I want exactly 40 spaces printed before every line.

If you want the word "Hello" to print in a column that's 40 characters wide, with spaces padding the left, use the following.
char *ptr = "Hello";
printf("%40s\n", ptr);
That will give you 35 spaces, then the word "Hello". This is how you format stuff when you know how wide you want the column, but the data changes (well, it's one way you can do it).
If you know you want exactly 40 spaces then some text, save the 40 spaces in a constant and print them. If you need to print multiple lines, either use multiple printf statements like the one above, or do it in a loop, changing the value of ptr each time.

I use this function to indent my output (for example to print a tree structure). The indent is the number of spaces before the string.
void print_with_indent(int indent, char * string)
{
printf("%*s%s", indent, "", string);
}

int space = 40;
printf("%*s", space, "Hello");
This statement will reserve a row of 40 characters, print string at the end of the row (removing extra spaces such that the total row length is constant at 40).
Same can be used for characters and integers as follows:
printf("%*d", space, 10);
printf("%*c", space, 'x');
This method using a parameter to determine spaces is useful where a variable number of spaces is required. These statements will still work with integer literals as follows:
printf("%*d", 10, 10);
printf("%*c", 20, 'x');
printf("%*s", 30, "Hello");
Hope this helps someone like me in future.

If you want exactly 40 spaces before the string then you should just do:
printf(" %s\n", myStr );
If that is too dirty, you can do (but it will be slower than manually typing the 40 spaces):
printf("%40s%s", "", myStr );
If you want the string to be lined up at column 40 (that is, have up to 39 spaces proceeding it such that the right most character is in column 40) then do this:
printf("%40s", myStr);
You can also put "up to" 40 spaces AfTER the string by doing:
printf("%-40s", myStr);

Related

printf variable placeholder? Is it even a thing?

#include <stdio.h>
char pos[] = {34,92,48,51,51,91,57,59,57,72,37,115,34}; // "\033[9;9H%s"
main() {
printf(pos,"Aaaaaaa"); // (1) This doesnt work as intended
printf("\033[9;9H%s","Aaaaaaa"); // (2) Works as intended
}
So why (2) works and (1) doesn't?
There are two problems with pos.
First what you have is a character array, not a null terminated string. You need to add a 0 to the end of that array.
Second, you don't have the same characters. In the string literal "\033[9;9H%s" there are a total of 8 characters while pos has 13.
The sequence \033 represent a single character whose value is 33 octal or 27 decimal. You instead have the literal characters '\', '0', '3', and '3'. So replace 92,48,51,51 with 27. Also, you have 34 for the first and last characters in pos, which is the double quote character ". These characters are not part of the string literal but are used to denote it in code. So get rid of those.
pos should now look like this:
char pos[] = {27,91,57,59,57,72,37,115,0};
You've got three differences:
You don't need the initial and final 34 character ("), since string (2) doesn't print them out.
You need a null terminator to ensure that you print only your string and nothing more.
If \033 is meant to be an escape character, then its value is just 27, not 92,48,51,51.
After addressing those differences, your pos array:
{34,92,48,51,51,91,57,59,57,72,37,115,34}
Should instead look like this (aligned to match the original array):
{27,91,57,59,57,72,37,115,0}

Printing number of spaces

Is there a way to specify the number of spaces using a variable?
For example lets say I have a basic print statement:
printf("%5d",someNumber);
This will print 5 spaces then the number. Is there a way that would let me declare a variable var = 5, and use a variable to determine spacing instead? The reason i'm asking is because I'm trying to control the number of spaces after each iteration of a loop to format data a certain way
Try:
printf("%*d", width, someNumber);
You can find more info by man 3 printf
"%5d" prints at least 5 characters. Leading spaces are first printed as needed, then the '-' sign, if needed, then the digits.
To print an int with at least n characters,use '*', the minimum field width:
printf("%*d", n, someNumber);
To print n spaces only, use
printf("%*s", n, "");
The format string is just that: a string. You can build your own with sprintf() e.g.:
sprintf(frmt,"%%%dd",iterator);
If iterator = 3 wil give the format string "%3d" which you can use in printf() like e.g.:
printf(frmt,some_number);
(The variable field width posted by Jesse Chen is not necessarily available everywhere)

Issue with saving characters in multidimensional array

i have a given Input of four scanf-strings which i want to save in a multidimensional array. I Don't know if i save the string right, but i can't just simply print the whole array or certain characters of it.
char getr[4][4];
for (z=0; z<4; z++){
scanf(" %99s", &getr[z]);
}
for (s=0; s<4; s++) {
printf("%s\n",getr[s]);
}
Input:
abcd
efgh
ijkl
mnop
Output:
abcdefghijklmnop
efghijklmnop
ijklmnop
mnop
what if i just want to print the second line or the fourth character of the first line? Does anybody know?
First, change as following:
scanf(" %99s", getr[z]); //getr[z] is the address to take the 4 characters string
To print out the second line:
printf("%s\n", getr[1]);
To print out the fourth character of the first line:
printf("%c\n", getr[0][3]); // %c is used here because just print one character.
To store 4-char strings, like your example input, you need 5-char arrays to leave room for the terminating null character:
char getr[4][5];
Your scanf() format string should also reflect the amount of space you have; %99s could read up to 100 bytes (99 chars plus the null), and you only have 5 (including the null, after the above change). Also, &getr[z] and getr[z] happen to give the same address, but the types of the pointers are different -- but getr[z] gives a char * which is appropriate in this case. So...
scanf(" %4s", getr[z]);
Those changes will already keep the strings from running together, so individual strings can be accessed as getr[0] through getr[3]. To print individual characters within a string, add an additional set of indexing brackets and use a function that prints a character rather than a string:
fputc(getr[0][2],stdout); /* print 3rd char in 1st string */
printf("%c",getr[1][3]); /* print 4th char of 2nd string */
The reason you were getting all your strings concatenated was because the null char from the earlier strings overflowed into the next char array, and was overwritten by the first char of the next string you read. The last string's null would have overflowed past your whole 2D array into whatever was next in memory (which is bad).

Sscanf not returning what I want

I have the following problem:
sscanf is not returning the way I want it to.
This is the sscanf:
sscanf(naru,
"%s[^;]%s[^;]%s[^;]%s[^;]%f[^';']%f[^';']%[^;]%[^;]%[^;]%[^;]"
"%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]"
"%[^;]%[^;]%[^;]%[^;]%[^;]%[^;]",
&jokeri, &paiva1, &keskilampo1, &minlampo1, &maxlampo1,
&paiva2, &keskilampo2, &minlampo2, &maxlampo2, &paiva3,
&keskilampo3, &minlampo3, &maxlampo3, &paiva4, &keskilampo4,
&minlampo4, &maxlampo4, &paiva5, &keskilampo5, &minlampo5,
&maxlampo5, &paiva6, &keskilampo6, &minlampo6, &maxlampo6,
&paiva7, &keskilampo7, &minlampo7, &maxlampo7);
The string it's scanning:
const char *str = "city;"
"2014-04-14;7.61;4.76;7.61;"
"2014-04-15;5.7;5.26;6.63;"
"2014-04-16;4.84;2.49;5.26;"
"2014-04-17;2.13;1.22;3.45;"
"2014-04-18;3;2.15;3.01;"
"2014-04-19;7.28;3.82;7.28;"
"2014-04-20;10.62;5.5;10.62;";
All of the variables are stored as char paiva1[22] etc; however, the sscanf isn't storing anything except the city correctly. I've been trying to stop each variable at ;.
Any help how to get it to store the dates etc correctly would be appreciated.
Or if there's a smarter way to do this, I'm open to suggestions.
There are multiple problems, but BLUEPIXY hit the first one — the scan-set notation doesn't follow %s.
Your first line of the format is:
"%s[^;]%s[^;]%s[^;]%s[^;]%f[^';']%f[^';']%[^;]%[^;]%[^;]%[^;]"
As it stands, it looks for a space separated word, followed by a [, a ^, a ;, and a ] (which is self-contradictory; the character after the string is a space or end of string).
The first fixup would be to use scan-sets properly:
"%[^;]%[^;]%[^;]%[^;]%f[^';']%f[^';']%[^;]%[^;]%[^;]%[^;]"
Now you have a problem that the first %[^;] scans everything up to the end of string or first semicolon, leaving nothing for the second %[;] to match.
"%[^;]; %[^;]; %[^;]; %[^;]; %f[^';']%f[^';']%[^;]%[^;]%[^;]%[^;]"
This looks for a string up to a semicolon, then for the semicolon, then optional white space, then repeats for three items. Apart from adding a length to limit the size of string, preventing overflow, these are fine. The %f is OK. The following material looks for an odd sequence of characters again.
However, when the data is looked at, it seems to consist of a city, and then seven sets of 'a date plus three numbers'.
You'd do better with an array of structures (if you've worked with those yet), or a set of 4 parallel arrays, and a loop:
char jokeri[30];
char paiva[7][30];
float keskilampo[7];
float minlampo[7];
float maxlampo[7];
int eoc; // End of conversion
int offset = 0;
char sep;
if (fscanf(str + offset, "%29[^;]%c%n", jokeri, &sep, &eoc) != 2 || sep != ';')
...report error...
offset += eoc;
for (int i = 0; i < 7; i++)
{
if (fscanf(str + offset, "%29[^;];%f;%f;%f%c%n", paiva[i],
&keskilampo[i], &minlampo[i], &maxlampo[i], &sep, &eoc) != 5 ||
sep != ';')
...report error...
offset += eoc;
}
See also How to use sscanf() in loops.
Now you have data that can be managed. The set of 29 separately named variables is a ghastly thought; the code using them will be horrid.
Note that the scan-set conversion specifications limit the string to a maximum length one shorter than the size of jokeri and the paiva array elements.
You might legitimately be wondering about why the code uses %c%n and &sep before &eoc. There is a reason, but it is subtle. Suppose that the sscanf() format string is:
"%29[^;];%f;%f;%f;%n"
Further, suppose there's a problem in the data that the semicolon after the third number is missing. The call to sscanf() will report that it made 4 successful conversions, but it doesn't count the %n as an assignment, so you can't tell that sscanf() didn't find a semicolon and therefore did not set &eoc at all; the value is left over from a previous call to sscanf(), or simply uninitialized. By using the %c to scan a value into sep, we get 5 returned on success, and we can be sure the %n was successful too. The code checks that the value in sep is in fact a semicolon and not something else.
You might want to consider a space before the semi-colons, and before the %c. They'll allow some other data strings to be converted that would not be matched otherwise. Spaces in a format string (outside a scan-set) indicate where optional white space may appear.
I would use strtok function to break your string into pieces using ; as a delimiter. Such a long format string may be a source of problems in future.

moving elements of array in c, is there a better option

I am reading input from file (line by line) Each line is a state of a game board. Below is example of input:
(8,7,1,0,0,0,b,b,b,b,b,b,b,b,b,b,b,b,s,s,r,r,g,b,r,g,r,r,r,r,b,r,r,s,b,b,b,b,r,s,s,r,b,b,r,s,s,s,r,b,g,b,r,r,r,r,r,r,r,r,r,s) 0
I have used fgets() and strtok() to split the string at (),
My problem:
I want the first 6 integers in their individual variables such as:
int column = 8
int row = 7
so on..
I want to get rid of the last integer at the end of input- 0
and the chars should be stored in an array, because they represent pieces of a board.
Right now, I have an array with all the integers and chars stored together.
I can iterate through my array, and copy the integers to their variables and then chars to a new array. But that's inefficient.
Is there another way to do it?
I used fscanf() but don't know how to split the string using delimiters.
Thanks
WELL-FORMED INPUT ONLY
if (fscanf(FILE_PTR, "(%d,%d,...,%c,%c,%c,...,%c) %*d", &column, &row, ..., &chars[0], &chars[1], ...) == 60)
or something like that
the %*d specifier will discard that input (you didn't want the last number)
for the chars, give pointers to their indices for a preallocated array
for the ints, give the variable pointer/ref
Thank you to Jon Leffler for reminding that you should test the output of *scanf (number of things read)!
More information
REEDIT nope, it was right -
int fscanf ( FILE * stream, const char * format, ... );
format: C string that contains a sequence of characters that control how characters extracted from the stream are treated:
Whitespace character: the function will read and ignore any whitespace characters encountered before the next non-whitespace character (whitespace characters include spaces, newline and tab characters -- see isspace). A single whitespace in the format string validates any quantity of whitespace characters extracted from the stream (including none).
Non-whitespace character, except format specifier (%): Any character that is not either a whitespace character (blank, newline or tab) or part of a format specifier (which begin with a % character) causes the function to read the next character from the stream, compare it to this non-whitespace character and if it matches, it is discarded and the function continues with the next character of format. If the character does not match, the function fails, returning and leaving subsequent characters of the stream unread.
Format specifiers: A sequence formed by an initial percentage sign (%) indicates a format specifier, which is used to specify the type and format of the data to be retrieved from the stream and stored into the locations pointed by the additional arguments.
Above quote from here. I am aware of the hostility towards cplusplus.com here but I do not have access to the standard. please feel free to edit if you do
I have used fgets() and strtok() to split the string at "()"
later
I used fscanf() but don't know how to split the string using delimiters.
I guess if strtok() worked for parenthesis, it would work for commas too.
Apart from that: you have several possibilities for doing what you want. Without much context provided, I can't really tell you which one you want, but here we go:
Grab a pointer to the first non-integer, and use it as if it was a pointer to the first element of another array, containing the integers only. This avoids all copying and/or moving overhead.
Use memcpy() to copy only the necessary parts of the array to another array. memcpy() is generally highly optimized and faster than the naive for-loop-with-assignment approach.
if you have a char * you can think of it as an array or as a string, as the memory layout is the same...
char * input = "(8,7,1,0,0,0,b,b,b,b,b,b,b,b,b,b,b,b,s,s,r,r,g,b,r,g,r,r,r,r,b,r,r,s,b,b,b,b,r,s,s,r,b,b,r,s,s,s,r,b,g,b,r,r,r,r,r,r,r,r,r,s) 0";
size_t len = strlen(input);
int currentIndex = 0;
char * output = calloc(1,len);
for (int i = 0 ; i<len ; i++)
{
if (input[i] == '(' || input[i] == ')' || input[i] == ','|| input[i] == ' ') {
continue;
}
output[currentIndex++] = input[i];
}
assert(strlen(output) == 63); //well formatted?
char a = output[0];
char b = output[1];
char (* board)[60] = malloc(60); //pointer to array or is it a mal-formed string.
memcpy(board, output+2, 60);
char last = output[62];
the main thing that I would add, if you want to use it more like a string, then you have to make the array 1 bigger and set board[60] = \0;

Resources