/**************************************************************************** * CS50 Library 2.1 * * https://manual.cs50.net/Library * * Glenn Holloway * David J. Malan * * Based on Eric Roberts' genlib.c and simpio.c. * * Creative Commons Attribution-ShareAlike 3.0 Unported License * http://creativecommons.org/licenses/by-sa/3.0/ ***************************************************************************/ #include #include #include #include #include "cs50.h" /* * Reads a line of text from standard input and returns the equivalent * char; if text does not represent a char, user is prompted to retry. * Leading and trailing whitespace is ignored. If line can't be read, * returns CHAR_MAX. */ char GetChar(void) { // try to get a char from user while (true) { // get line of text, returning CHAR_MAX on failure string line = GetString(); if (line == NULL) return CHAR_MAX; // return a char if only a char (possibly with // leading and/or trailing whitespace) was provided char c1, c2; if (sscanf(line, " %c %c", &c1, &c2) == 1) return c1; else printf("Retry: "); } } /* * Reads a line of text from standard input and returns the equivalent * double as precisely as possible; if text does not represent a * double, user is prompted to retry. Leading and trailing whitespace * is ignored. For simplicity, overflow and underflow are not detected. * If line can't be read, returns DBL_MAX. */ double GetDouble(void) { // try to get a double from user while (true) { // get line of text, returning DBL_MAX on failure string line = GetString(); if (line == NULL) return DBL_MAX; // return a double if only a double (possibly with // leading and/or trailing whitespace) was provided double d; char c; if (sscanf(line, " %lf %c", &d, &c) == 1) return d; else printf("Retry: "); } } /* * Reads a line of text from standard input and returns the equivalent * float as precisely as possible; if text does not represent a float, * user is prompted to retry. Leading and trailing whitespace is ignored. * For simplicity, overflow and underflow are not detected. If line can't * be read, returns FLT_MAX. */ float GetFloat(void) { // try to get a float from user while (true) { // get line of text, returning FLT_MAX on failure string line = GetString(); if (line == NULL) return FLT_MAX; // return a float if only a float (possibly with // leading and/or trailing whitespace) was provided char c; float f; if (sscanf(line, " %f %c", &f, &c) == 1) return f; else printf("Retry: "); } } /* * Reads a line of text from standard input and returns it as an * int in the range of [-2^31 + 1, 2^31 - 2], if possible; if text * does not represent such an int, user is prompted to retry. Leading * and trailing whitespace is ignored. For simplicity, overflow is not * detected. If line can't be read, returns INT_MAX. */ int GetInt(void) { // try to get an int from user while (true) { // get line of text, returning INT_MAX on failure string line = GetString(); if (line == NULL) return INT_MAX; // return an int if only an int (possibly with // leading and/or trailing whitespace) was provided int n; char c; if (sscanf(line, " %d %c", &n, &c) == 1) return n; else printf("Retry: "); } } /* * Reads a line of text from standard input and returns an equivalent * long long in the range [-2^63 + 1, 2^63 - 2], if possible; if text * does not represent such a long long, user is prompted to retry. * Leading and trailing whitespace is ignored. For simplicity, overflow * is not detected. If line can't be read, returns LLONG_MAX. */ long long GetLongLong(void) { // try to get a long long from user while (true) { // get line of text, returning LLONG_MAX on failure string line = GetString(); if (line == NULL) return LLONG_MAX; // return a long long if only a long long (possibly with // leading and/or trailing whitespace) was provided long long n; char c; if (sscanf(line, " %lld %c", &n, &c) == 1) return n; else printf("Retry: "); } } /* * Reads a line of text from standard input and returns it as a string, * sans trailing newline character. (Ergo, if user inputs only "\n", * returns "" not NULL.) Leading and trailing whitespace is not ignored. * Returns NULL upon error or no input whatsoever (i.e., just EOF). */ string GetString(void) { // growable buffer for chars string buffer = NULL; // capacity of buffer unsigned int capacity = 0; // number of chars actually in buffer unsigned int n = 0; // character read or EOF int c; // iteratively get chars from standard input while ((c = fgetc(stdin)) != '\n' && c != EOF) { // grow buffer if necessary if (n + 1 > capacity) { // determine new capacity: start at 32 then double if (capacity == 0) capacity = 32; else if (capacity <= (UINT_MAX / 2)) capacity *= 2; else { GC_FREE(buffer); return NULL; } // extend buffer's capacity string temp = GC_REALLOC(buffer, capacity * sizeof(char)); if (temp == NULL) { GC_FREE(buffer); return NULL; } buffer = temp; } // append current character to buffer buffer[n++] = c; } // return NULL if user provided no input if (n == 0 && c == EOF) return NULL; // minimize buffer string minimal = GC_MALLOC((n + 1) * sizeof(char)); strncpy(minimal, buffer, n); GC_FREE(buffer); // terminate string minimal[n] = '\0'; // return string return minimal; }