0

I tried using %.s but I want don't wanna end up using it in every line is there any solution for this ?

#include<stdio.h>
void main()
{
    printf("\n %40.s press :");
    printf("\n %40.s 1.) Display all existing products:");
    printf("\n %40.s 2.) Add new product details:");
    printf("\n %40.s 3.) Edit a existing product:");
    printf("\n %40.s 4.) Make a purchase.");
    printf("\n %40.s 5.) Delete a list :");
    printf("\n %40.s 6.) Display Profit/loss is sales:");
    printf("\n %40.s 7.) Display all product with zero quantity");
    printf("\n %40.s 8.) Display all product with highest quantity");
    printf("\n %40.s 9.) Change user password.");
    printf("\n %40.s 10.) Exit the program.\n");
}

And i want output like this.

2 Answers2

2

I focus on what you asked in the title, not on your code, because your code does something very different and is not related to the question in the title.

printf() alone can not center text. You have to find out the length of the text to print and then print the padding space chars as you need to align. As the others said, make a function:

//Prints Text in the center of width, when possible
int printCenter(FILE *out, const char *str, size_t width)
{
  size_t l=strlen(str); //Find out how long the text is
  if(l<width) // only print padding chars when we can align the text
  {
    size_t p=(width-l)/2;
    //Need to convert p to a int, only do that when p is small enough
    //use UINT_MAX in #if because p is <=SIZE_MAX/2. This avoids the
    //Check when size_t and int have the same rank
    #if SIZE_MAX>UINT_MAX
    if(p>INT_MAX)
    {
      errno=ERANGE;
      return -1;
    }
    #endif
    //print the padding chars to the left
    if(fprintf(out,"%*s",(int)p,"")<0) return -1;
  }
  return fprintf(out,"%s\n",str);
}

Don't forget to include the correct headers.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • Thank you very much This is the solution I wanted . I'll do everything you mentioned above. you are the best !! – MrWhoseTheNoob Aug 13 '21 at 17:49
  • There is an unresolved issue and an unremarked-upon behaviour. The behaviour is that if the string is longer than the width, it is printed in full — a reasonable behaviour, and consistent with `%16s`, for example, which prints the whole string even if it is longer than 16 characters. The unresolved issue is whether the output should be blank-padded to full width. If this is the last field on the output line, then the trailing blanks are undesirable; if there will be other fields output on the same line, it is quite likely that a shorter string should be blank-padded to the width specified. – Jonathan Leffler Aug 13 '21 at 19:15
  • @JonathanLeffler string should be trimmed. Not the sting itself but printed partially. – 0___________ Aug 13 '21 at 19:17
  • My comments (about an unresolved issue and unremarked-upon behaviour) don't prevent this from being a useful answer. – Jonathan Leffler Aug 13 '21 at 19:17
  • @0___________ — says who? The question doesn't say that. It is legitimate to decide that 'chopping an overlong string' is correct, but 'print all of an overlong string' is also legitimate. Different people will quite reasonably have different requirements; neither behaviour is unconditionally correct for everyone. That is why what I called 'unremarked-upon behaviour' needs to be remarked upon — it is important to know how the function is designed. – Jonathan Leffler Aug 13 '21 at 19:19
  • @JonathanLeffler when I program menus and have a specific size of the window - pointing should not go outside that window. Or good function should have additional parameter what to do in this case – 0___________ Aug 13 '21 at 19:23
  • Your use case is legitimate — you can need code to do what you say (though there's another argument that trying to print an overlong string in a window is a bug at a higher level of the program). The implemented behaviour (print the whole string regardless) is also legitimate. As you say, a single function would need controls to determine what to do. Another issue would become "formatting a string" versus "printing direct to file" — should the output to a file stream be part of the solution, or should it simply format the data into a buffer? That's likely to be useful for display to 'windows'. – Jonathan Leffler Aug 13 '21 at 19:27
  • @JonathanLeffler _whether the output should be blank-padded to full width_ That is something for the OP left to do. The code isn't intended to by a source for copy&paste but to give an idea how to solve the problem. If the OP needs a full width without the newline, he can change the code. – 12431234123412341234123 Aug 13 '21 at 20:06
  • 1
    Agreed — and I hadn't noticed the newline. Designing general purpose functions is hard work, as this discussion illustrates. – Jonathan Leffler Aug 13 '21 at 20:08
  • @JonathanLeffler It wasn't the goal to reinvent `printf()`. Having said that, GNU provides the possibility to customize `printf()` at runtime. A program could add a new conversion specifier that prints a string in the center. https://www.gnu.org/software/libc/manual/html_node/Registering-New-Conversions.html – 12431234123412341234123 Aug 13 '21 at 20:32
0
typedef struct
{
    char *string;
    int (*handler)(const int, const char *, void *);
}menu_type;

void print_menu(int width, const menu_type *menu)
{
    int pos = 1;
    printf("%*spress :\n",width, "");
    while(menu -> string)
    {
        printf("%*d.) %s\n", width, pos++, menu -> string);
        menu++;
    }
}

const menu_type mm[] = 
{
    {"Display all existing products:", NULL},
    {"Add new product details:", NULL},
    {"Edit a existing product:", NULL},
    {"Make a purchase.", NULL},
    {"Delete a list :", NULL},
    {"Display Profit/loss is sales:", NULL},
    {"Display all product with zero quantity", NULL},
    {"Display all product with highest quantity", NULL},
    {"Change user password.", NULL},
    {"Exit the program.", NULL},
    {NULL, NULL},
};

int main(void)
{
    print_menu(40, mm);
}
0___________
  • 60,014
  • 4
  • 34
  • 74
  • 1
    `printf("%*.spress :\n",width);` I don't think that is correct. That causes UB and gcc warns about it with `-Wall`. – 12431234123412341234123 Aug 13 '21 at 17:26
  • If you use `.` as part of `%s`, it should be followed by a number or by `*`. `%*s` is fine; `%*.*s` is fine. But `%*.s` is not officially allowed, though it is far from improbable that implementations will handle it semi-sanely. – Jonathan Leffler Aug 13 '21 at 17:30
  • @JonathanLeffler This is for my first semester project .so can I use this method?? – MrWhoseTheNoob Aug 13 '21 at 17:34
  • 2
    It produces some output, @MrWhoseTheNoob, but whether it is what you are after is harder to say. Using `%*s` will right-align a string with a minimum width given by an argument. Using `%*d` will right-align a number with the given number of digits. None of the code is obviously 'centring' the data, but I'm not clear that's what you'd want anyway. Since you've not shown how you want the data to appear, it is hard to know what to advise. Nevertheless, using `%*.s` or `%*.d` is strictly incorrect, so using that is ill-advised — remove the `.`. – Jonathan Leffler Aug 13 '21 at 17:39
  • @JonathanLeffler sorry for my poor communication skills. But I got what you wanted to waned to say. – MrWhoseTheNoob Aug 13 '21 at 17:42
  • This is a nice template for a menu. Maybe a little bit hard for a beginner who just wants to indent menu options though? – Jardel Lucca Aug 13 '21 at 17:49
  • @12431234123412341234123 indeed – 0___________ Aug 13 '21 at 18:15
  • 1
    @JardelLucca actually this is a portion of my semester project and I want to make it look very cool. currently my project is little rough but with all your guidance and support I think I can make it perfect . – MrWhoseTheNoob Aug 13 '21 at 18:22