Day 66: Passing Input to C Programs In Shell

I finished writing out the example C program I wanted to test. BUT I had no idea how to pass an external file to the program. I had some ideas from writing shell scripts and using shell commands but I hadn’t dealt with passing file inputs for a while. After a bit of chaotic searching I found two methods to pass in the input I wanted and I got to review some of my notes on working within the shell. It felt great and reminded how useful it is.

TLDR;

Okay, so here are the highlights of what I did:

  • Continued to work on the “Technical Questions” section of the book “Cracking the Coding Interview” by Gayle Laakmann McDowell. Within that, I continued my work on Tree data structures. Started trying to replicate the example pretty print functions provided in the article I am reading through. I had to pause working on my Horizontal Pretty Print project to better understand string/character manipulation in the C programming language. It is a bit of a detour but I imagine it will pay itself off in the long run. Continued reading the C programming book called “The C Programming Language” by Brian W. Kernighan and Dennis M. Ritchie. I finished copying the example code and got the programming running correctly. I had some hiccups with the function names in the example clashing with existing functions from the <stdio.h> library. It took me a while to understand what the error prompt was telling me and making the appropriate name changes to get things going. The program deals with really only one char array at a time but it was a nice step towards handling multi-dimensional char arrays.
  • I continued reading through chapter 6 of the book “Eloquent JavaScript” by Marjin Haverbeke. I am starting to read the book to help cover some insecurities I have about my knowledge of the language. I learned JavaScript on the fly through projects and YouTube videos. There are some core questions about the language that I don’t think I can answer, so hopefully this will help. I was reviewing my notes on classes today. In Chapter 6 the topic is covered alongside prototypes but because I had previously confused what prototypes really were I didn’t understand how classes built off of them. Honestly feels great to understand that classes are just an abstraction to simplify the syntax and reading of JavaScript’s informal OOP implementation. Everything is really just about prototypes. Now I know and can move on slowly. Every piece in this chapter feels really important for me to understand key concepts in React that I may have missed before.

/*
 * Example from: Section 1.9 Character Arrays - C Programming Language (Benjamin...
 *
 * This program is intended to read a set of text lines and print the longest line.
 * */

#include <stdio.h>
#define MAXLINE 1000        // maximum input line size

// Function prototypes
int getTextLine(char line[], int maxline);
void copy(char to[], char from[]);


// Print the longest input line
int main(){
  int len;
  int max;
  char line[MAXLINE];
  char longest[MAXLINE];

  max = 0;

  while((len = getTextLine(line, MAXLINE)) > 0)
    if(len > max){
      max = len;
      copy(longest, line);
    }

  if(max > 0)
    printf("%s", longest);

  return 0;
}


// getTextLine: read a line from input and store it in s, return length
int getTextLine(char line[], int maxline){
  int c, i;

  for(i=0; i < maxline-1 && (c=getchar()) != EOF && c != '\n'; ++i)
    line[i] = c;

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

  line[i] = '\0';
  return i;
}

// copy: copy 'from' into 'to'; assume 'to' is big enough
void copy(char to[], char from[]){
  int i = 0;
  while((to[i] = from[i]) != '\0')
    ++i;
}

How to run the program Afte Compiling

The program needs some input to run (There is no error checking for no input LOL). Anyways here are some examples on how to pass it some input. I found three methods.

# Example with the Piping method

cat TEXT_FILE | print_longest_line.exe

# Program Outputs: My name is jamal
# Example with the file input redirection method

print_longest_line.exe < TEXT_FILE

# Program Outputs: My name is jamal
# Example with the Here Documents Redirection

print_longest_line.exe << EOF
Hello
World
My name is Jamal
EOF

# Program Outputs: My name is jamal

JavaScript Class Notes:

The prototype system in JavaScript can be interpreted as a somewhat informal take on classes in object-oriented programming (As mentioned above). A class defines the shape for a type of object along with what methods and properties it has. An object of that shape would be called an instance of the class. Basically, there is no official class system in JavaScript that is like what would be found in other languages like Java or C++. The use of prototypes is how JavaScript attempts to represent that system.

Prototypes are helpful for defining properties that are shared amongst all instances of a class e.g. methods for the class. Properties that differ per instance need to be stored directly in the objects themselves because of limitations in the language – new versions might rectify this. e.g. (Rabbit type from the example above). In older versions of JavaScript the prototype was only capable of holding methods, not properties – hence why these two aspects are performed separately.

In JavaScript the fundamental way to produce an instance of a given class is to build an object that derives from the desired prototype i.e. (It has all the methods that should be shared by all instances of the class) and we are able to give it the properties that each instance of this class are meant to have. At the basic level this is what it looks like:

// Prototype type declaration for all Rabbits (Rabbit Class)

let protoRabbit = {
  // shorthand syntax for writing a method for an object.
  speak(line) {
    console.log(`The ${this.type} rabbit says '${line}'`);
  },
};

// Informal "Constructor" function to build new Rabbit Objects from
// the Rabbit prototype (class) and setting the unique instance
// properties (e.g. type)

function makeRabbit(type) {
  let rabbit = Object.create(protoRabbit);
  rabbit.type = type;
  return rabbit;
}

Again, in the example above the “class” is represented by the prototype not some actual “class” like in Java or C++. Our makeRabbit function produces new instances that are always given this same prototype. So that is the way classes and class instances (objects of a class) are informally implemented in JavaScript. Now we can look at ways this is abstracted through syntax and conventions.

JavaScript provides a way to make defining this type of function easier. If you put the keyword new in front of the function call, the function itself will be treated as a constructor. We can then add the prototype (class) properties to the Function prototype itself to ensure all objects produced from this constructor function share the same prototype properties. This means that an object with the right prototype is automatically constructed, then it’s unique properties are bound to the instance itself through the this property. This happens all in one function, and the instance is finally, automatically returned at the end of the function. This is far more convenient than our manual method above. Also, By convention all Class Constructor functions are given a Capital Letter to start.

function Rabbit(type) {
  this.type = type;
}
Rabbit.prototype.speak = function (line) {
  console.log(`The ${this.type} rabbit says '${line}'`);
};

let weirdRabbit = new Rabbit("weird");

Constructors (in fact all functions [but NOT OBJECTS] ) automatically get a property named prototype, which by default holds a plain, empty object that ultimately derives from Object.prototype. You can overwrite it with a new object if you want. Or you can add properties to the existing object, as the example does. This is the prototype that will be used for all instances produced from this constructor function using the new keyword syntax. As mentioned above, by convention, the names of constructors are capitalized so that they can easily be distinguished from other functions.

It is important to understand the distinction between the way a prototype is associated with a constructor (through its prototype property) and the way objects have a prototype (which can be found with Object.getPrototypeOf). The actual prototype of a constructor is Function.prototype since constructors are functions. The Constructor’s prototype property holds the prototype used for instances built through it.

console.log(Object.getPrototypeOf(Rabbit) == Function.prototype);
// → true

console.log(Object.getPrototypeOf(weirdRabbit) == Rabbit.prototype);
// → true

Question: What would happen if we built an instance from the class before setting the prototype properties we want and then later setting the prototype properties. Would it reflect the old blank prototype or the new one. Basically, I am wondering if prototypes are dynamic and reference one source or if each instance has it’s own copy produced from the environment at the time of it’s construction.

Answer: The prototype of the instance would have access to the updated version of the prototype not the one at the time the object was instantiated from the class. So it would seem that all changes to the prototype (class) will be reflected in all instances of that class (prototype) regardless of the time that the instance was constructed. Here is the example using the example protoRabbit

let coldRabbit = makeRabbit("cold");
console.log(Object.getPrototypeOf(coldRabbit));
// -> { speak: [Function: speak] }

protoRabbit.yell = function yell(line) {
  console.log(`The ${this.type} rabbit yells '${line}'!!`);
};

coldRabbit.yell("It's cold outside");
// -> The cold rabbit yells 'It's cold outside'!!

console.log(Object.getPrototypeOf(coldRabbit));
// -> { speak: [Function: speak], yell: [Function: yell] }

Conclusion

That’s all for today. This is my sixth round of the “#100daysofcode” challenge. I will be continuing my work from round five into round six. I am currently working through the book “Cracking the Coding Interview” by Gayle Laakmann McDowell. My goal is to become more familiar with algorithms and data structures. This goal was derived from my goal to better understand operating systems and key programs that I use in the terminal regularly e.g. Git. This goal was in term derived from my desire to better understand the fundamental tools used for coding outside of popular GUIs. This in turn was derived from my desire to be a better back-end developer.

I have no idea if my path is correct but I am walking down this road anyways. Worst case scenario I learn a whole bunch of stuff that will help me out on my own personal projects.