Unix

{"content":{"id":1050,"title":"Weekly Links - The Glorious Future Of Technology Edition","body":"\u003cul\u003e\r\n\u003cli\u003e\r\nNeed a book to read? Try \u003ca href=\"https://www.amazon.ca/Savaged-Systemd-Erotic-Unix-Encounter-ebook/dp/B075DYXZW1\"\u003eSavaged by Systemd: an Erotic Unix Encounter\u003c/a\u003e. Amazon also recommended 'git commit murder'.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\n\u003ca href=\"http://ishikawa-vision.org/vision/DPM/\"\u003eDynamic projection mapping\u003c/a\u003e is cooler than I could possibly describe in words.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\n\u003ca href=\"https://www.clickhole.com/yoda-is-supposed-to-be-just-a-normal-guy-1829478120\"\u003eYoda is supposed to be just a normal guy\u003c/a\u003e (by George Lucas).\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\nBritish TV in the 60s is completely inexplicable. \u003ca href=\"https://youtu.be/HdkixaxjZCM\"\u003eHere\u003c/a\u003e is couple elderly, enthusiastic men playing a wacky version of Bye Bye Blues on a mellotron.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\n\u003ca href=\"https://youtu.be/XXN9HjLJvdc\"\u003eThe first step to building an irl holodeck\u003c/a\u003e. It looks really pretty.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\nA JS library to generate \u003ca href=\"https://github.com/jwilber/roughViz\"\u003egraphs that look like they were cutely sketched by hand\u003c/a\u003e.\r\n\u003c/li\u003e\r\n\u003c/ul\u003e","publication_date":"2019-12-02T00:00:00.000Z","created_at":"2019-12-01T18:24:35.000Z","updated_at":"2019-12-01T18:36:58.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=weekly_links\"\u003eweekly_links\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=unix\"\u003eunix\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=linux\"\u003elinux\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=japan\"\u003ejapan\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=music\"\u003emusic\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=synthesizers\"\u003esynthesizers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=the_sixties\"\u003ethe_sixties\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=twentieth_century\"\u003etwentieth_century\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=javascript\"\u003ejavascript\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=bored_of_star_wars\"\u003ebored_of_star_wars\u003c/a\u003e"}

Weekly Links - The Glorious Future Of Technology Edition

{"content":{"id":979,"title":"Weekly Links - No Discernible Theme Edition","body":"\u003cul\u003e\r\n\u003cli\u003e\r\nMy vote for most dramatic Buzzfeed-style listicle? \u003ca href=\"https://lonerwolf.com/the-dark-night-of-the-soul/\"\u003e7 Omens That Herald the Dark Night of the Soul\u003c/a\u003e.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\nRecipe of the week: \u003ca href=\"https://www.mayoclinic.org/healthy-lifestyle/recipes/beef-enchiladas/rcp-20125121\"\u003eDon't die in your forties enchiladas\u003c/a\u003e.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\nInstead of posting Ancient Clickhole of the Week, I'm posting \u003ca href=\"https://www.theonion.com/banksy-painting-sells-for-record-12-2-million-1838855509\"\u003ethis\u003c/a\u003e because it made me laugh for ten minutes.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\n\u003ca href=\"https://leahneukirchen.org/blog/archive/2019/10/ken-thompson-s-unix-password.html\"\u003eKen Thompson's Unix password\u003c/a\u003e.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\nBrian Harvey, who has some truly amazing lectures and books online, \u003ca href=\"https://www.youtube.com/watch?v=hMloyp6NI4E\"\u003ehilariously explains why not to cheat\u003c/a\u003e.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\nIt turns out there's a big ol' online bird song database, so you can hear multiple examples of \u003ca href=\"https://www.xeno-canto.org/species/Heteroxenicus-stellatus\"\u003ebirds you'll probably never see or hear in person\u003c/a\u003e\r\n\u003c/li\u003e\r\n\u003c/ul\u003e","publication_date":"2019-10-13T00:00:00.000Z","created_at":"2019-10-12T20:35:18.000Z","updated_at":"2019-10-12T21:09:08.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=weekly_links\"\u003eweekly_links\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=food\"\u003efood\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=recipes\"\u003erecipes\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=sad\"\u003esad\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=hype\"\u003ehype\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=unix\"\u003eunix\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=news\"\u003enews\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=painting\"\u003epainting\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=birds\"\u003ebirds\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=animals\"\u003eanimals\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=mountains\"\u003emountains\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=music\"\u003emusic\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=ancient_clickhole\"\u003eancient_clickhole\u003c/a\u003e"}

Weekly Links - No Discernible Theme Edition

{"content":{"id":973,"title":"Weekly Links - Our Glorious Future Edition","body":"\u003cul\u003e\r\n\u003cli\u003e\r\nHave you heard of xlogo? If you use the X Window System, \u003ca href=\"https://simont.dreamwidth.org/242297.html\"\u003ethis is pretty neat\u003c/a\u003e.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\nAncient Clickhole of the week: \u003ca href=\"https://www.clickhole.com/these-elderly-people-s-stories-of-an-early-unsafe-vers-1825126728\"\u003eThese Elderly People’s Stories Of An Early, Unsafe Version Of Disneyland Will Terrify You\u003c/a\u003e.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\nC gets a lot of shit on the Internet, yet still persists and thrives. Your operating system is running C code right now, for example. For all its cruft and quirks, there are just certain niches that C fills which languages like Rust unequivocally do not, no matter how many think pieces are written. It also requires discipline and planning. Here's a lighthearted \u003ca href=\"https://www.lysator.liu.se/c/ten-commandments.html\"\u003eTen Commandments Of C\u003c/a\u003e.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\n\u003ca href=\"http://www.weirduniverse.net/blog/comments/rabbit\"\u003eIncredible short film\u003c/a\u003e.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\n\u003ca href=\"https://github.com/FoxDotBuild/woof-alert\"\u003eA dog collar that converts all barks to emails\u003c/a\u003e.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\nValve is a company that went from rich to ridonculously rich due to a side project that was the product of their bizarrely relaxed organizational model. Their \u003ca href=\"https://steamcdn-a.akamaihd.net/apps/valve/Valve_NewEmployeeHandbook.pdf\"\u003eemployee handbook\u003c/a\u003e is both interesting to read and very well-designed.\r\n\u003c/li\u003e\r\n\u003c/ul\u003e","publication_date":"2019-10-07T00:00:00.000Z","created_at":"2019-10-06T16:56:01.000Z","updated_at":"2019-10-06T17:38:27.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=weekly_links\"\u003eweekly_links\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=ancient_clickhole\"\u003eancient_clickhole\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=horror\"\u003ehorror\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=unix\"\u003eunix\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=linux\"\u003elinux\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=games\"\u003egames\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=design\"\u003edesign\u003c/a\u003e"}

Weekly Links - Our Glorious Future Edition

{"content":{"id":620,"title":"K\u0026R Solutions - 1.19","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e Write a function 'reverse(s)' that reverses the character string 's'. Use it to write a program that reverses the input one line at a time.\u003c/p\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e\u003c/p\u003e \r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e#include \u0026ltstdio.h\u0026gt\r\n\r\n// Using the same basic format is previous exercises and examples\r\n#define MAXLINE 1000\r\n\r\nint get_a_line(char s[], int lim);\r\nvoid reverse(char s[]);\r\n\r\nint main(void)\r\n{\r\n char line[MAXLINE];\r\n\r\n while ((get_a_line(line, MAXLINE)) \u003e 0) {\r\n reverse(line);\r\n printf(\"%s\", line);\r\n }\r\n\r\n return 0;\r\n}\r\n\r\nint get_a_line(char s[], int lim)\r\n{\r\n int c, i;\r\n\r\n for (i = 0; i \u003c lim-1 \u0026\u0026 (c=getchar()) != EOF \u0026\u0026 c != '\\n'; ++i) {\r\n s[i] = c;\r\n }\r\n\r\n if (c == '\\n') {\r\n s[i] = c;\r\n ++i;\r\n }\r\n s[i] = '\\0';\r\n\r\n return i;\r\n}\r\n\r\nvoid reverse(char s[])\r\n{\r\n char temp[MAXLINE];\r\n int i, j;\r\n\r\n i = 0;\r\n while ((temp[i] = s[i]) != '\\0')\r\n ++i;\r\n\r\n /* Reversing the newline looks ugly. In real life, we might strip that \r\n * char of whitespace before reversing it, as per the last lesson. */\r\n j = 0;\r\n --i;\r\n s[i--] = '\\n';\r\n while (i \u003e= 0) {\r\n s[i] = temp[j];\r\n ++j;\r\n --i;\r\n }\r\n}\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003e./reverse \r\nhi\r\nih\r\nsananab is a good blog\r\ngolb doog a si bananas\r\ntacocat\r\ntacocat\r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2019-04-29T00:00:00.000Z","created_at":"2019-03-30T17:08:48.000Z","updated_at":"2019-03-30T17:36:31.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=k%26r\"\u003ek\u0026amp;r\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=unix\"\u003eunix\u003c/a\u003e"}

K&R Solutions - 1.19

Q: Write a function 'reverse(s)' that reverses the character string 's'. Use it to write a program that reverses the input one line at a time.

A:

#include <stdio.h>

// Using the same basic format is previous exercises and examples
#define MAXLINE 1000

int get_a_line(char s[], int lim);
void reverse(char s[]);

int main(void)
{
  char line[MAXLINE];

  while ((get_a_line(line, MAXLINE)) > 0) {
    reverse(line);
    printf("%s", line);
  }

  return 0;
}

int get_a_line(char s[], int lim)
{
  int c, i;

  for (i = 0; i < lim-1 && (c=getchar()) != EOF && c != '\n'; ++i) {
    s[i] = c;
  }

  if (c == '\n') {
    s[i] = c;
    ++i;
  }
  s[i] = '\0';

  return i;
}

void reverse(char s[])
{
  char temp[MAXLINE];
  int i, j;

  i = 0;
  while ((temp[i] = s[i]) != '\0')
    ++i;

  /* Reversing the newline looks ugly. In real life, we might strip that 
   * char of whitespace before reversing it, as per the last lesson. */
  j = 0;
  --i;
  s[i--] = '\n';
  while (i >= 0) {
    s[i] = temp[j];
    ++j;
    --i;
  }
}
./reverse 
hi
ih
sananab is a good blog
golb doog a si bananas
tacocat
tacocat
{"content":{"id":557,"title":"K\u0026R Solutions - 1.18","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e Write a program to remove trailing blanks and tabs from each line of input, and to delete entirely blank lines.\u003c/p\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e\u003c/p\u003e \r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e#include \u0026ltstdio.h\u0026gt\r\n#define MAXLINE 1000\r\n\r\nint get_a_line(char s[], int lim);\r\nvoid chop(char s[], int lim);\r\n\r\nint main(void)\r\n{\r\n int len;\r\n char line[MAXLINE];\r\n\r\n while ((len = get_a_line(line, MAXLINE)) \u003e 0) {\r\n if (line[0] == '\\n') {\r\n // Nothing happens. We want to totally ignore strings that are just\r\n // newlines.\r\n } else {\r\n chop(line, MAXLINE);\r\n printf(\"%s\u003c---End Of String\\n\", line);\r\n }\r\n }\r\n\r\n return 0;\r\n}\r\n\r\n// Same as the previous exercise.\r\nint get_a_line(char s[], int lim) \r\n{\r\n int c, i;\r\n\r\n for (i = 0; i \u003c lim-1 \u0026\u0026 (c=getchar()) != EOF \u0026\u0026 c != '\\n'; ++i) {\r\n s[i] = c;\r\n }\r\n if (c == '\\n') {\r\n s[i] = c;\r\n ++i;\r\n }\r\n s[i] = '\\0';\r\n \r\n return i;\r\n}\r\n\r\nvoid chop(char s[], int lim) {\r\n int i;\r\n\r\n // First we find the end of the string.\r\n // Notice that the the resulting value of 'i' is the length of the string.\r\n // Also notice that in this context, we could have just moved to the newline\r\n // before the null char.\r\n for (i = 0; s[i] != '\\0'; ++i) {\r\n }\r\n\r\n // Now move backwards again, untill we find something that's not whitespace.\r\n for (i -= 1; s[i] == '\\t' || s[i] == '\\n' || s[i] == ' '; --i) {\r\n }\r\n\r\n // And we replace whatever is after with a null char.\r\n // We're replacing the newline, even though the exercise doesn't tell us\r\n // to get rid of it. This is becuse it makes the output easier to test.\r\n s[i+1] = '\\0';\r\n}\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003e./trimmer\r\nhi \t (enter)\r\nhi\u003c---End Of String\r\nhow are you?\t\t(enter)\t \r\nhow are \tyou?\u003c---End Of String\r\n(enter)\r\nthree little birds(enter)\r\nthree little birds\u003c---End Of String\r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2019-03-20T00:00:00.000Z","created_at":"2019-02-18T20:55:42.000Z","updated_at":"2019-02-18T22:31:22.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=k%26r\"\u003ek\u0026amp;r\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=unix\"\u003eunix\u003c/a\u003e"}

K&R Solutions - 1.18

Q: Write a program to remove trailing blanks and tabs from each line of input, and to delete entirely blank lines.

A:

#include <stdio.h>
#define MAXLINE 1000

int get_a_line(char s[], int lim);
void chop(char s[], int lim);

int main(void)
{
  int len;
  char line[MAXLINE];

  while ((len = get_a_line(line, MAXLINE)) > 0) {
    if (line[0] == '\n') {
      // Nothing happens. We want to totally ignore strings that are just
      // newlines.
    } else {
      chop(line, MAXLINE);
      printf("%s<---End Of String\n", line);
    }
  }

  return 0;
}

// Same as the previous exercise.
int get_a_line(char s[], int lim) 
{
  int c, i;

  for (i = 0; i < lim-1 && (c=getchar()) != EOF && c != '\n'; ++i) {
    s[i] = c;
  }
  if (c == '\n') {
    s[i] = c;
    ++i;
  }
  s[i] = '\0';
  
  return i;
}

void chop(char s[], int lim) {
  int i;

  // First we find the end of the string.
  // Notice that the the resulting value of 'i' is the length of the string.
  // Also notice that in this context, we could have just moved to the newline
  // before the null char.
  for (i = 0; s[i] != '\0'; ++i) {
  }

  // Now move backwards again, untill we find something that's not whitespace.
  for (i -= 1; s[i] == '\t' || s[i] == '\n' || s[i] == ' '; --i) {
  }

  // And we replace whatever is after with a null char.
  // We're replacing the newline, even though the exercise doesn't tell us
  // to get rid of it. This is becuse it makes the output easier to test.
  s[i+1] = '\0';
}
./trimmer
hi 	  (enter)
hi<---End Of String
how are         you?		(enter)	 
how are 	you?<---End Of String
(enter)
three little birds(enter)
three little birds<---End Of String
{"content":{"id":553,"title":"K\u0026R Solutions - 1.17","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e Write a program to print all input lines that are longer than 80 characters.\u003c/p\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e\u003c/p\u003e \r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e/* This is really a simpler version of the longest-line program: that already\r\n * has most of what we need. */\r\n#include \u0026ltstdio.h\u0026gt\r\n#define MAXLINE 1000\r\n\r\nint get_a_line(char s[], int lim);\r\n\r\n\r\nint main(void)\r\n{\r\n int len;\r\n char line[MAXLINE];\r\n\r\n while ((len = get_a_line(line, MAXLINE)) \u003e 0) {\r\n if (len \u003e 80) {\r\n printf(\"%s\", line);\r\n }\r\n }\r\n\r\n return 0;\r\n}\r\n\r\nint get_a_line(char s[], int lim) \r\n{\r\n int c, i;\r\n\r\n for (i = 0; i \u003c lim-1 \u0026\u0026 (c=getchar()) != EOF \u0026\u0026 c != '\\n'; ++i) {\r\n s[i] = c;\r\n }\r\n if (c == '\\n') {\r\n s[i] = c;\r\n ++i;\r\n }\r\n s[i] = '\\0';\r\n \r\n return i;\r\n}\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003eThis is a short sentence, which will not be repeated.\r\nThis, however, is a very, very, very long sentence, which will be repeated back by the program. \r\nThis, however, is a very, very, very long sentence, which will be repeated back by the program.\r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2019-03-18T00:00:00.000Z","created_at":"2019-02-15T21:16:49.000Z","updated_at":"2019-02-15T21:20:51.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=k%26r\"\u003ek\u0026amp;r\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=unix\"\u003eunix\u003c/a\u003e"}

K&R Solutions - 1.17

Q: Write a program to print all input lines that are longer than 80 characters.

A:

/* This is really a simpler version of the longest-line program: that already
 * has most of what we need. */
#include <stdio.h>
#define MAXLINE 1000

int get_a_line(char s[], int lim);


int main(void)
{
  int len;
  char line[MAXLINE];

  while ((len = get_a_line(line, MAXLINE)) > 0) {
    if (len > 80) {
      printf("%s", line);
    }
  }

  return 0;
}

int get_a_line(char s[], int lim) 
{
  int c, i;

  for (i = 0; i < lim-1 && (c=getchar()) != EOF && c != '\n'; ++i) {
    s[i] = c;
  }
  if (c == '\n') {
    s[i] = c;
    ++i;
  }
  s[i] = '\0';
  
  return i;
}
This is a short sentence, which will not be repeated.
This, however, is a very, very, very long sentence, which will be repeated back by the program.     
This, however, is a very, very, very long sentence, which will be repeated back by the program.
{"content":{"id":537,"title":"K\u0026R Solutions - 1.16","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e Revise the main routine of the longest-line program so it will correctly print the length of arbitrarily long input lines and as much as possible of the text.\u003c/p\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e\u003c/p\u003e \r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e...\r\nint main(void)\r\n{\r\n int len;\r\n int max;\r\n char line[MAXLINE];\r\n char longest[MAXLINE];\r\n\r\n max = 0;\r\n while ((len = get_a_line(line, MAXLINE)) \u003e 0) {\r\n if (len \u003e max) {\r\n max = len;\r\n copy(longest, line);\r\n }\r\n // Following tradition, we will be ignoring the null character that marks\r\n // the end of every string. The standard library function strlen() also\r\n // ignores null characters.\r\n printf(\"Length: %d\\n\", len - 1);\r\n printf(\"Line: %s\\n\", line);\r\n }\r\n if (max \u003e 0) {\r\n printf(\"%s\", longest);\r\n }\r\n\r\n return 0;\r\n}\r\n...\u003c/code\u003e\u003c/pre\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003ehi\r\nLength: 2\r\nLine: hi\r\n\r\nthere this is an \r\nLength: 16\r\nLine: there this is an\r\n\r\narbitrarily long string\r\nLength: 23\r\nLine: arbitrarily long string\r\n\r\nmoo \r\nLength: 3\r\nLine: moo\r\n\r\narbitrarily long string\r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2019-03-14T00:00:00.000Z","created_at":"2019-02-12T20:20:39.000Z","updated_at":"2019-02-12T20:44:42.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=k%26r\"\u003ek\u0026amp;r\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=unix\"\u003eunix\u003c/a\u003e"}

K&R Solutions - 1.16

Q: Revise the main routine of the longest-line program so it will correctly print the length of arbitrarily long input lines and as much as possible of the text.

A:

...
int main(void)
{
  int len;
  int max;
  char line[MAXLINE];
  char longest[MAXLINE];

  max = 0;
  while ((len = get_a_line(line, MAXLINE)) > 0) {
    if (len > max) {
      max = len;
      copy(longest, line);
    }
    // Following tradition, we will be ignoring the null character that marks
    // the end of every string. The standard library function strlen() also
    // ignores null characters.
    printf("Length: %d\n", len - 1);
    printf("Line: %s\n", line);
  }
  if (max > 0) {
    printf("%s", longest);
  }

  return 0;
}
...
hi
Length: 2
Line: hi

there this is an 
Length: 16
Line: there this is an

arbitrarily long string
Length: 23
Line: arbitrarily long string

moo 
Length: 3
Line: moo

arbitrarily long string
{"content":{"id":522,"title":"K\u0026R Solutions - 1.15","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e Rewrite the temperature conversion program of Section 1.2 to use a function for conversion.\u003c/p\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e\u003c/p\u003e \r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e// Compared with the original, this is much easier to read.\r\n\r\n#include \u0026ltstdio.h\u0026gt\r\n \r\nfloat fahrenheit_to_celsius (float fahr) {\r\n return (5.0/9.0) * (fahr-32.0);\r\n}\r\n\r\nint main(void) {\r\n int lower = 0;\r\n int upper = 300;\r\n int step = 20;\r\n float fahr = lower;\r\n\r\n while (fahr \u003c= upper) {\r\n printf(\"%3.0f %6.1f\\n\", fahr, fahrenheit_to_celsius(fahr));\r\n fahr = fahr + step;\r\n }\r\n\r\n return 0;\r\n}\u003c/code\u003e\u003c/pre\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003e 0 -17.8\r\n 20 -6.7\r\n 40 4.4\r\n 60 15.6\r\n 80 26.7\r\n100 37.8\r\n120 48.9\r\n140 60.0\r\n160 71.1\r\n180 82.2\r\n200 93.3\r\n220 104.4\r\n240 115.6\r\n260 126.7\r\n280 137.8\r\n300 148.9\r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2019-03-08T00:00:00.000Z","created_at":"2019-02-05T18:34:52.000Z","updated_at":"2019-02-12T20:19:30.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=k%26r\"\u003ek\u0026amp;r\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=unix\"\u003eunix\u003c/a\u003e"}

K&R Solutions - 1.15

Q: Rewrite the temperature conversion program of Section 1.2 to use a function for conversion.

A:

// Compared with the original, this is much easier to read.

#include <stdio.h>
  
float fahrenheit_to_celsius (float fahr) {
  return (5.0/9.0) * (fahr-32.0);
}

int main(void) {
  int lower = 0;
  int upper = 300;
  int step = 20;
  float fahr = lower;

  while (fahr <= upper) {
    printf("%3.0f %6.1f\n", fahr, fahrenheit_to_celsius(fahr));
    fahr = fahr + step;
  }

  return 0;
}
  0  -17.8
 20   -6.7
 40    4.4
 60   15.6
 80   26.7
100   37.8
120   48.9
140   60.0
160   71.1
180   82.2
200   93.3
220  104.4
240  115.6
260  126.7
280  137.8
300  148.9
{"content":{"id":532,"title":"19-02-10 Weekly Links","body":"\u003cul\u003e\r\n\u003cli\u003e\r\n\u003ca href=\"http://www.weirduniverse.net/blog/comments/showered_for_days\"\u003eThe Longest Shower\u003c/a\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\n\u003ca href=\"https://0x46.net/thoughts/2019/02/01/dotfile-madness/\"\u003eDon't put dotfiles in the home directory, please\u003c/a\u003e. This comes up once in a while, but everyone ignores it. I saw a proposal once to put them all in a folder like '.config', but humanity is to corrupt for something that beautiful to happen.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\nEveryone loves visualizing algorithms. \u003ca href=\"https://www.cs.usfca.edu/~galles/visualization/Algorithms.html\"\u003eHere are a bunch that aren't just the usual sort algorithms\u003c/a\u003e\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\nRelics are wacky. Interesting text on \u003ca href=\"https://ferrebeekeeper.wordpress.com/2019/01/31/the-votive-crown-of-oswald-at-hildesheim/\"\u003ethe votive crown of St. Oswald at Hildesheim\u003c/a\u003e.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\n\u003ca href=\"https://www.dwitter.net/\"\u003e\"Dwitter.net is a challenge to see what awesomeness you can create when limited to only 140 characters of javascript and a canvas\"\u003c/a\u003e. Extra points for having a random button.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\nI've never seen it, but look at this \u003ca href=\"https://youtu.be/-glpbcSDPNI\"\u003etrailer for a movie from 1936\u003c/a\u003e. The leading actress is the social worker from Beetlejuice.\r\n\u003c/li\u003e\r\n\u003c/ul\u003e","publication_date":"2019-02-10T00:00:00.000Z","created_at":"2019-02-09T17:02:55.000Z","updated_at":"2019-02-10T00:12:58.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=weekly_links\"\u003eweekly_links\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=water\"\u003ewater\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=linux\"\u003elinux\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=unix\"\u003eunix\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=history\"\u003ehistory\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=middle_ages\"\u003emiddle_ages\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=javascript\"\u003ejavascript\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=movies\"\u003emovies\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=beetlejuice\"\u003ebeetlejuice\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=religion\"\u003ereligion\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=hype\"\u003ehype\u003c/a\u003e"}

19-02-10 Weekly Links

{"content":{"id":357,"title":"K\u0026R Solutions - 1.14","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e Write a program to print a histogram of the frequencies of different characters\r\nin its input.\u003c/p\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e\u003c/p\u003e \r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e#include \u0026ltstdio.h\u0026gt\r\n\r\nint main(void) \r\n{\r\n int FREQUENCY_LENGTH = 256; // We'll just count all ASCII values. Why not?\r\n int frequencies[FREQUENCY_LENGTH];\r\n int i, j, c;\r\n int tally = 0;\r\n\r\n for (i = 0; i \u003c FREQUENCY_LENGTH; ++i) {\r\n frequencies[i] = 0;\r\n }\r\n\r\n // This part gets a lot more simple.\r\n while ((c = getchar()) != EOF) {\r\n ++frequencies[c];\r\n }\r\n\r\n printf(\"\\n\");\r\n printf(\"Character Frequencies\\n\");\r\n printf(\"---------------------\\n\");\r\n /* For the sake of brevity, we will only print visible characters.\r\n * The ASCII values for visible characters are all between 33 and 126,\r\n * a fact I pulled off www.asciitable.com\r\n */\r\n for (i = 33; i \u003c= 126; ++i) {\r\n printf(\"%c | \", i);\r\n\r\n for (j = 0; j \u003c frequencies[i]; ++j) {\r\n printf(\"-\");\r\n }\r\n\r\n printf(\"\\n\");\r\n }\r\n\r\n return 0;\r\n}\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003eAmerica! Land of my dreams, home of the Whopper!\r\n\r\n(ctrl+d)\r\n\r\nCharacter Frequencies\r\n---------------------\r\n! | --\r\n\" | \r\n# | \r\n$ | \r\n% | \r\n\u0026 | \r\n' | \r\n( | \r\n) | \r\n* | \r\n+ | \r\n, | -\r\n- | \r\n. | \r\n/ | \r\n0 | \r\n1 | \r\n2 | \r\n3 | \r\n4 | \r\n5 | \r\n6 | \r\n7 | \r\n8 | \r\n9 | \r\n: | \r\n; | \r\n\u003c | \r\n= | \r\n\u003e | \r\n? | \r\n@ | \r\nA | -\r\nB | \r\nC | \r\nD | \r\nE | \r\nF | \r\nG | \r\nH | \r\nI | \r\nJ | \r\nK | \r\nL | -\r\nM | \r\nN | \r\nO | \r\nP | \r\nQ | \r\nR | \r\nS | \r\nT | \r\nU | \r\nV | \r\nW | -\r\nX | \r\nY | \r\nZ | \r\n[ | \r\n\\ | \r\n] | \r\n^ | \r\n_ | \r\n` | \r\na | ---\r\nb | \r\nc | -\r\nd | --\r\ne | -----\r\nf | --\r\ng | \r\nh | ---\r\ni | -\r\nj | \r\nk | \r\nl | \r\nm | ----\r\nn | -\r\no | ----\r\np | --\r\nq | \r\nr | ---\r\ns | -\r\nt | -\r\nu | \r\nv | \r\nw | \r\nx | \r\ny | -\r\nz | \r\n{ | \r\n| | \r\n} | \r\n~ | \r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2018-11-06T01:00:00.000Z","created_at":"2018-11-05T23:37:34.000Z","updated_at":"2018-11-06T22:40:55.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=k%26r\"\u003ek\u0026amp;r\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=unix\"\u003eunix\u003c/a\u003e"}

K&R Solutions - 1.14

Q: Write a program to print a histogram of the frequencies of different characters in its input.

A:

#include <stdio.h>

int main(void) 
{
  int FREQUENCY_LENGTH = 256; // We'll just count all ASCII values. Why not?
  int frequencies[FREQUENCY_LENGTH];
  int i, j, c;
  int tally = 0;

  for (i = 0; i < FREQUENCY_LENGTH; ++i) {
    frequencies[i] = 0;
  }

  // This part gets a lot more simple.
  while ((c = getchar()) != EOF) {
    ++frequencies[c];
  }

  printf("\n");
  printf("Character Frequencies\n");
  printf("---------------------\n");
  /* For the sake of brevity, we will only print visible characters.
   * The ASCII values for visible characters are all between 33 and 126,
   * a fact I pulled off www.asciitable.com
   */
  for (i = 33; i <= 126; ++i) {
    printf("%c | ", i);

    for (j = 0; j < frequencies[i]; ++j) {
      printf("-");
    }

    printf("\n");
  }

  return 0;
}
America! Land of my dreams, home of the Whopper!

(ctrl+d)

Character Frequencies
---------------------
! | --
" | 
# | 
$ | 
% | 
& | 
' | 
( | 
) | 
* | 
+ | 
, | -
- | 
. | 
/ | 
0 | 
1 | 
2 | 
3 | 
4 | 
5 | 
6 | 
7 | 
8 | 
9 | 
: | 
; | 
< | 
= | 
> | 
? | 
@ | 
A | -
B | 
C | 
D | 
E | 
F | 
G | 
H | 
I | 
J | 
K | 
L | -
M | 
N | 
O | 
P | 
Q | 
R | 
S | 
T | 
U | 
V | 
W | -
X | 
Y | 
Z | 
[ | 
\ | 
] | 
^ | 
_ | 
` | 
a | ---
b | 
c | -
d | --
e | -----
f | --
g | 
h | ---
i | -
j | 
k | 
l | 
m | ----
n | -
o | ----
p | --
q | 
r | ---
s | -
t | -
u | 
v | 
w | 
x | 
y | -
z | 
{ | 
| | 
} | 
~ | 
{"content":{"id":318,"title":"K\u0026R Solutions - 1.13, Part 2","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e The same as part one, but vertical.\u003c/p\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e\u003c/p\u003e \r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e#include \u0026ltstdio.h\u0026gt\r\n\r\nint main(void) \r\n{\r\n int FREQUENCY_LENGTH = 10; \r\n int frequencies[FREQUENCY_LENGTH];\r\n int i, j, c;\r\n int tally = 0;\r\n int highest = 0;\r\n\r\n // We're tallying in the exact same way.\r\n for (i = 0; i \u003c FREQUENCY_LENGTH; ++i) {\r\n frequencies[i] = 0;\r\n }\r\n\r\n while ((c = getchar()) != EOF) {\r\n if (c == '.' || c == '\\n' || c == '\\t' || c == ' ' || c == ',') {\r\n if (tally \u003e FREQUENCY_LENGTH) {\r\n tally = FREQUENCY_LENGTH - 1;\r\n }\r\n ++frequencies[tally];\r\n tally = 0;\r\n } else {\r\n ++tally;\r\n }\r\n }\r\n\r\n /* First, we need the height of the highest bar.\r\n * At the top of the function, temp is set to zero. Normally a function\r\n * wouldn't be this long, but we haven't got to that part fo the book yet.\r\n */\r\n for (i = 0; i \u003c FREQUENCY_LENGTH; i++) {\r\n if (frequencies[i] \u003e highest) {\r\n highest = frequencies[i];\r\n }\r\n }\r\n\r\n /* Now we keep drawing the bars untill our 'highest' variable, and everything\r\n * in our tallies is zeroed out.\r\n */\r\n while (highest) {\r\n // Remember there are no zero-length words so we skip 0. Feel free to play\r\n // around with this, because some junk data is getting stored in\r\n // frequencies[0]. Why?\r\n for(i = 1; i \u003c FREQUENCY_LENGTH; i++) {\r\n if (frequencies[i] == highest) {\r\n printf(\" | \");\r\n frequencies[i]--;\r\n } else {\r\n printf(\" \");\r\n }\r\n }\r\n printf(\"\\n\");\r\n highest--;\r\n }\r\n\r\n /* Now we print a handy guide at the bottom.\r\n */\r\n for (i = 1; i \u003c FREQUENCY_LENGTH; i++) {\r\n printf(\"---\");\r\n }\r\n printf(\"-\\n\");\r\n for (i = 1; i \u003c FREQUENCY_LENGTH; i++) {\r\n if (i == FREQUENCY_LENGTH - 1) {\r\n printf(\" %d+\", i);\r\n } else {\r\n printf(\" %d \", i);\r\n }\r\n }\r\n printf(\"\\n\");\r\n\r\n return 0;\r\n}\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003eThe worst of misery\r\nIs when a nature framed for noblest things\r\nCondemns itself in youth to petty joys,\r\nAnd, sore athirst for air, breathes scanty life\r\nGasping from out the shallows.\r\nSupercalifragilisticexpialidocious.\r\n\r\n(ctrl+d)\r\n\r\n | \r\n | | \r\n | | | \r\n | | | | \r\n | | | | | | | \r\n | | | | | | | \r\n | | | | | | | | | \r\n----------------------------\r\n 1 2 3 4 5 6 7 8 9+ \r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cp\u003eYou can play around with this quite a bit. Removing one line and then changing one character, and we get a nice little graph:\u003c/p\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003e . \r\n . \r\n . \r\n . \r\n . . . \r\n \r\n . . \r\n----------------------------\r\n 1 2 3 4 5 6 7 8 9+ \r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2018-10-14T01:00:00.000Z","created_at":"2018-10-13T17:15:36.000Z","updated_at":"2018-10-13T19:47:42.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=k%26r\"\u003ek\u0026amp;r\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=unix\"\u003eunix\u003c/a\u003e"}

K&R Solutions - 1.13, Part 2

Q: The same as part one, but vertical.

A:

#include <stdio.h>

int main(void) 
{
  int FREQUENCY_LENGTH = 10; 
  int frequencies[FREQUENCY_LENGTH];
  int i, j, c;
  int tally = 0;
  int highest = 0;

  // We're tallying in the exact same way.
  for (i = 0; i < FREQUENCY_LENGTH; ++i) {
    frequencies[i] = 0;
  }

  while ((c = getchar()) != EOF) {
    if (c == '.' || c == '\n' || c == '\t' || c == ' ' || c == ',') {
      if (tally > FREQUENCY_LENGTH) {
        tally = FREQUENCY_LENGTH - 1;
      }
      ++frequencies[tally];
      tally = 0;
    } else {
      ++tally;
    }
  }

  /* First, we need the height of the highest bar.
  *  At the top of the function, temp is set to zero. Normally a function
  *  wouldn't be this long, but we haven't got to that part fo the book yet.
  */
  for (i = 0; i < FREQUENCY_LENGTH; i++) {
    if (frequencies[i] > highest) {
      highest = frequencies[i];
    }
  }

  /* Now we keep drawing the bars untill our 'highest' variable, and everything
   * in our tallies is zeroed out.
   */
  while (highest) {
    // Remember there are no zero-length words so we skip 0. Feel free to play
    // around with this, because some junk data is getting stored in
    // frequencies[0]. Why?
    for(i = 1; i < FREQUENCY_LENGTH; i++) {
      if (frequencies[i] == highest) {
        printf(" | ");
        frequencies[i]--;
      } else {
        printf("   ");
      }
    }
    printf("\n");
    highest--;
  }

  /* Now we print a handy guide at the bottom.
   */
  for (i = 1; i < FREQUENCY_LENGTH; i++) {
    printf("---");
  }
  printf("-\n");
  for (i = 1; i < FREQUENCY_LENGTH; i++) {
    if (i == FREQUENCY_LENGTH - 1) {
      printf(" %d+", i);
    } else {
      printf(" %d ", i);
    }
  }
  printf("\n");

  return 0;
}
The worst of misery
Is when a nature framed for noblest things
Condemns itself in youth to petty joys,
And, sore athirst for air, breathes scanty life
Gasping from out the shallows.
Supercalifragilisticexpialidocious.

(ctrl+d)

       |                   
       |        |          
       |  |     |          
    |  |  |     |          
    |  |  |  |  |  |  |    
    |  |  |  |  |  |  |    
 |  |  |  |  |  |  |  |  | 
----------------------------
 1  2  3  4  5  6  7  8  9+ 

You can play around with this quite a bit. Removing one line and then changing one character, and we get a nice little graph:

       .                   
                .          
          .                
    .                      
             .     .  .    
                           
 .                       . 
----------------------------
 1  2  3  4  5  6  7  8  9+ 
{"content":{"id":310,"title":"K\u0026R Solutions - 1.13, Part 1","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e Write a program to print a histogram of the lengths of words in its input. It is easy to draw the histogram with the bars horizontal; a vertical orientation is more challenging.\u003c/p\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e\u003c/p\u003e \r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e#include \u0026ltstdio.h\u0026gt\r\n\r\nint main(void) \r\n{\r\n /* Because of screen space and the limitations of terminal output, words\r\n * longer than ten are going to be categorized as greater than 10.\r\n * \r\n * In this model, frequencies[0] is a one-character word, and frequencies[1]\r\n * is a two-character word. This 'off-by-one' behaviour seems unintuitive\r\n * and certainly leads to bugs, but there is a very good, low-level reason\r\n * that becomes very obvious when you learn a bit of assembly. You could find\r\n * a work-around (like leaving frequencies[0] unused), but it's better to get\r\n * use to thinking of things as starting with the 0th element because, in the\r\n * long run, there's no real avoiding it in programming.\r\n */\r\n int FREQUENCY_LENGTH = 10; \r\n // It's tradition to capitalize this we won't be changing.\r\n int frequencies[FREQUENCY_LENGTH];\r\n int i, j, c;\r\n int tally = 0;\r\n\r\n /* Initialize all frequencies to 0 */\r\n /* The book hasn't told us this yet, but the easiest way to initiate all\r\n * elements in an array to 0 is simply to go:\r\n * int frequencies[10] = {0};\r\n * BUT doing it with what the book has tought us gives us a better feel for\r\n * the way that arrays work.\r\n */\r\n for (i = 0; i \u003c FREQUENCY_LENGTH; ++i) {\r\n frequencies[i] = 0;\r\n }\r\n\r\n /* Count word-length frequencies */\r\n /* I'm missing colons and semi-colons here for the sake of space, but you get\r\n * the drift. In a professional setting, you would probably want to create \r\n * a separate subroutine called is_word_barrier() to keep your code cleaner\r\n * and more readable, but we haven't got to that part of the book yet. \r\n */\r\n while ((c = getchar()) != EOF) {\r\n if (c == '.' || c == '\\n' || c == '\\t' || c == ' ' || c == ',') {\r\n if (tally \u003e FREQUENCY_LENGTH) {\r\n tally = FREQUENCY_LENGTH - 1;\r\n }\r\n ++frequencies[tally];\r\n tally = 0;\r\n } else {\r\n ++tally;\r\n }\r\n }\r\n\r\n /* Print horizontal-barred histogram */\r\n printf(\"\\n\");\r\n printf(\"Word Frequencies: Horizontal\\n\");\r\n printf(\"----------------------------\\n\");\r\n for (i = 0; i \u003c FREQUENCY_LENGTH; ++i) {\r\n if (i != 0) {\r\n if (i == FREQUENCY_LENGTH - 1) {\r\n printf(\"%3d+ | \", i);\r\n } else {\r\n printf(\"%3d | \", i);\r\n } \r\n for (j = 0; j \u003c frequencies[i]; ++j) {\r\n printf(\"-\");\r\n }\r\n printf(\"\\n\");\r\n }\r\n }\r\n\r\n return 0;\r\n}\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cpre\u003e\u003ccode class=\"lisp\"\u003eThe worst of misery\r\nIs when a nature framed for noblest things\r\nCondemns itself in youth to petty joys,\r\nAnd, sore athirst for air, breathes scanty life\r\nGasping from out the shallows.\r\nSupercalifragilisticexpialidocious.\r\n\r\n(ctrl+d)\r\n\r\nWord Frequencies: Horizontal\r\n----------------------------\r\n 1 | -\r\n 2 | ----\r\n 3 | -------\r\n 4 | -----\r\n 5 | ---\r\n 6 | ------\r\n 7 | ---\r\n 8 | ---\r\n 9+ | -\r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2018-10-10T01:00:00.000Z","created_at":"2018-10-09T16:32:55.000Z","updated_at":"2018-10-10T01:27:10.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=k%26r\"\u003ek\u0026amp;r\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=unix\"\u003eunix\u003c/a\u003e"}

K&R Solutions - 1.13, Part 1

Q: Write a program to print a histogram of the lengths of words in its input. It is easy to draw the histogram with the bars horizontal; a vertical orientation is more challenging.

A:

#include <stdio.h>

int main(void) 
{
  /* Because of screen space and the limitations of terminal output, words
   * longer than ten are going to be categorized as greater than 10.
   * 
   * In this model, frequencies[0] is a one-character word, and frequencies[1]
   * is a two-character word. This 'off-by-one' behaviour seems unintuitive
   * and certainly leads to bugs, but there is a very good, low-level reason
   * that becomes very obvious when you learn a bit of assembly. You could find
   * a work-around (like leaving frequencies[0] unused), but it's better to get
   * use to thinking of things as starting with the 0th element because, in the
   * long run, there's no real avoiding it in programming.
   */
  int FREQUENCY_LENGTH = 10; 
  // It's tradition to capitalize this we won't be changing.
  int frequencies[FREQUENCY_LENGTH];
  int i, j, c;
  int tally = 0;

  /* Initialize all frequencies to 0 */
  /* The book hasn't told us this yet, but the easiest way to initiate all
   * elements in an array to 0 is simply to go:
   * int frequencies[10] = {0};
   * BUT doing it with what the book has tought us gives us a better feel for
   * the way that arrays work.
   */
  for (i = 0; i < FREQUENCY_LENGTH; ++i) {
    frequencies[i] = 0;
  }

  /* Count word-length frequencies */
  /* I'm missing colons and semi-colons here for the sake of space, but you get
   * the drift. In a professional setting, you would probably want to create 
   * a separate subroutine called is_word_barrier() to keep your code cleaner
   * and more readable, but we haven't got to that part of the book yet. 
   */
  while ((c = getchar()) != EOF) {
    if (c == '.' || c == '\n' || c == '\t' || c == ' ' || c == ',') {
      if (tally > FREQUENCY_LENGTH) {
        tally = FREQUENCY_LENGTH - 1;
      }
      ++frequencies[tally];
      tally = 0;
    } else {
      ++tally;
    }
  }

  /* Print horizontal-barred histogram */
  printf("\n");
  printf("Word Frequencies: Horizontal\n");
  printf("----------------------------\n");
  for (i = 0; i < FREQUENCY_LENGTH; ++i) {
    if (i != 0) {
      if (i == FREQUENCY_LENGTH - 1) {
        printf("%3d+ | ", i);
      } else {
        printf("%3d  | ", i);
      } 
      for (j = 0; j < frequencies[i]; ++j) {
        printf("-");
      }
      printf("\n");
    }
  }

  return 0;
}
The worst of misery
Is when a nature framed for noblest things
Condemns itself in youth to petty joys,
And, sore athirst for air, breathes scanty life
Gasping from out the shallows.
Supercalifragilisticexpialidocious.

(ctrl+d)

Word Frequencies: Horizontal
----------------------------
  1  | -
  2  | ----
  3  | -------
  4  | -----
  5  | ---
  6  | ------
  7  | ---
  8  | ---
  9+ | -
{"content":{"id":301,"title":"K\u0026R Solutions - 1.12","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e Write a program that prints its input one word per line.\u003c/p\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e\u003c/p\u003e \r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e#include \u0026ltstdio.h\u0026gt\r\n\r\nint main(void)\r\n{\r\n char c;\r\n\r\n while ((c = getchar()) != EOF) {\r\n if (c == '\\t' || c == '\\n' || c == ' ') {\r\n printf(\"\\n\");\r\n } else {\r\n putchar(c);\r\n }\r\n }\r\n\r\n return 0;\r\n}\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e\u0026gt muh muh muh moo cows\r\nmuh\r\nmuh\r\nmuh\r\nmoo\r\ncows\r\n\u003c/code\u003e\u003c/pre\u003e","publication_date":"2018-10-05T01:00:00.000Z","created_at":"2018-10-04T23:41:25.000Z","updated_at":"2018-10-05T03:44:39.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=k%26r\"\u003ek\u0026amp;r\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=unix\"\u003eunix\u003c/a\u003e"}

K&R Solutions - 1.12

Q: Write a program that prints its input one word per line.

A:

#include <stdio.h>

int main(void)
{
  char c;

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

  return 0;
}
> muh muh muh     moo cows
muh
muh
muh
moo
cows
{"content":{"id":270,"title":"18-09-16 Weekly Links","body":"\u003cimg src=\"/uploads/d1.jpg\" class=\"card-image\"\u003e\r\n\u003cul\u003e\r\n\u003cli\u003e\r\n\u003ca href=\"https://i.imgur.com/bm2X9l7.gifv\" target=\"_blank\"\u003eMaking a pear picker\u003c/a\u003e.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\nA pretty neat little article about the Unix \u003ca href=\"https://akr.am/blog/posts/today-in-history-brought-to-you-by-unix\" target=\"_blank\"\u003ecalendar\u003c/a\u003e program and its history.\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\nThis \u003ca href=\"http://taotajima.jp\" target=\"_blank\"\u003efancy site for a Japanese film director\u003c/a\u003e puts all other fancy sites I've seen to shame. In spite of how much it does, it runs pretty fast. Nowadays, the industry considers fast sites to be unprofessional...\r\n\u003c/li\u003e\r\n\u003cli\u003e\r\n\u003ca href=\"https://i.imgur.com/4eDorpC.gifv\" target=\"_blank\"\u003eHey!\u003c/a\u003e\r\n\u003c/li\u003e\r\n\u003c/ul\u003e","publication_date":"2018-09-16T00:00:00.000Z","created_at":"2018-09-14T14:08:40.000Z","updated_at":"2020-08-05T16:54:16.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=weekly_links\"\u003eweekly_links\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=china\"\u003echina\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=japan\"\u003ejapan\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=unix\"\u003eunix\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=trivia\"\u003etrivia\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=realism\"\u003erealism\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=france\"\u003efrance\u003c/a\u003e"}

18-09-16 Weekly Links

{"content":{"id":138,"title":"K\u0026R Solutions - 1.11","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e How would you test the word count program? What kinds of input are most\r\nlikely to uncover bugs if there are any?\u003c/p\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e There is no perfect answer to this kind of question. Writing good test is really a matter of experience. Part of the reason all programs have bugs is that even the best test writers can't anticipate all the wild ways a program will be used by other people. Nevertheless, writing good tests is a good skill to develop, as you can filter out about 99% of potential bugs that way, and prevent unexpected behaviour when you make small changes to large programs.\u003c/p\u003e\r\n\u003cp\u003eThe first thing I would do is test it with no characters at all, hoping for '0 0 0'. Next, test it with one word, then with one tab, then with one newline. Then a tab and a newline, then a newline and a tab... you probably don't need the full 16, but instinct tells me that starting input with white space might cause problems. After that, a few short strings like 'two words' will cover the basics. Of course, in real life, I \u003ci\u003ehope\u003c/i\u003e I can write such thorough tests.\u003c/p\u003e\r\n\u003cp\u003eThat might seem like a lot but if you write a test once, you get the peace of mind forever.\u003c/p\u003e","publication_date":"2018-06-30T18:00:00.000Z","created_at":"2018-06-23T17:23:03.000Z","updated_at":"2020-10-18T17:09:31.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=k%26r\"\u003ek\u0026amp;r\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=unix\"\u003eunix\u003c/a\u003e"}

K&R Solutions - 1.11

Q: How would you test the word count program? What kinds of input are most likely to uncover bugs if there are any?

A: There is no perfect answer to this kind of question. Writing good test is really a matter of experience. Part of the reason all programs have bugs is that even the best test writers can't anticipate all the wild ways a program will be used by other people. Nevertheless, writing good tests is a good skill to develop, as you can filter out about 99% of potential bugs that way, and prevent unexpected behaviour when you make small changes to large programs.

The first thing I would do is test it with no characters at all, hoping for '0 0 0'. Next, test it with one word, then with one tab, then with one newline. Then a tab and a newline, then a newline and a tab... you probably don't need the full 16, but instinct tells me that starting input with white space might cause problems. After that, a few short strings like 'two words' will cover the basics. Of course, in real life, I hope I can write such thorough tests.

That might seem like a lot but if you write a test once, you get the peace of mind forever.

{"content":{"id":137,"title":"K\u0026R Solutions - 1.10","body":"\u003cp\u003e\u003cb\u003eQ:\u003c/b\u003e Write a program to copy its input to its output, replacing each tab by \\t , each\r\nbackspace by \\b , and each backslash by \\\\ . This makes tabs and backspaces visible in an\r\nunambiguous way.\u003c/p\u003e\r\n\u003cp\u003e\u003cb\u003eA:\u003c/b\u003e\u003c/p\u003e \r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003e#include \u0026ltstdio.h\u0026gt\r\n\r\nint main(void)\r\n{\r\n char c;\r\n\r\n while ((c = getchar()) != EOF) {\r\n if (c == '\\t') {\r\n printf(\"\\\\t\");\r\n } else if (c == '\\b') {\r\n printf(\"\\\\b\");\r\n } else if (c == '\\\\') {\r\n printf(\"\\\\\\\\\");\r\n } else {\r\n putchar(c);\r\n }\r\n }\r\n\r\n return 0;\r\n}\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cpre\u003e\u003ccode class=\"cpp\"\u003etab\texample\r\ntab\\texample\r\n\\ example\r\n\\\\ example\r\nBackspace example doesn't work!\r\nBackspace example doesn't work!\r\n\u003c/code\u003e\u003c/pre\u003e\r\n\u003cimg src=\"/uploads/56.jpg\" class=\"card-image\"\u003e\r\n\u003cdiv class=\"card-image-caption\" style=\"color: black\"\u003eDenis Richie standing by the computer where he invented C\u003c/div\u003e\r\n\u003cp\u003e\u003cb\u003eNotes:\u003c/b\u003e\u003c/p\u003e\r\n\u003cp\u003eYour terminal emulator takes care of automatically backspacing for you, so the final part of this exercise is long-obsolete.\u003c/p\u003e\r\n\u003cp\u003eExplicit backspaces were a problem Richie dealt with when they were developing C and Unix in the 70s. Their office computer didn't have a monitor, only a printer (teletype) which didn't show the characters you had already backspaced (in fact, it added the whitespace \\b which was applied as a character deletion only after you saved the line); you just had to try to keep track of your corrections in your head.\u003c/p\u003e\r\n\u003cp\u003eAccording to people around back then, the reason C tends to be so terse, and keywords/variable names tended to be so short, is that backspacing was so frustratingly difficult to keep track of that they wanted to keep the lines as short as possible. This is contrary to the modern style, where clear names are considered extremely important.\u003c/p\u003e\r\n\u003cp\u003eIt's pretty easy (and fun) to run Unix 6 on an emulator, to get a bit of a taste of what these people were dealing with back then. After trying to write a few small programs, you'll get a pretty good feeling for why old Unix culture discouraged long names.\u003c/p\u003e","publication_date":"2018-06-30T15:00:00.000Z","created_at":"2018-06-23T03:55:54.000Z","updated_at":"2020-10-21T18:14:00.000Z","user_id":1,"rating":null},"tags":"\u003ca class=\"changeable-title\" href=\"/q?tag=k%26r\"\u003ek\u0026amp;r\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=programming\"\u003eprogramming\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=answers\"\u003eanswers\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=c\"\u003ec\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=unix\"\u003eunix\u003c/a\u003e \u003ca class=\"changeable-title\" href=\"/q?tag=computer_history\"\u003ecomputer_history\u003c/a\u003e"}

K&R Solutions - 1.10

Q: Write a program to copy its input to its output, replacing each tab by \t , each backspace by \b , and each backslash by \\ . This makes tabs and backspaces visible in an unambiguous way.

A:

#include <stdio.h>

int main(void)
{
  char c;

  while ((c = getchar()) != EOF) {
    if (c == '\t') {
      printf("\\t");
    } else if (c == '\b') {
      printf("\\b");
    } else if (c == '\\') {
      printf("\\\\");
    } else {
      putchar(c);
    }
  }

  return 0;
}
tab	example
tab\texample
\ example
\\ example
Backspace example doesn't work!
Backspace example doesn't work!
Denis Richie standing by the computer where he invented C

Notes:

Your terminal emulator takes care of automatically backspacing for you, so the final part of this exercise is long-obsolete.

Explicit backspaces were a problem Richie dealt with when they were developing C and Unix in the 70s. Their office computer didn't have a monitor, only a printer (teletype) which didn't show the characters you had already backspaced (in fact, it added the whitespace \b which was applied as a character deletion only after you saved the line); you just had to try to keep track of your corrections in your head.

According to people around back then, the reason C tends to be so terse, and keywords/variable names tended to be so short, is that backspacing was so frustratingly difficult to keep track of that they wanted to keep the lines as short as possible. This is contrary to the modern style, where clear names are considered extremely important.

It's pretty easy (and fun) to run Unix 6 on an emulator, to get a bit of a taste of what these people were dealing with back then. After trying to write a few small programs, you'll get a pretty good feeling for why old Unix culture discouraged long names.