diff --git a/.travis.yml b/.travis.yml index 884e3cd..e119fef 100644 --- a/.travis.yml +++ b/.travis.yml @@ -84,6 +84,10 @@ deploy: - <<: *deb dist: ubuntu/bionic + # 19.04 + - <<: *deb + dist: ubuntu/disco + # Fedora - <<: *rpm dist: fedora/24 diff --git a/Makefile b/Makefile index f08a8c4..c8d03b7 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION := 9.0.2 +VERSION := 9.1.0 MAJOR_VERSION := $(shell echo $(VERSION) | head -c 1) # installation directory (/usr/local by default) diff --git a/docs/eprintf.3 b/docs/eprintf.3 deleted file mode 100644 index 0607b8f..0000000 --- a/docs/eprintf.3 +++ /dev/null @@ -1,64 +0,0 @@ -'\" t -.\" Title: eprintf -.\" Author: [see the "AUTHOR(S)" section] -.\" Generator: Asciidoctor 1.5.7.1 -.\" Date: 2017-09-16 -.\" Manual: CS50 Programmer's Manual -.\" Source: CS50 -.\" Language: English -.\" -.TH "EPRINTF" "3" "2017-09-16" "CS50" "CS50 Programmer\(aqs Manual" -.ie \n(.g .ds Aq \(aq -.el .ds Aq ' -.ss \n[.ss] 0 -.nh -.ad l -.de URL -\fI\\$2\fP <\\$1>\\$3 -.. -.als MTO URL -.if \n[.g] \{\ -. mso www.tmac -. am URL -. ad l -. . -. am MTO -. ad l -. . -. LINKSTYLE blue R < > -.\} -.SH "NAME" -eprintf \- prints an error message to stderr -.SH "SYNOPSIS" -.sp -\fB#include \fP -.sp -\fBvoid eprintf(const string format, ...);\fP -.SH "DESCRIPTION" -.sp -Prints an error message formatted like \fBprintf(3)\fP to standard error, prefixing it with file and line number from which the function was called. See \fBprintf(3)\fP for more on formatting. -.SH "EXAMPLE" -.sp -.if n .RS 4 -.nf -int main(void) -{ - eprintf("This line of code should be executed\(rsn"); - - int i; - for (i = 0; i < 50; i++) - { - printf("i is %d\(rsn", i); - } - - eprintf("Expected i to be 49 but it is actually %d\(rsn", i); -} -.fi -.if n .RE -.SH "SEE ALSO" -.sp -.if n .RS 4 -.nf -printf(3) -.fi -.if n .RE \ No newline at end of file diff --git a/src/cs50.c b/src/cs50.c index 5feac60..a51eec1 100644 --- a/src/cs50.c +++ b/src/cs50.c @@ -397,6 +397,43 @@ long get_long(const char *format, ...) } } +/** + * Prompts user for a line of text from standard input and returns the + * equivalent long long; if text does not represent a long long in + * [-2^63, 2^63 - 1) or would cause underflow or overflow, user is + * prompted to retry. If line can't be read, returns LLONG_MAX. + */ +long long get_long_long(const string format, ...) +{ + va_list ap; + va_start(ap, format); + + // Try to get a long long from user + while (true) + { + // Get line of text, returning LLONG_MAX on failure + string line = get_string(&ap, format); + if (line == NULL) + { + va_end(ap); + return LLONG_MAX; + } + + // Return a long long if only a long long (in range) was provided + if (strlen(line) > 0 && !isspace((unsigned char) line[0])) + { + char *tail; + errno = 0; + long long n = strtoll(line, &tail, 10); + if (errno == 0 && *tail == '\0' && n < LLONG_MAX) + { + va_end(ap); + return n; + } + } + } +} + /** * Called automatically after execution exits main. */ diff --git a/src/cs50.h b/src/cs50.h index 2b9d18b..b284ba2 100644 --- a/src/cs50.h +++ b/src/cs50.h @@ -94,6 +94,14 @@ int get_int(const char *format, ...) __attribute__((format(printf, 1, 2))); */ long get_long(const char *format, ...) __attribute__((format(printf, 1, 2))); +/** + * Prompts user for a line of text from standard input and returns the + * equivalent long long; if text does not represent a long long in + * [-2^63, 2^63 - 1) or would cause underflow or overflow, user is + * prompted to retry. If line can't be read, returns LLONG_MAX. + */ +long long get_long_long(const string format, ...) __attribute__((format(printf, 1, 2))); + /** * Prompts user for a line of text from standard input and returns * it as a string (char *), sans trailing line ending. Supports