From 731b0a30e98c36955516278bca7b1ee4d763d8ac Mon Sep 17 00:00:00 2001 From: Sagar Ladla <29002865+sagarladla@users.noreply.github.com> Date: Fri, 28 Jun 2024 16:16:11 +0000 Subject: [PATCH] Add-support-for-scanf-accept-formatted-input scanf support for multi byte input Added support for int, long, float, char, string datatype Added support for value deletion (backspace) Issue: #225 --- src/lib/libc/include/stdio.h | 4 +- src/lib/libc/scanf.c | 278 ++++++++++++++++++++--------------- 2 files changed, 163 insertions(+), 119 deletions(-) diff --git a/src/lib/libc/include/stdio.h b/src/lib/libc/include/stdio.h index 60ea17bf..8e19fb5f 100644 --- a/src/lib/libc/include/stdio.h +++ b/src/lib/libc/include/stdio.h @@ -30,17 +30,17 @@ extern FILE stddev[]; int __printf(const char *fmt, ...); int __eprintf(const char *fmt, ...); +int scanf(const char *fmt, ...); int fputs(const FILE *, const char *); int fputc(const FILE *, const char); int fgetc(const FILE *, char *); char getch(); char getchar(); -char *gets(); -int scanf(const char * restrict, ...); #ifdef _STDBOOL_H_ int fprintf(const FILE *, bool, const char *fmt, ...); #ifdef _STDARG_H_ +int vscanf(const FILE *, const char *fmt, va_list args); int vprintf(const FILE *, bool, const char *fmt, va_list args); #endif #endif diff --git a/src/lib/libc/scanf.c b/src/lib/libc/scanf.c index f28a2bbb..b0bfe3dc 100644 --- a/src/lib/libc/scanf.c +++ b/src/lib/libc/scanf.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include @@ -46,155 +45,200 @@ char getchar() return c; } -/** - * get string with spaces - * - * @brief This function will take string input with spaces - * - */ -char *gets(char *str) -{ - char *p = str; - char temp; - do - { - temp = getch(); - fputc(stdout, temp); - if(temp == '\r') - { - fputc(stdout, '\n'); - } - else - { - *str++ = temp; - } - } while(temp != '\r'); - str = '\0'; - return p; -} - -/** - * scanf - * - * @brief This function will take standard input for default data types. - * input will break at spaces - * - */ - -int scanf(const char * restrict fmt, ...) +int vscanf(const FILE *dev, const char *fmt, va_list args) { - unsigned int count = 0; - char c = '0', temp; - va_list ap; - va_start(ap, fmt); - while (*fmt) + int ret = 0; + int l_ret; + int N; + char c; + while (*fmt != '\0') { + l_ret = 0; if (*fmt == '%') { fmt++; - /* char length : %7d */ - unsigned int cl = 0; - while (isDigit(*fmt)) +loop: + switch (*fmt) { - cl *= 10; - cl += *fmt++ - '0'; - } - switch (*fmt++) - { - case 'c': + case 'i': + case 'd': { - /* skip leading spaces */ - while (isSpace(temp = getch())) + int a = 0; + N = 0; + // skip leading whitespaces + do { - if (temp == '\r') + fgetc(dev, &c); + if (c == '\r') fputc(stdout, '\n'); else - fputc(stdout, temp); - } - fputc(stdout, temp); - c = temp; - while ((temp = getch())) + fputc(stdout, c); + } while (isSpace(c)); + // initialize first int digit + if (c == '-') + N = 1; + else if (isDigit(c)) + a = c - '0'; + // append rest of digits till whitespace + do { - fputc(stdout, temp); - if (isSpace(temp)) - break; - } - fputc(stdout, '\n'); - *(char *)va_arg(ap, char *) = c; - count++; + fgetc(dev, &c); + if (isDigit(c)) + { + a *= 10; + a += (c - '0'); + fputc(stdout, c); + } + else if (a && (c == 0x7f || c== 0x08)) + { + a /= 10; + fputs(stdout, "\b \b"); + } + } while (!isSpace(c)); + (c == '\r') ? fputc(stdout, '\n') : fputc(stdout, c); + if (l_ret >= 2) + *(int64_t *)va_arg(args, int64_t *) = (N) ? -(a) : a; + else if (l_ret == 1) + *(long *)va_arg(args, long *) = (N) ? -(a) : a; + else + *(int *)va_arg(args, int *) = (N) ? -(a) : a; + ret++; break; } - case 's': + case 'l': { - char *s = va_arg(ap, char *); - /* skip leading spaces */ - while (isSpace(temp = getch())) + l_ret++; + fmt++; + goto loop; + } +#if USE_FLOAT == 1 + case 'f': + { + float a = 0; + unsigned int rp = 0; // radix point + float e = 1; + unsigned int fl = 1; // floating length - length after radix point + N = 0; + // skip leading whitespaces + do { - if (temp == '\r') + fgetc(dev, &c); + if (c == '\r') fputc(stdout, '\n'); else - fputc(stdout, temp); - } - fputc(stdout, temp); - *s++ = temp; - while ((temp = getch())) + fputc(stdout, c); + } while (isSpace(c)); + if (c == '.') + rp = 1; + else if (c == '-') + N = 1; + else if (isDigit(c)) + a = (float)(c - '0'); + // append rest of digits till whitespace + do { - fputc(stdout, temp); - if (isSpace(temp)) - break; - *s++ = temp; - } - fputc(stdout, '\n'); - *s = '\0'; - count++; + fgetc(dev, &c); + if (!rp && c == '.') + { + rp = 1; + fputc(stdout, c); + } + else if (isDigit(c)) + { + if (rp) + { + e /= 10.0; + a += (e * (float)(c - '0')); + fl *= 10; + } + else + { + a *= 10.0; + a += (float)(c - '0'); + } + fputc(stdout, c); + } + else if (a && (c == 0x7f || c == 0x08)) + { + long d = (long)a; + float frac = a - (float)d; + if (frac == 0.0 && rp) + rp = 0; + else if (rp) + { + fl /= 10; + frac *= fl; + frac = (long)frac / (float)fl; + a = d + frac; + } + else + a = (int)a / 10; + fputs(stdout, "\b \b"); + } + } while (!isSpace(c)); + (c == '\r') ? fputc(stdout, '\n') : fputc(stdout, c); + *(float *)va_arg(args, float *) = (N) ? -(a) : a; + ret++; break; } - case 'u': - case 'd': +#endif + case 'c': { - int a = 0; - /* skip leading spaces */ - while (isSpace(temp = getch())) + *(char *)va_arg(args, char *) = getchar(); + ret++; + break; + } + case 's': + { + int i = 0; + char *s = va_arg(args, char *); + //skip leading whitespaces + do { - if (temp == '\r') + fgetc(dev, &c); + if (c == '\r') fputc(stdout, '\n'); else - fputc(stdout, temp); - } - fputc(stdout, temp); - c = temp; - while ((temp = getch())) + fputc(stdout, c); + } while (isSpace(c)); + s[i++] = c; + do { - a *= 10; - if (isDigit(c)) - a += (c - '0'); - else - a += (int)c; - if (isSpace(temp)) + fgetc(dev, &c); + if (isSpace(c)) break; - c = temp; - fputc(stdout, temp); - } - fputc(stdout, '\n'); - *(int *)va_arg(ap, int *) = a; - count++; - break; - } - case 'f': - { - char *buff = (char *)malloc(sizeof(char) * 50); - gets(buff); - *(float *)va_arg(ap, float *) = (float)atof(buff); - count++; + else if (i && (c == 0x7f || c == 0x08)) + { + i--; + fputs(stdout, "\b \b"); + } + else + s[i++] = c; + fputc(stdout, c); + } while (!isSpace(c)); + (c == '\r') ? fputc(stdout, '\n') : fputc(stdout, c); + s[i] = '\0'; + ret++; break; } default: - break; + return -1; } continue; } /* increment pointer if % not found */ fmt++; } - return count; + fputc(stdout, '\n'); + return ret; +} + +int scanf(const char *fmt, ...) +{ + int ret; + va_list va; + va_start(va, fmt); + ret = vscanf(stdin, fmt, va); + va_end(va); + return ret; }