Machine Problem 1, due at the end of Sept 11

Part of the homework for CS:2630, Fall 2023
by Douglas W. Jones
THE UNIVERSITY OF IOWA Department of Computer Science

Framework: Your program must begin and end as follows:

/* mp1.c by YOUR NAME HERE */
#include <stdio.h>
#include "/mnt/nfs/clasnetappvm/fs3/dwjones/2630mp1.h"

int main() {
    ... your code here ...
    return 0;
}

Obviously, where it says YOUR NAME HERE put your name, and where it says ... your code here ... put C code to solve the problem.

Details: The second header file above, ...2630mp1.h defines and initializes a variable:

This variable points to the first character of the message the program should output. Successive characters of this message are stored in preceeding memory locations, so the memory location immediately before the one ptr points to contains the second character of the message. The end of the message is marked with a null character ('\0' in C).

Top Level Specification: Write a C program that outputs the text described by the header file, as described above, and nothing else. If you get it right, the output should be in coherent English.

To output just one character to standard output, any of the following will work, where 'c' is any expression with a value that is a character:

putchar( 'c' );
putc( 'c', stdout );
printf( "%c" ,'c' );

Grading: 5 points. Correct output is worth 2.5 points. The remaining credit will be offered only for those who have correct output.

Code that does not compile will not earn any credit.

Stylistically clean code is important; that is why half the credit is reserved for style, but only if the code works. Bad indenting will be penalized up to 1 point from the 2.5 style points. Excessive or inadequate white space within and between lines will be penalized, again, up to 1 point. Excessive or inadequate comments will be judged similarly.

Note: Comments should not repeat the assignment. Assume that the reader of your code has read the assignment. Assume that the reader knows how to program, so commenting i++ with /*increment i*/ would be stupid. Comments should help the reader when the code is hard to follow.

Note: As a general rule, the first lines of every file should identify that file. The header comment in the code framework above does this. Please avoid using lines longer than 80 characters -- this is a common rule in the style guidelines of many employers. You can use this program to flag many common file format problems such as overly long lines or invisible characters:

   [HawkID@fastx?? ~]$ ~dwjones/format mp1.c

This format checker does not know anything about C or SMAL, it is looking for things that cause trouble with files imported from Windows systems, over-length lines, and non-printable characters.

Submission: To submit your work, it must be in a file named mp1.c in your current directory on the CLAS Linux system, and you must know your section number. In the following, what you type is shown in bold face. Begin at the linux command-line prompt:

   [HawkID@fastx?? ~]$ ~dwjones/submit 0A0X mp1.c

Note: The ~dwjones must be verbatim, do not substitute another name. Also, use your section number (one of 0A01 to 0A05).

The submission script will copy your code and, after the copy is made, it will output a message saying "successful submission." You may resubmit as many times as you want; each time you resubmit, your previous submission of that file will be replaced, so we will only see your final submission. The completed dialogue on your screen will look like this when you are done:

In the event of insurmountable trouble, do not delete or edit files you have submitted until the graded work is returned. The operating system record of the last edit time and date and the backups maintained by the operating system are proof of what you did and when, and they allow us to investigate what happened. until your graded work is returned. This way, the time stamp marking the time of last edit is a trustworthy indicator of whether you did the work on time.

Historically, students unable to successfully complete MP1 for this course have an extraordinarily low chance of success in the course. If this assignment proves daunting, seek help early.


Discussion

Sept. 4, 8:30 PM

I am a little bit confused in regards to getting started on the first coding assignment. I understand that you want us to create a file called mp1.c in our directory.

Yes. It should contain a C program. Note that your directory should be on the University's little cloud of shared Linux servers that we are accessing via FastX.

An obvious place to start is to get the classic Hello World program working first. Google C Hello World and you'll find lots of copies all over the place. There's one in Chapter 2 of the notes too, in the section called "A little bit of C."

Obviously, once you type it into a file (an obvious file name is Hello.c), you can use the Brief Introduction to Unix from the first day of class handouts. That explains that the cc shell command will compile a C program, and the result, by default, is in a file called a.out which you can run by typing that as a command.

But after that is where I am lost. Where/how to create a C script,

You need to use a text editor. The vi editor is the one most widely used by people using the command line in Unix/Linux.

By the way, calling it a C script is unusual. Most people would call it a C program. It is true that the borderline between scripting and programming is vague, at best, but scripting languages (such as the Unix/Linux shells or the Windows command language) are mostly tools for launching other applications in the right order and connecting them to the right input and output files. You can program in a scripting language, but most are at least a bit awkward. You can use C for scripting, but it's awkward compared to programming in C.

and then just clarification about the top level specification.

An obvious first step is to take the skeleton solution from the assignment, and instead of trying to output the whole string, just try to output a single constant character:

/* mp1.c by YOUR NAME HERE */
#include 
#include "/mnt/nfs/clasnetappvm/fs3/dwjones/2630mp1.h"

int main() {
    putchar( 'c' );
    return 0;
}

Then, try to output the first character of the string:

/* mp1.c by YOUR NAME HERE */
#include 
#include "/mnt/nfs/clasnetappvm/fs3/dwjones/2630mp1.h"

int main() {
    putchar( *ptr );
    return 0;
}

If that works, try to build a loop that outputs successive characters and checks for termination. Obviously, that involves adding a loop to the program, with a check of the terminating condition and something to fiddle with ptr between iterations.

Sept. 6, 1:46 PM

I'm getting this error message

/usr/bin/ld:mp1.c[CR]: file format not recognized; treating as linker script

I can't figure it out.

First, a matter of error reporting conventions. Many Unix/Linux utilities will attempt to reconstruct their command line from the parameters passed to the utility and use that as a prefix to the error message. So, the above message is from a program that was launched by the shell command /usr/bin/ld.

After the colon, /usr/bin/ld reports on the file that was giving it trouble. That file had the name mp1.c[CR]. Then it explains that it didn't understand the file format (that is given by the file name extension .c[CR], so it assumed the file must contain a linker script (which it almost certainly didn't).

Note that when the cc command sees a file name ending in .c it runs the C compiler, but .c[CR] is different, and cc decided it must be something to be handled by the linker /usr/bin/ld.

Some error message print routines convert unprintable characters such as '\r' to their C equivalents when they find such characters in an error message. Others (as in this case) give the name of the character in square braces ('\r' becomes [CR]) or the control character you'd type ('\r' becomes ^M).

I'm betting you tried to type cc mp1.c but you were doing it using something that's not a standard FastX Xterm window. I also suspect you weren't using a U of Iowa Linux server, because the closest I was able to get to reconstructing your error message on those servers was:

[dwjones@fastx01 temp]$ cc mp1.c^M
: file format not recognized; treating as linker script

It was really hard for me to figure out how to get that message. The file named mp1.c^M had to exist (where the ^M is the [CR] nonprinting character, and I had to figure out how to enter a name containig the a key code that means someone hit the Enter key.

Sept. 6, 2:30 PM

I'm having trouble with this code if (xxx == \0).

You either want if (xxx == '\0') with quotes added, or you want if (xxx == 0) with the backslash removed. Both will work, but there are stylistic reasons to prefer one over the other:

If the value xxx is a character, you can emphasize that it is one by comparing with another character. That is, use '\0' where the quotation marks make it a character constant.

If the value xxx is intended as a numeric value, you can emphasize that by comparing with a number. That is, use the numeral 0.

If C were really strongly typed, only one of the above would work, but C considers characters to be simple numeric codes, and arrays of characters are just arrays of integers that happen to be interpreted as characters. So, C programmers tend to get sloppy about this distinction.

I'm having trouble with this code *ptr++.

In C, this is equivalent to (*ptr)++. That means, find the thing that ptr points to and increment it. The variable ptr points to a character in memory, so this is trying to increment that character. That won't work, because the character string we have is a constant. You should not be able to increment the characters.

I am guessing you probably wanted to write ptr++ to increment the pointer to point to the next successive character.

That would be a mistake for a different reason. The assignment said that the string was stored backwards. That is, successive characters are stored in preceeding locations, so you need to decrement, not increment.

Sept. 7, 5:40 PM

Is this enough commenting on the code?

int main() {
        while ( *ptr ... ) { // while the ptr character is not a null value,
                             // the while loop will run, ...

And what about my indenting?

This is an example of a comment that repeats, in long-winded English, what the code says in C, which is not a good idea. Assume your reader knows C and focus the comments on what the code does not say.

Referring to the "ptr character" is odd. Correct English would be "the character ptr points to." That's even longer, but it's also irrelevant.

A C programmer looking at this code will wonder where ptr is declared and what it is. The assignment says this, but it would make sense to make a very short comment explaining it in roughly the place a C programmer would expect to find the declaration.

Finally, a typical C programmer would expect to see ptr incremented on each iteration of the loop. They would typically be deeply puzzled by the correct solution to this code. A small comment could help remind the reader why the code seems odd.

About the indenting: You used tabs for indent levels. That's perfectly OK in small programs like this, but as the number of indent levels grows, it becomes a problem. Big programs frequently end up with parts that are deeply indented. Tabs by default are 8 characters, so 5 levels of indenting puts you halfway across an 80 character editing window.

Lots of style guides from around the computer industry say that:

Using these rules makes your code easier to share with others. They don't need to customize their editing environment to view it. Also, note that long lines are harder to read; this is why newspapers and magazines with nice big sheets of paper print their text in relatively narrow columns.

I tend to follow these rules, and I've adopted a 4-space indent that I use in my C, C++ and Java code.

Sept. 8, 3:30 PM

After adjusting ptr inside the loop, I wrote this comment:

//ptr is XXcremented so that it points
//to the next successive character

Is this good?

Your code works and you are trying to polish it up. Good! But the comment is not perfect. First, anyone who can read C will understand that ptr++ or ptr-- or ptr=ptr+1 or ptr=ptr-1 increments or decrements the pointer, so starting the comment by saying that is a waste of words. For that matter, if the comment is on or obviously conected to the line where ptr is adjusted, the subject of the comment is obvious so need not be repeated.

The comment should always emphasize why, not what, and if there are any surprises in the code, emphasize that. And do it tersely. A good comment here can be quite short.

At the start of my program, after a comment saying where ptr is initialized, I added this comment:
//ptr points to the memory location of a character

Is this good?

It could be better. First, C programmers know that pointers point to memory locations, so you could say it points to a character. The big problem here, though, is that that character is not isolated! At the start of the program, you know much more about that character. Is it the first, the last, or a middle character in some collection? How is that collection organized. You can say all of that in a terse one-line comment.