Frequently Asked Questions about HW3


Q.
Should prompts to the user (like "Please enter name, cost, etc...") be included in main(), or in the inventory functions themselves?

A.
Only generic inventory code goes in the inventory module. Anything specific like prompts goes in the main program.

For the operations that need information about an item, you must prompt for and read those pieces of information in the main program. You cannot (and should not) do so in the inventory module (after all, inventory functions take those values as parameters, and thus, they must be obtained before calling an inventory function).

You can, however, add helper functions to the main program that get all the information for a certain operation and then call the appropriate inventory function (if you like). These would be called from main().


Q.
Let's say I call the function InventoryReadFromFile from main() in this form:
InventoryReadFromFile(&list, "name_of_file");
Again, the prototype is:
int InventoryReadFromFile(inventoryT *listP, char filename[]);
Now, what if I want to call another function (perhaps InventoryAddItems) from InventoryReadFromFile that does something to my big 'list'. Could I do?
InventoryAddItems(listP, new_item);
Recall, the prototype is:
int InventoryAddItems(inventoryT *listP, itemT item);

A.
That's correct. InventoryAddItems wants an "inventoryT *" and listP (in InventoryReadFromFile) is just such a thing.


Q.
How can I read in the inventory items from the file? Do I have to read in the name character by character?

A.
Recall from HW1, that %s reads in a whole string. Most formats, like %s and %d, skip over whitespace too.


Q.
I am having trouble comparing 2 strings, as in:
if (temp_name == item.name) {

A.
You cannot compare strings with == (see Lab 5).


Q.
What is the field 'howmany' (in the inventoryT) used for?

A.
The 2nd field of an inventoryT (i.e., howmany) contains the number of inventory items in the array (you should maintain 'howmany' as you add and remove items).


Q.
What goes in h3invent.c vs. h3main.c? Why do the prompts, etc. have to be in the main program?

A.
h3invent.c has only inventory functions (plus helpers for those functions) that are supposed to be part of the inventory module (i.e., the generic functions we asked you to include in it). Everything else, i.e., functions specific to prompting, input, error messages all go in the main program, h3main.c. You probably want to break that code up into several functions called by main().

If you put prompts, etc. in the inventory module and someone wanted to re-use your module, then they would probably have to change (or even strip out your prompts). That would defeat the purpose of writing re-usable (without many changes) code. It is a matter of good program design.


Q.
How is the prompted-for information passed to inventory functions?

A.
All functions that need an item name or price or count have an "itemT" parameter that you should set up with the appropriate values (see the write-up).


Q.
How do we pass the "list" to functions that take those listP's?

A.
If "list" is an inventoryT, and listP wants a pointer to one (i.e., its address), which operator will you use on "list"? (The easy way to answer this question is to just look at the hw write-up since there are many examples there, but students should figure it out on their own first).


Q.
I read the inventory file with a loop like:
itemT temp_item;

while (!feof(ifp))  {
...
but it ends up reading in the last item "Fruit_loops" twice?

A.
What is likely happening is that after it reads the last line, it is not quite at the end of the file (since there is still a newline (\n) at the end of that line that is not yet read). So, the next time feof() still reports false, and, although there are no more items to read, it again processes the last item read which is stored in your temporary item variable.

The solution is to use the return value of fscanf (i.e., the number of things fscanf read it), as we discussed in our lab on File I/O.


Q.
Must I reset (zero out price, count, etc.) when I completely remove an item from the list.

A.
If the method you choose for deletion is moving all the items after it down, it is not necessary to reset the item.


Q.
What is the point of the inventory initialize function and when would you call it?

A.
When you declare an "inventoryT" that you use throughout the program to store inventory, it's fields are not initialized. Just like an other variable in C, you must initialize it. Namely, inventory should start out empty (with 0 elements, this implies something for the field 'howmany').

You must call the initialize function to set it up before you do anything else with the "inventoryT" (like add or delete items).


Q.
For InventoryReadFromFile(), is that function only going to be needed to get the initial inventory? What I'm wondering is if the function will only be used when the inventory structure is completely empty?

A.
For this program, yes. However, you should not assume that when you implement that function, since that would make the function less generic (and thus, less re-usable).


Q.
I tried declaring an item with "struct itemT var_name" and that did not work?

A.
"itemT" is a typedef name for the structure. Use it without the "struct" keyword. If you use the struct keyword, it requires the tag name (i.e., the name after the struct keyword in the type definition). In this case, no tag name was given for the type, but in general, using the typedef name (here, "itemT") by itself is the better method anyhow.


Q.
When we read the inventory from the file, do we assume we know how many items are in there?

A.
No, you just read as many as there are. Obviously, you'll have to deal appropriately with the case that there are more items in that file than the inventory list can hold.


Q.
Do these helper functions you've been mentioning go in h3main.c or h3invent.c?

A.
Both those files can have their own helper functions. I.e., you can have helper functions that help main() and you can have a separate set of helper functions that assist the inventory functions. They each go in the file with the functions they are helping.

Make sure you understand which file we are referring to in questions above when we discuss helper functions.


Q.
I open the file with:
int InventoryReadFromFile(inventoryT *listP, char filename[])
{
   ...
   f = fopen("filename", "r");
and my program "Seg faults" when I run it?

A.
When you:

   f = fopen("filename", "r");
this says to open a file name exactly "filename" (there probably is no such UNIX file). You mean to open the file whose name is contained in the variable 'filename'. So, how would you fix that (see File I/O web page if necessary)?


Q.
The compiler complains about cases in my switch:
case "a":
  /* do something */

A.
Switches can only be used with integral types, like ints, chars, etc. You have specified a string ("a") rather than a character ('a').


Q.
I get a weird error from the make utility about my make file (it's not an error from the compiler):
% make -f h3makefile
h3makefile:13: weird error

A.
Sounds like a problem downloading the makefile correctly. Did you cut-and-paste it (which would translate the needed Tab's to spaces) or did you download it on a PC (transferring from PC to UNIX has to convert end-of-line representations)?

Go back to our machines and download it again.


Q.
When I enter a command (like 'a' for add), it acts as if I entered 2 commands (though the 2nd one is not a valid one)?

OR

I get my prompt "Choice> " twice after my program performs an inventory command?

A.
When someone types in the 'a' command, for example, they actually type in 2 characters. I.e., what they really do is type:

Choice> a<Return>

The newline, which is generated when you hit the <Return> key, is the 2nd character. So, input is really:

a\n
^
|

The arrow shows the current position in input.

Now, when you write code to read in the command, e.g.,

scanf("%c", &command);  /* Or whatever char-reading routine you used. */
It only advances one character in the input:
a\n
 ^
 |

and remains sitting on the newline.

The same problem exists when you are done reading in other fields:

Enter item name: Pinesol\n
                        ^
                        |

Price is ...

I.e., the input from the keyboard has only been scanned up to (but not past) the newline.

So, either case might cause the problem, i.e., the next time you go to scan a command:

scanf("%c", &command);

What it reads in is the leftover newline (recall that %c, unlike %s and %d, does not skip over whitespace).

So, in summary, a way to solve this problem is to scan in those extra newlines before you process the next command.

Another method is to read in the command as a string, since %s skips over whitespace.

Do not use fflush() to get rid of the newline, fflush is not to be used on input.


BU CAS CS 113 - FAQ - HW3