how can i make functions which behaves like printf

K

Kaush

how can i make functions which behaves like printf.
i mean the function should be capable of accepting variable number of
arguments and of varaible types.
thanx
kaush
 
P

pete

Kaush said:
how can i make functions which behaves like printf.
i mean the function should be capable of accepting variable number of
arguments and of varaible types.

/* BEGIN std_io.h */

#ifndef H_STD_IO
#define H_STD_IO

#include <stdarg.h>
#include <stdio.h>
/*
** Only 4 features from stdio.h, are used in std_io.c:
**
** EOF
** FILE
** stdout
** putc(c, stream)
*/

#define put_c(c, stream) (putc((c), (stream)))
#define put_char(c) (put_c((c), stdout))

int (put_c)(int, FILE *);
int fput_c(int, FILE *);
int (put_char)(int);
int put_s(const char *);
int fput_s(const char *, FILE *);
int min_printf(char *, ...);
/*
** Only 5 different conversion specifiers
** are supported for min_printf: % c d s u
** and no fancy stuff.
*/

#endif

/* END std_io.h */

/* BEGIN std_io.c */

#include "std_io.h"

static int put_u(unsigned);
static int put_u_plus_1(unsigned);
static int put_d(int);

int (put_c)(int c, FILE *stream)
{
return put_c(c, stream);
}

int fput_c(int c, FILE *stream)
{
return put_c(c, stream);
}

int (put_char)(int c)
{
return put_c(c, stdout);
}

int put_s(const char *s)
{
while (*s != '\0') {
if (put_char(*s) == EOF) {
return EOF;
}
++s;
}
return put_char('\n');
}

int fput_s(const char *s, FILE *stream)
{
const char *const p = s;

while (*s != '\0') {
if (put_c(*s, stream) == EOF) {
return EOF;
}
++s;
}
return s - p;
}

static int put_u(unsigned integer)
{
int count;

if (integer / 10 != 0) {
count = put_u(integer / 10);
if (count == EOF) {
return EOF;
}
} else {
count = 0;
}
return put_char(integer % 10 + '0') == EOF ? EOF : count + 1;
}

static int put_u_plus_1(unsigned integer)
{
unsigned digit;
int count;

digit = (integer % 10 + 1) % 10;
integer /= 10;
if (integer != 0) {
count = digit == 0 ? put_u_plus_1(integer) : put_u(integer);
if (count == EOF) {
return EOF;
}
} else {
if (digit == 0) {
if (put_char('1') == EOF) {
return EOF;
}
count = 1;
} else {
count = 0;
}
}
return put_char('0' + digit) == EOF ? EOF : count + 1;
}

static int put_d(int integer)
{
int count;

if (0 > integer) {
if (put_char('-') == EOF) {
return EOF;
}
++integer;
integer = -integer;
count = put_u_plus_1(integer);
return count == EOF ? EOF : count + 1;
} else {
return put_u(integer);
}
}

int min_printf(char *s, ...)
{
int count, increment;
va_list ap;

va_start(ap, s);
for (count = 0; *s != '\0'; ++s) {
if (*s == '%') {
switch (*++s) {
case 'c':
increment =
put_char(va_arg(ap, int)) == EOF ? EOF : 1;
break;
case 'd':
increment = put_d(va_arg(ap, int));
break;
case 's':
increment = fput_s(va_arg(ap, char *), stdout);
break;
case 'u':
increment = put_u(va_arg(ap, unsigned));
break;
default:
increment = put_char(*s) == EOF ? EOF : 1;
break;
}
} else {
increment = put_char(*s) == EOF ? EOF : 1;
}
if (increment == EOF) {
return EOF;
} else {
count += increment;
}
}
va_end(ap);
return count;
}

/* END std_io.c */
 
P

Peter Pichler

pete said:
#include <stdio.h>

#define put_c(c, stream) (putc((c), (stream)))

int (put_c)(int c, FILE *stream)
{
return put_c(c, stream);
}

That's really neat, I love the general idea. Is it portable?

Peter
 
P

pete

You can link str_str.c with std_io.c

/* BEGIN str_str.c output */

put_s is a function.
fput_s is a function.
fput_c is a function.
put_char is a macro.
put_c is a macro.

On my system:

puts is a function.
fputs is a function.
fputc is a function.
putchar is a macro.
putc is a macro.

/* END str_str.c output */

/* BEGIN str_str.c */

#include <string.h>
#include "std_io.h"

#define str(s) # s
#define xstr(s) str(s)

int main(void)
{
char *mf[] = {"macro", "function"};

put_s("/* BEGIN str_str.c output */\n");
min_printf("put_s is a %s.\n",
mf[strstr(xstr(put_s(A)), str(put_s(A))) != NULL]);
min_printf("fput_s is a %s.\n",
mf[strstr(xstr(fput_s(A)), str(fput_s(A))) != NULL]);
min_printf("fput_c is a %s.\n",
mf[strstr(xstr(fput_c(A)), str(fput_c(A))) != NULL]);
min_printf("put_char is a %s.\n",
mf[strstr(xstr(put_char(A)), str(put_char(A))) != NULL]);
min_printf("put_c is a %s.\n",
mf[strstr(xstr(put_c(A, B)), str(put_c(A, B))) != NULL]);
put_s("\nOn my system:\n");
min_printf("puts is a %s.\n",
mf[strstr(xstr(puts(A)), str(puts(A))) != NULL]);
min_printf("fputs is a %s.\n",
mf[strstr(xstr(fputs(A)), str(fputs(A))) != NULL]);
min_printf("fputc is a %s.\n",
mf[strstr(xstr(fputc(A)), str(fputc(A))) != NULL]);
min_printf("putchar is a %s.\n",
mf[strstr(xstr(putchar(A)), str(putchar(A))) != NULL]);
min_printf("putc is a %s.\n",
mf[strstr(xstr(putc(A, B)), str(putc(A, B))) != NULL]);
put_s("\n/* END str_str.c output */");
return 0;
}

/* END str_str.c */
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top