/**************************************************************************** * cs50.c * * version 1.1.2 * * Computer Science 50 * Glenn Holloway * David J. Malan * * Definitions for CS 50's library. * Based on Eric Roberts' genlib.c and simpio.c. * * The latest version of this file can be found at * http://cs50.net/pub/releases/cs50/cs50.c. * * To compile as a static library on your own system: * % gcc -c -ggdb -std=c99 cs50.c -o cs50.o * % ar rcs libcs50.a cs50.o * % rm -f cs50.o * % cp cs50.h /usr/local/include * % cp libcs50.a /usr/local/lib ***************************************************************************/ #include #include #include #include "cs50.h" /* * Default capacity of buffer for standard input. */ #define CAPACITY 128 /* * char * GetChar() * * 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() { // 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) { free(line); return c1; } else { free(line); printf("Retry: "); } } } /* * double * GetDouble() * * 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() { // 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) { free(line); return d; } else { free(line); printf("Retry: "); } } } /* * float * GetFloat() * * 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() { // 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) { free(line); return f; } else { free(line); printf("Retry: "); } } } /* * int * GetInt() * * 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() { // 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) { free(line); return n; } else { free(line); printf("Retry: "); } } } /* * long long * GetLongLong() * * 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() { // 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) { free(line); return n; } else { free(line); printf("Retry: "); } } } /* * string * GetString() * * 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() { // 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 CAPACITY then double if (capacity == 0) capacity = CAPACITY; else if (capacity <= (UINT_MAX / 2)) capacity += 2; else { free(buffer); return NULL; } // extend buffer's capacity string temp = realloc(buffer, capacity * sizeof(char)); if (temp == NULL) { 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 = malloc((n + 1) * sizeof(char)); strncpy(minimal, buffer, n); free(buffer); // terminate string minimal[n] = '\0'; // return string return minimal; }