0

This code:

#include <stdio.h>

void main()
{
    char *csv_delimiter = ",";
    printf("col1%scol2%scol3%scol4\n", csv_delimiter, csv_delimiter, csv_delimiter);
}

has this output:

col1,col2,col3,col4

That's exactly what I need. But I have to refer to the pointer csv_delimiter multiple times. What if I had 1 thousand columns? Is there a way to refer to csv_delimiter only once and print it multiple times to delimite as many columns as possible? I'm looking for some code like this:

#include <stdio.h>

void main()
{
    char *csv_delimiter = ",";
    printf("col1[REF1]col2[REF1]col3[REF1]col4\n", csv_delimiter);
}

As you can see from this example, I'm not looking for a loop (I can't loop in the original code due to reasons related to the implementation). I need some way to put a lot of %s in a single line and refer them all to the same pointer, in this case csv_delimiter. I'm sure this is possible. I remember reading something like this in Deitel, but I can't find where he explains how to do this.

renatov
  • 5,005
  • 6
  • 31
  • 38
  • 2
    [relevant](http://stackoverflow.com/questions/10572271/how-can-i-print-the-same-variable-into-a-string-several-times) – Ryan Haining Apr 30 '15 at 21:58
  • The reasons are related to the original implementation I'm working on and would add anything to my question. What I'm asking is clear: I can't loop, I need a way to refer every `%s` to the same pointer. – renatov Apr 30 '15 at 22:20
  • 1
    a loop is your only option in standard ANSI-C though. Also why exactly can't you just use a loop? Anyway, on windows I guess that shouldwork: https://msdn.microsoft.com/en-us/library/bt7tawza.aspx – rfreytag Apr 30 '15 at 22:23
  • @RyanHaining, I read that question before opening this one. The solution presented there doesn't work for me in Windows using MinGW, as I said there. – renatov Apr 30 '15 at 22:24
  • "reasons related to the implementation" - can you be more specific? – Iskar Jarak Apr 30 '15 at 22:26
  • @pfannkuchen_gesicht to explain why I can't loop, I would have to describe the whole implementation I'm doing (which is a simulation of human behavior using an artificial neural network created with FANN). It would add nothing to the question. What I'm looking for is very clearly put in my example. – renatov Apr 30 '15 at 22:27
  • And by the way, `void main()` is not standard C, please use `int main()` instead. – Iskar Jarak Apr 30 '15 at 22:27
  • 3
    Re. having to describe the whole implementation, can't you try to produce a simplified example of why you cannot loop for this? – Iskar Jarak Apr 30 '15 at 22:29
  • let me guess, you have a function somewhere, which builds your format string as the computation goes on and that's why you need a way to avoid loops? – rfreytag Apr 30 '15 at 22:36
  • 1
    @pfannkuchen_gesicht it's related to the FANN struct output format, to the file I'm reading the input from and how I need to process these information all together to output a CSV file to be used by another function. – renatov Apr 30 '15 at 22:42
  • 1
    Call me naive, but I can't think of any conceivable reason why this wouldn't be possible with a loop. I think perhaps your real question lies outside of what you're showing us. – MasterHD Apr 30 '15 at 23:01
  • 1
    If you don't use a loop for this, the function you end up calling will. – Crowman Apr 30 '15 at 23:47
  • For the "col1","col2", etc. is there a plan to fill those with values, say %d? – bentank May 01 '15 at 00:15
  • Take a look at http://stackoverflow.com/questions/11532883/is-there-a-c-macro-to-generate-repeat-string. Not the except answer, but the 4th or so one down. It uses memset in a macro. Might work for your needs. – bentank May 01 '15 at 00:21

4 Answers4

1

you could use a format specifier position modifier:

void main()
{
    char *csv_delimiter = ",";
    printf("col1%1$scol2%1$scol3%1$scol4\n", csv_delimiter);
}

here the %1$s is the format specifier for the first parameter after the format.

Grady Player
  • 14,399
  • 2
  • 48
  • 76
  • 1
    You ought to point out that this (and `void main()`, for that matter) is non-standard. – Crowman Apr 30 '15 at 22:08
  • Yes, I'm looking for a "position modifier". I'll test your answer. If it works, I'll mark it as correct. – renatov Apr 30 '15 at 22:08
  • It didn't work. The line `printf("col1%1$scol2%1$scol3%1$scol4\n", csv_delimiter);` has the following output: `col1$scol2$scol3$scol4`. I upvoted your answer anyway, because this is exactly what I'm looking for. – renatov Apr 30 '15 at 22:11
  • @PaulGriffiths... I didn't know it was non-standard... it is listed in this standard: http://pubs.opengroup.org/onlinepubs/009695399/functions/printf.html... – Grady Player Apr 30 '15 at 22:11
  • 3
    @GradyPlayer: That's *a* standard, but it's not the C standard. – Crowman Apr 30 '15 at 22:11
  • @renatov, sorry, I guess it isn't standard then... I have used them for localization on mac os stuff, but I don't know really where that behavior is defined – Grady Player Apr 30 '15 at 22:12
  • @GradyPlayer I appreciate your help. Do you know some equivalent solution to the "position modifier" you posted, but for windows? – renatov Apr 30 '15 at 22:16
1

On Windows there is a _printf_p() function, which implements the positional parameter. So instead

printf("col1%1$scol2%1$scol3%1$scol4\n", csv_delimiter);

you should be able to use

_printf_p("col1%1$scol2%1$scol3%1$scol4\n", csv_delimiter);

See https://msdn.microsoft.com/en-us/library/bt7tawza.aspx for more info.

EDIT:

for Linux/Windows cross compiling use something like this:

#if defined (__WIN32__)
  _printf_p(...);
#elif defined (__linux__)
  printf(...);
#endif
rfreytag
  • 1,203
  • 11
  • 18
  • This is very close to what I need. I tested but "_printf_p" couldn't be found. Do you know if this function can only be used within Visual Studio? I prefer to use MinGW. – renatov Apr 30 '15 at 22:39
  • will not work on linux, however, you should be able to create a macro with that or at least you can use pre-compiler directives to switch between the two, depending on which platform you compile. – rfreytag Apr 30 '15 at 22:41
  • did you include the conio.h header file? – rfreytag Apr 30 '15 at 23:01
  • This answer did not solve the issue, but it helped me the most, so I'm choosing it to close this topic. – renatov May 06 '15 at 18:49
0

OP asserts "I can't loop in the original code due to reasons related to the implementation)".

Assuming this limitation does not refer to all code, but only to the print command itself, call a helper function instead of printf(). Since OP wants "... some way to put a lot of %s in a single line and refer them all to the same pointer", processing that single line is easy.

#include <stdio.h>

void printf_renatov(const char *format, const char *csv_delimiter) {
  while (*format) {
    if (format[0] == '%' && format[1] == 's') {
      fputs(csv_delimiter, stdout);
      format += 2;
    } else {
      fputc(*format, stdout);
      format++;
    }
  }
}

int main(void) {
  char *csv_delimiter = ",";
  printf_renatov("col1%scol2%scol3%scol4\n", csv_delimiter);
}

col1,col2,col3,col4

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
-3

why can't you use a loop?

int i, max;
for(i=0; i<max-1; i++){
    printf("col%d%s ", i, csv_delimiter);
}
printf("col%d%\n", max);

where max is the highest value you wish to print.

  • I can't use a loop in the original code because of reasons related to the implementation' specificities. – renatov Apr 30 '15 at 22:14