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().
Again, the prototype is:InventoryReadFromFile(&list, "name_of_file");
Now, what if I want to call another function (perhaps InventoryAddItems) from InventoryReadFromFile that does something to my big 'list'. Could I do?int InventoryReadFromFile(inventoryT *listP, char filename[]);
Recall, the prototype is:InventoryAddItems(listP, new_item);
int InventoryAddItems(inventoryT *listP, itemT item);
A.
That's correct. InventoryAddItems wants an "inventoryT *" and listP (in
InventoryReadFromFile) is just such a thing.
A.
Recall from HW1, that %s reads in a whole string. Most formats, like
%s and %d, skip over whitespace too.
if (temp_name == item.name) {
A.
You cannot compare strings with ==
(see Lab 5).
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).
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.
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).
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).
but it ends up reading in the last item "Fruit_loops" twice?itemT temp_item; while (!feof(ifp)) { ...
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.
A.
If the method you choose for deletion is moving all the items after
it down, it is not necessary to reset the item.
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).
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).
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.
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.
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.
and my program "Seg faults" when I run it?int InventoryReadFromFile(inventoryT *listP, char filename[]) { ... f = fopen("filename", "r");
A.
When you:
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)?f = fopen("filename", "r");
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').
% 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.
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.,
It only advances one character in the input:scanf("%c", &command); /* Or whatever char-reading routine you used. */
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.