Code Monkey home page Code Monkey logo

ohkimur / the-c-programming-language-2nd-edition-solutions Goto Github PK

View Code? Open in Web Editor NEW
462.0 11.0 109.0 698 KB

Solutions to the exercises in the book "The C Programming Language" (2nd edition) by Brian W. Kernighan and Dennis M. Ritchie. This book is also referred to as K&R.

License: MIT License

C 99.85% Makefile 0.15%
c c-language c-programming programming solutions solution programming-exercises programming-challenges language programming-language

the-c-programming-language-2nd-edition-solutions's Introduction

The C Programming Language 2nd Edition - Solutions

C/C++ CI

Introduction

The C Programming Language is a very popular book and sometimes people refer to it as K&R. The authors Brian W. Kernighan and Dennis M. Ritchie did a very good job of explaining the core concepts of programming. The focus of the book is the C programming language, however, the approach is general, so it can be extrapolated to other programming languages.

Each chapter of the book contains exercises that could be very helpful for a better understanding of the C language. The exercises are designed so that anybody can solve them with the knowledge acquired up to that exercise.

This repository contains the solutions to the exercises from each chapter of the book. These solutions are meant to be helpful for those who want to learn to program with the C language.

Environment

The source code is not tied up to an IDE, so any text editor will do the job. However, there are useful tasks and settings available for Visual Studio Code. For a better experience using this editor, the C/C++ extension provides some very helpful features specific to the C programming language.

Compilers

To be able to write programs in C, a compiler is required. There are many options available for each operating system.

macOS

The Clang compiler is a very nice choice when using macOS. It is available with Xcode Command Line Tools, which can be easily installed using the following command:

xcode-select --install

Linux

The GCC compiler is a very popular way to build C programs and it is a good choice when using Linux. Each distro has its own set of development tools that comes with the GCC compiler out of the box. The development tools can be installed with the following commands:

Ubuntu / Debian / Debian derivatives
sudo apt-get update
sudo apt-get install build-essential
Arch Linux
sudo pacman -Sy base-devel
Fedora
sudo yum update
sudo yum groupinstall "Development Tools" "Legacy Software Development"

Windows

Because Windows is not a Unix like operating system, Windows Subsystem for Linux (a.k.a. WSL) could be a very good approach when writing C programs. It provides a full Linux system that can make the programming experience much better. The official documentation has a pretty good explanation about how to install WSL.

MinGW Compiler Collection is another good alternative to obtain access to the GCC compiler on a Windows system. The official documentation shows how it can be installed step by step.

Debuggers

A debugger is a tool that can become very handy when trying to find out how a program works or why it doesn't. There are many times when the code will compile successfully because syntactically there are no problems. However, that doesn't mean there aren't logical problems. If that is the case it might be a very good idea to use a debugger.

A very good option is LLDB. It is the default debugger in Xcode on macOS and supports debugging C, Objective-C and C++. It converts debug information into Clang types so that it can leverage the Clang compiler infrastructure.

Another very popular option is GDB. It supports the following languages (in alphabetical order): Ada, Assembly, C, C++, D, Fortran, Go, Objective-C, OpenCL, Modula-2, Pascal, Rust.

the-c-programming-language-2nd-edition-solutions's People

Contributors

0xblurr avatar 4rturkania avatar aweebit avatar caldotdev avatar coed95 avatar cyberavater avatar danielcft avatar deadrobotdev avatar densel86 avatar duxv avatar everylittlefox avatar iliketohelp avatar illustrofia avatar kotoffski avatar marcelned avatar marcofilimon avatar metalbuild-mnbv avatar mtalhakrc avatar ohkimur avatar phaleth avatar pinguxx28 avatar pipboyguy avatar rfhits avatar sadeem-albir avatar saifeilee avatar shakenbeer avatar slackuj avatar tobiasjdcolvin avatar vladimirfokow avatar ye-chuan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

the-c-programming-language-2nd-edition-solutions's Issues

wrong result for 'escape sequence chain' - Exercise 1-12.

#include <stdio.h>
int main()
{
char c;
char last_char = -1;
while ((c = getchar()) != EOF) {
if((c==' ' || c=='\t' || c=='\n')) {
if(c != last_char) {
putchar('\n');
}
}
else {
putchar(c);
}
last_char=c;
}
return 0;
}

Imagine the input being \t

  1. c = ' '
  2. last_char = ' ' and c = '\t' here c != last_char evaluates to true and a newline would be printed to stdout although no new word started

e.g.

This \tTest

I think having additional checks would fix this. I just recently started learning C so I am potentially missing something here..

#include <stdio.h>

int main() {
  int c, prev;
  prev = EOF;

  while ((c = getchar()) != EOF) {
    if (c == ' ' || c == '\t' || c == '\n') {
      if (prev != ' ' && prev != '\t' && prev != '\n') {
        putchar('\n');
      }
    } else {
      putchar(c);
    }

    prev = c;
  }

  return 0;
}

Exercise 1_13

  1. Index out of bounds:
// Initialize the histogram array with 0
  int i;
  for (i = 0; i <= BUFFER; ++i) 
  {
    histogram[i] = 0;
  }
  1. Index out of bounds: -1, when input starts with spaces. Need add check like this:
        if (word_count_index > 0 && word_count_index <= BUFFER) // <-- add check
        {
          ++histogram[word_count_index - 1];

          if (histogram[word_count_index - 1] > max_word_count)
          {
            max_word_count = histogram[word_count_index - 1];
          }

          if (histogram_length < word_count_index - 1)
          {
            histogram_length = word_count_index - 1;
          }

          word_count_index = 0;
        }

Too many warnings

Describe the bug
There are way too many warnings at the moment. The majority are caused by the unsequenced usage of some variables.

To Reproduce
Steps to reproduce the behavior:

  1. Build the project with make
  2. See warnings

Expected behavior
It should compile without unintended warnings.

Screenshots
image

Additional context
Add any other context about the problem here.

Improve consistency

Is your feature request related to a problem? Please describe.
The exercise folder names doesn't use the same pattern.

Describe the solution you'd like
Make all exercise folders consistent.

Describe alternatives you've considered
Keep the current folder names.

Additional context
Solving this issue will improve the repo consistency.

Replace malloc with custom alloc

Is your feature request related to a problem? Please describe.
The malloc function was introduced only in chapter 6. Before that, a custom alloc function was proposed.

Describe the solution you'd like
Replace malloc with custom alloc usage before chapter 6.

Describe alternatives you've considered
It is also possible to keep the current malloc approach, but the suggested solution is more appropriate.

Additional context
Also, it is important to note that it might be a good idea to not use the getline function provided by std. A custom approach would be better before chapter 6.

1.20: solution is not correct

The exercise states that the program should replace input tabs with the proper number of spaces to reach the next tab stop. The tab stops are at fixed intervals (like every 4 columns or every 8) and the spaces should only fill up until the next stop, mimicking the behavior of actual tabs.

For example, given the input 'as[\t]df' where [\t] is a tab character, it should return 'as  df' with a tab stop of 4 (inserting two spaces, as there are already two characters) or 'as      df' with a tab stop of 8 (inserting six spaces), etc.

As currently implemented, this is not the case and the tab is simply substituted for 8 spaces.

Your solution for Chapter 1, Exercise 12 is redundant

Your solution for 1-12 seems to be redundant. Why not just do it this way?

#include <stdio.h>

#define OUT 0
#define IN 1

main() {
    int state = OUT;

    int c;
    while ((c = getchar()) != EOF) {
        if (c != ' ' && c != '\n' && c != '\t') {
            state = IN;
            putchar(c);
        } else if (state == IN) {
            state = OUT;
            putchar('\n');
        }
    }
}

Please correct me if I am wrong.

Exercises page numbering

Describe the bug
The page numbering of each exercise doesn't match the actual book.

To Reproduce
Steps to reproduce the behavior:

  1. Go to chapter_01/exercise_1_1/hello_world.c
  2. See the last comment label as Exercise Page

Expected behavior
The exercise page should 8 , according to the book.

Screenshots
If applicable, add screenshots to help explain your problem.

Additional context
Maybe a better idea will be to just remove all the comments related with the exercise page.

strindex of exercise_5_06 always return -1, if the char t[] is modified to "this"

Describe the bug
I changed the definition of char t[] = "first" to char t[] = "this", this should make the return value to 0, which is the first element of char s[].
However the return value is -1, since the while statement and the first if statement are not consistent.
After while (*s++ != '\0'), the first if statement must skip the first element of s[], which is the character t of "this".
Meanwhile, the increment of variable pos is premature. It cannot show the index 0 correctly also if the t[] appears at the first position of s[] as the same reason above.

To Reproduce
Steps to reproduce the behavior:

  1. Modify char t[] = "first" to char t[] = "this".
  2. Recompile this program.
  3. Result on terminal should be -1.

Expected behavior
t[] = "this" should be matched char s[] = "this is first string" and the return value is 0.

Additional context
Workaround is provided below.

while (*s != '\0')                   /* removed ++ for consistency with the next if */
  {                                 /* ++pos deleted and moved to new position in which after the completion of if
                                                                      (*s == *t) */
    if (*s == *t)
    {
      first = s;
      second = t;

      while (*first++ == *second++)
      {
        if (*second == '\0')
          return pos;
      }
    }
    pos++;                                 /* new position of pos increment */
    s++;                                      /* increment of s for next loop */
  }

Ex 1-24: Allows for closing brackets before they are opened

Describe the bug
A case like ")))(((" should not be considered balanced parenthesis.

To Reproduce
Steps to reproduce the behavior:

  1. Run the program with input ")))((("
  2. Program finishes with no reported errors

Expected behavior
Program should output "Error: unbalanced parentheses." or a more specific error.

Possible Solution
Stop iteration and return from checksyntax() once any of the bracket counts falls to negative.

In checksyntax(), replace

while (str[i] != '\0')

with

while (str[i] != '\0' && parentheses >= 0 && brackets >= 0 && braces >= 0)

Fix errors on exercises that do not compile successfully

When compiling each exercise with Make many warnings and errors appear. To make the CI workflow work properly these warnings and errors need to be fixed.

NOTE: Most likely the problem is caused by platform-specific dependencies.

Incomplete solution for 1.12

The current solution for exercise 1.12 seems to not handle the case, where a couple of spaces and tabs goes one by one. It will currently print a new line for each space or tab.
Something like that would work in such case:

#include <stdio.h>

#define OUT 0
#define IN 1

int main(void)
{
  char c;
  int state;

  state = OUT;
  while ((c = getchar()) != EOF)
  {
    if (c != ' ' && c != '\t' && c != '\n')
    {
      putchar(c);
      state = IN;
    }
    else if (state)
    {
      putchar('\n');
      state = OUT;
    }
  }
  
  return 0;
}

Ex 1-23: Division operator gets wrongly matched as an inline comment

Describe the bug
Expressions like "2 / 3" get treated as inline comments, so "/ 3" is removed from the final string leaving only "2".

To Reproduce
Steps to reproduce the behaviour:

  1. Run the program with any input featuring a single forward slash e.g. a simple expression like the one above.
  2. The output generated is not the desired one, having any division operation removed.

Expected behaviour
Everything after a single forward slash should not be considered a comment.

Possible fix
The conditional on line 77 is only really checking for one thing as the second part of the AND expression is exactly the same as the first.

      if (str[i] == '/' && str[i] == '/')

The second part should be str[i + 1] == '/' instead.

[bug] 1-19 reverse.c implementation is incorrect

Describe the bug
The line array can either ends with \n\0 or \c\0 where \c is an arbitrary character; depending on whether or not the length of input characters exceed the MAXLINE limit or not.

With that, there are 2 bugs that were overlooked.

(1) In reverse function, setting int i_back = length(line) - 2 is incorrect since it's incorrectly assuming that the line ends with \n\0 in every scenario.

(2) In the case where the length of input characters exceed MAXLINE, the while loop inside get_line will terminate early by i < max_line_len - 1 check. However, there are input characters still remain in the iostream that did not get flush out, which causes output to be incorrect.

To Reproduce
Set MAXLINE to 10 temporally so that it's easier to test.

Here is a copy of my terminal:

clalexni :: ~ » cc 1-19.c && ./a.out
0123456789 // input
7654321089 // incorrect output, expecting 876543210
  • Notice that the output starts at 7 instead of 8. In this case the input is 012345678\0; there is no \n as described in (1).
  • Notice that the output ends with 89. This is due to iostream not getting flushed as described in (2).

Another example:

clalexni :: ~ » cc 1-19.c&& ./a.out
012345678 // input
765432108 // incorrect output, expecting 876543210

Expected behavior

clalexni :: ~ » cc 1-19.c && ./a.out
0123456789 // input
876543210 // Expected output
clalexni :: ~ » cc 1-19.c&& ./a.out
012345678 // input
876543210 // Expected output

1-11: A newline does not mark the end of a word

If one of the expressions in an if-else are true, it will execute the associated statement(s) and skip the rest of the if-else.

if (c == '\n')
{
++nl;
}
else if (c == ' ' || c == '\n' || c == '\t')
{
state = OUT;
}
else if (state == OUT)
{
state = IN;
++nw;
}

If c is a newline character, Line 22 is true and Line 24 is executed. It then skips the rest of the if-else statment, including Lines 26-29. This means a newline does not set STATE to OUT.

In the book, Lines 22-25 are a separate if statement. Admittedly, they could have made it clearer by separating them with a line.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.