.. default-domain:: c .. highlight:: c ============================ CS50 Library for C ============================ Installation ============ Ubuntu ------- .. code-block:: bash $ curl -s https://packagecloud.io/install/repositories/cs50/repo/script.deb.sh | sudo bash $ sudo apt install libcs50 Fedora ------- .. code-block:: bash $ curl -s https://packagecloud.io/install/repositories/cs50/repo/script.rpm.sh | sudo bash $ dnf install libcs50 From Source (Linux and Mac) --------------------------- 1. Download the latest release from https://github.com/cs50/libcs50/releases 2. Extract ``libcs50-*.*`` 3. ``cd libcs50-*`` 4. ``sudo make install`` Environment Variables ===================== For parity with `Visual Studio Code for CS50 `_ and `cli50 `_, you may want to set these environment variables: .. code-block:: bash CC="clang" CFLAGS="-ferror-limit=1 -gdwarf-4 -ggdb3 -O0 -std=c11 -Wall -Werror -Wextra -Wno-gnu-folding-constant -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wno-unused-but-set-variable -Wshadow" LDLIBS="-lcrypt -lcs50 -lm" Makefile -------- Alternatively, if using a ``Makefile`` to compile a program (e.g., ``foo``) from multiple files (e.g., ``foo.c`` and ``bar.c``), you could structure it as follows. But be sure the last line begins with an actual tab character (``\t``), not spaces. .. code-block:: bash CC= clang CFLAGS = -ferror-limit=1 -gdwarf-4 -ggdb3 -O0 -std=c11 -Wall -Werror -Wextra -Wno-gnu-folding-constant -Wno-sign-compare -Wno-unused-parameter -Wno-unused-variable -Wno-unused-but-set-variable -Wshadow LDLIBS = -lcrypt -lcs50 -lm EXE = foo SRCS = foo.c bar.c OBJS = $(SRCS:.c=.o) $(EXE): $(OBJS) $(CC) $(CFLAGS) -o $@ $(OBJS) $(LDLIBS) Usage ===== .. note:: To use these functions, make sure to include ``#include `` atop your file and compile with the ``-lcs50`` flag. .. type:: string Type representing a C string. Aliased to :code:`char *`. Example usage:: string s = "hello, world!"; .. function:: char get_char(const char *format, ...) :param format: the :func:`printf`-like format string used to display the prompt :param ...: values to be substituted into the format string a la :func:`printf` :returns: the :code:`char` equivalent to the line read from stdin, or :macro:`CHAR_MAX` on error Prompts user for a line of text from standard input and returns the equivalent :code:`char`; if text does not represent a single char, user is reprompted. Example usage:: #include #include int main(void) { // attempt to read character from stdin char c = get_char("Enter char: "); // ensure character was read successfully if (c == CHAR_MAX) { return 1; } char next = get_char("You just entered %c. Enter another char: ", c); if (next == CHAR_MAX) { return 1; } printf("The last char you entered was %c\n", next); } .. function:: double get_double(const char *format, ...) :param format: the :func:`printf`-like format string used to display the prompt :param ...: values to be substituted into the format string a la :func:`printf` :returns: the :code:`double` equivalent to the line read from stdin in [:macro:`DBL_MIN`, :macro:`DBL_MAX`), as precisely as possible, or :macro:`DBL_MAX` on error Prompts user for a line of text from standard input and returns the equivalent :code:`double`; if text does not represent a double or would cause overflow or underflow, user is reprompted. Example usage:: double divide_doubles(void) { // read double from stdin double d = get_double("Enter a double: "); // make sure we read one successfully if (d == DBL_MAX) { return DBL_MAX; } double e = get_double("What do you want to divide %lf by? ", d); // make sure we don't divide by zero if (e == DBL_MAX || e == 0.0) { return DBL_MAX; } return i / j; } .. function:: int get_int(const char *format, ...) :param format: the :func:`printf`-like format string used to display the prompt :param ...: values to be substituted into the format string a la :func:`printf` :returns: the :code:`int` equivalent to the line read from stdin in [:macro:`INT_MIN`, :macro:`INT_MAX`) or :macro:`INT_MAX` on error Prompts user for a line of text from standard input and returns the equivalent :code:`int`; if text does not represent an int or would cause overflow, user is reprompted. Example usage:: #include ... // Returns the sum of two ints read from stdin, or INT_MAX if there was an error. int add_ints(void) { // read int from stdin int i = get_int("Enter an int: "); // make sure we read one successfully if (i == INT_MAX) { return INT_MAX; } int j = get_int("What do you want to add %d to? ", i); if (j == INT_MAX) { return INT_MAX; } return i + j; } .. function:: float get_float(const char *format, ...) :param format: the :func:`printf`-like format string used to display the prompt :param ...: values to be substituted into the format string a la :func:`printf` :returns: the :code:`float` equivalent to the line read from stdin in [:macro:`FLT_MIN`, :macro:`FLT_MAX`), as precisely as possible, or :macro:`FLT_MAX` on error Prompts user for a line of text from standard input and returns the equivalent float; if text does not represent a float or would cause overflow or underflow, user is reprompted. Example usage:: // Returns the product of two floats, or FLT_MAX on error. float multiply_floats(void) { // read float from stdin float f = get_float("Enter a float: "); // make sure we read one successfully if (f == FLT_MAX) { return FLT_MAX; } float g = get_float("What do you want to multiply %f by? ", f); if (g == FLT_MAX) { return FLT_MAX; } return f * g; } .. function:: long get_long(const char *format, ...) :param format: the :func:`printf`-like format string used to display the prompt :param ...: values to be substituted into the format string a la :func:`printf` :returns: the :code:`long` equivalent to the line read from stdin in [:macro:`LONG_MIN`, :macro:`LONG_MAX`) or :macro:`LONG_MAX` on error Prompts user for a line of text from standard input and returns the equivalent :code:`long`; if text does not represent an int or would cause overflow, user is reprompted. Example usage:: #include ... // Returns the difference of two longs read from stdin, or LONG_MAX if there was an error. long subtract_longs(void) { // read long from stdin long i = get_long("Enter a long: "); // make sure we read one successfully if (i == LONG_MAX) { return LONG_MAX; } long j = get_long("What do you want to subtract from %ld? ", i); if (j == LONG_MAX) { return LONG_MAX; } return i - j; } .. function:: char *get_string(const char *format, ...) :param format: the :func:`printf`-like format string used to display the prompt :param ...: values to be substituted into the format string a la :func:`printf` :returns: the read line as a string sans line endings, or :macro:`NULL` on :macro:`EOF`. Prompts user for a line of text from standard input and returns it as a string (:code:`char *`), sans trailing line ending. Supports CR (``\r``), LF (``\n``), and CRLF (``\r\n``) as line endings. Stores string on heap, but library’s destructor frees memory on program’s exit. Example usage:: int main(void) { string s = get_string("Enter string: "); // ensure string was read if (s == NULL) { return 1; } string next = get_string("You just entered %s. Enter a new string: ", s); if (next == NULL) { return 1; } printf("Your last string was %s\n", next); } Troubleshooting =============== If when compiling your program, you see: ``/usr/bin/ld: cannot find -lcs50``: Add ``export LIBRARY_PATH=/usr/local/lib`` to your ``.bashrc``. ``fatal error: 'cs50.h' file not found``: Add ``export C_INCLUDE_PATH=/usr/local/include`` to your ``.bashrc``. ``cannot open shared object file: No such file or directory``: Add ``export LD_LIBRARY_PATH=/usr/local/lib`` to your ``.bashrc``.