CS 2213/2211
Advanced Programming
Questions and Answers, Spring 2005

  1. Question (Sat Jan 22 17:00:01 CST 2005): I am in your CS 2213 Advanced Programming class. I am working on Recitation 1 on my home machine running Fedora Core 2 with all the latest updates. I know you said we should use the lint utility on the Sun system. I was wondering if you were familiar with splint. Documentation and downloads can be found at www.splint.org. More than likely it is included in your SUSE distribution like is in Fedora. splint is supposedly better than lint. Is it okay to use splint rather than lint or must we use lint on the Sun System?

    Answer: I wasn't familiar with splint. It's on the Fedora systems in the Linux lab. (My SuSE system is a couple of years old now and doesn't seem to have splint.) Yes, of course you can use splint. However, a few test runs on my own programs produce an amazing number of warnings. These bring up issues that I don't want to discuss in class at all, since we are trying to learn the basics of C. For example, splint refers repeatedly to type "boolean" in its messages, and I guess the newest C standards have a boolean type, but I don't know the status of this. For us in this course, C has no boolean type separate from int. In summary, splint seems pretty high-tech and may not be useful for this course.

    Update to answer (Mon Jan 24 09:56:02 CST 2005): On investigation, it doesn't seem as if splint will be usable in this course. It simply displays too many high-tech messages. Perhaps it can be configured to be useful, but for now I want you to use lint (on the Sun system) and NOT splint.

    Hugh Maynard says that gcc with option -Wall will give some of the warnings of lint, but not all.


  2. Question (Mon Jan 24 18:24:17 CST 2005): I have recitation #2 pretty much finished, except for problems when trying to implement one of the "hand written" RNGs. If I use the built-in rand(), I get output like this... (correct-looking output).

    However, when I replace the call to rand() in the roll function with, say, Knuth's double generator algorithm the output looks like this... (every roll is a 2). I declared the seed1, seed2, and seed variables and tried it with and without srand doing the seeding. I tried all kinds of different scenarios and different RNG algorithmss, none of which are working. Can you give me any assistance with using a RNG other than the library one?

    Answer: You didn't include the code you are using, but still there seems to be a likely answer. In the program craps.c as it is in the write-up for Recitation 2, the call rand() to the built-in RNG should return an integer between 1 and RAND_MAX inclusive. Then when you divide this by RAND_MAX + 1 as doubles, the result should be a double between 0 and 1.

    In contrast, the function I called "Knuth's double generator" is designed to return a double between 0 and 1 directly. If you put it into the expresssion rand()/(double)RAND_MAX) + 1.0 this will always be 1, since 1/(double)RAND_MAX) will always be 0. So even though both functions are called rand(), they return quite different things.

    If you seed either one of these generators with 0, you should get the same incorrect result. Also, using srand() to seed Knuth's generator doesn't make sense because srand() is connected to the built-in generator.


  3. Question (Fri Jan 28 08:09:10 CST 2005): I was going over rec1 and I was having a problem executing the compiled dice program from the terminal on my home computer. I create the executable file using gcc or cc. The file is created in the rec1 directory and when I do the following I get:

    I am using fedora. Am I missing a package or something? Could you please let me know what the problem is asap? Thanx

    Answer: This is not really a problem (it's a feature!). All the versions of Unix and all the various shells (and Zzzzzindows also) have the concept of a "PATH" variable, saying where to look for commands that are typed at the command line. This variable gives a sequence of directories to search for the command. This is what happens when you type a Unix command, say,

    Normally this path variable has a dot (which stands for the current directory) as its last entry. In the case of your system, this dot is missing. So all you have to do is type ./dice and it will work. Sometimes students give their executable the name of a common command, and have the same trouble you are having. The same solution works. Here's a little demo:

    I consulted with Dan Smolenski a bit. In the Linux lab you are using the shell tcsh (a version of csh). It must have dot on its path. You are at home, and are using bash, which evidently doesn't have dot on its path. It is more secure to not have the dot there, and Dan says he's used to always typing ./ in front of commands. Each shell has an initialization file that lets you change the path variable; you'll learn more about this in the Systems Programming course.


  4. Question (Sat Feb 5 20:37:00 CST 2005): I hope this is not such a dumb question. I assume we can use <ctype.h> for Recitation 3 to ignore white space, punctuation, and uppercase etc. Is this correct? I hope so because this is the plan that I am going with even though there was no mention that we could use or not use this library.

    Answer: Yeah, I meant for you to use these functions, and I assumed you would figure it out, since almost the same functions are available in the Character class in Java. You'll have to look up the proper functions to use (the names vary a little from Java). Of course you have to include <ctype.h>. Notice that there is a function that will convert uppercase letters to lowercase and will leave lowercase letters alone.

    In general, I want you to do a lot of C programming. I'm never going to be too uptight with some detail about the way you do your programming, as long as you're learning.


  5. Question (Sat Feb 5 20:53:14 CST 2005): I was wondering if you knew of a good example program of opening and reading from a file in C. I know you included the Copy Program with Rec 3, however I was still unsure how the file actually got opened and read by the program since it was not referenced anywhere in the code, and when at execution nothing is passed as well ... so it appears to me that this program is not reading a text file ... just echoing command line args ... is this correct? And again if we have to read from a text file do you have an example of this or was it intentionally left out for us to find in the book or somewhere?

    Answer: No, I didn't intentionally leave stuff out, although reading in books and digging stuff out is always good for you (the best way to learn). I should have emphasized these matters more because it's a very important part of Unix at the command line. When you read in C with getchar() or with scanf(), the input is coming from the Standard Input, known in C as stdin. At the Unix command line, this means just to type the input at the terminal. However, Unix (and also Zzzzindows) allows re-direction of the input. If you follow the command to execute some file with < somefile.txt, this means to take the input from this file, rather than from the terminal. Think of the < as an arrow pointing from the input into the file to execute. The program reads from this file, and if it keeps reading, eventually it will come to the end of the file, and you will be able to test for this using EOF, since getchar() returns EOF when you try to read a character and there are no more characters left.

    You should look at the webpage on copying: Copy Programs, since this stuff is illustrated there (although not fully explained). On that page, one of the commands reads: copy < copy.c > copy2.c. This means that the program copy when it executes and tries to read data will find the file copy.c provided to it for reading, just as if the characters of this file were being typed at the terminal. The othre re-direction above sends the output to the file copy2.c, instead of to the terminal. If a file copy2.c had already existed, it would have been trashed, and the new output would take its place. It's a little weird that I'm copying the C source for the copy program itself, but I like weird things.


  6. Question (Sat Feb 5 21:26:04 CST 2005): Another question that is bugging me is how we are supposed to terminate the program from main. You have it written as: while ((ch = getchar()) != EOF), but in the Java implementation I see that Ctrl-C terminates the program, which we could do with your C implementation, but is that how you want us to do this?

    Answer: Ctrl-C sends a "break" signal to halt execution of the program (process) that is executing, whether it is Java or C. We don't normally want to plan to terminate execution of our programs using Ctrl-C. Instead, if we are reading from a file, we want to properly check for end-of-file so that we can stop executing the read (or getchar() in this case) by checking to see if there is any more to read (in this case checking if EOF is returned). The while above is not my code but is the way this has been done in C since pre-historic times.

    Now in case you are reading directly from the terminal, there's not exactly an end-of-file, since you could always keep typing, but in the Unix world, you can simulate an end-of-file by typing Ctrl-D (the letter after C). To your executing program, it seems exactly the same as if it had come to an end-of-file on the file it was reading. For Recitation 3 and elsewhere, do NOT use Ctrl-C, but either redirect a file in as the standard input or use Ctrl-D to simulate end-of-file.


  7. Question (Sat Feb 12 00:21:40 CST 2005): I'm having problems with Recitation 4 ... (various things mentioned) .... I created my own function to check if digits are within the base's range called isbasedigit. (Other discussion follows ...) Answer: There are several problems with your function:


  8. Question (Sat Feb 12 23:14:53 CST 2005): I am having trouble understanding the portion of code with the name clarg.c located under the description of step 2 to rec 4. It appears that the main function takes two parameters, an int and a string, or char array. In the execution view the first time clarg is executed no params are passed, but "Usage: clarg base" is printed. Obviously argc would not equal 2 if no param is passed so i can see why that is printed. The next time however that you execute clarg you pass the value 8. I am confused as to why "Command-line argument: 8" is then printed. If in main argc is checked to not be 2 then how would 8 make it past the same if statement that the previous run of the program did not? The second part of my question deals with the actual execution of the second part of the code. It looks like that since this program now must take an additional input from the command line, that we can no longer get the ints from the standard input like the file, because of the need for a number base as well as various numbers. It looks like in the execution example for the second step that the base is the first number passed, and the rest of the digits are just seperated by whitespace, with a control d at the end. If a control d was input at the end of the line wouldnt the program terminate? or are the ints after the base input one at a time, and converted as each are read? I am confused as to how things are input for the second step, can you please explain.

    Answer: We will go over how these main parameters work later. (They are an int and an array of strings.) I assumed that you would just use my code "as is". This is just another convenient way to get numbers into an executable file without directly reading them as input: instead put them on the command line. In this case we are only putting one number, the base to use, on the commmand line. The variable argc holds the number of items on the command line -- in this case it should be 2. What we want is the second argument, the 8, and we get that with the mysterious statement base = atoi(argv[1]); which we will explain later.

    In my demonstration program, I just printed "Command-line argument: 8" to show that the code was working properly. In case you use an 8 on the command line, your program is supposed to print "Base: 8" instead. Then you will go on to process the input, either in a file or by typing the input. In case it is in a file, your commands might look like:

    Or like:

    So the base is really separate from the other numbers provided for reading, since the base is on the command line, while any other numbers are either in a file directed in for reading, or are on subsequent lines typed in and read by the program. In case you enter data at the terminal without redirecting, the reading of the data will commence with what follows the command line, after you type [Enter].


  9. Question (Sun, 13 Feb 2005 18:59:14 -0600 (CST)): In Recitation 4 ... now it seems that my command line argument for the base is not being read in properly.

    I have tried a test:

    and also where

    I get a number either negative or not even close to the given base. Is there something else I am missing. I have had this error before in other classes I programmed before, but it never affected my results. Can you suggest anything.

    Answer: We are going to talk about this stuff. For now I meant for you just to use the code I gave you, namely base = atoi(argv[1]); This converts your input integer value, whatever it is, to an internal int.

    Just as a "preview" of things we will discuss shortly, argv[1] is a string in C, which (it turns out), is the same as the address of the first character of the string. Thus dereferencing, ... , *argv[1] will be the first character of the string. If you type 8, then you get the character '8', while if you type 16, then you get the character '1'. All this will be clear soon in the course.


  10. Question (Sun Feb 13 22:20:27 CST 2005): I have a question pertaining to part 3 of Recitation 4. You say that we need to make changes to the isdigit function used in the file getint.c ... do mean that the changes we need to make are to our isdigit(foo,bar) that we wrote in part 2 to replace the <ctype.h> isdigit(c)?

    Answer: For Step 2, you need relatively minor changes to the isdigit function, available when you include <ctype.h>, along with several other changes: picking up the command line argument and using it for the number base.

    For Step 3 you need heavier-duty changes. I did this part by replacing the isdigit function with my lookup function. This is certainly not the only way to do this part.


  11. Question (Mon Feb 14 20:22:14 CST 2005): In Recitation 4 I am having trouble with the validy checking for correct ranges of input numbers. My program will run fine if only correct numbers are input to be converted but if an invalid number or letter is input I enter an endless loop. This occurs without any changes to the getint() method.

    Answer: Yeah, this is the way this particular program behaves. Once you get an invalid input (a 0 returned), you have to terminate. This is because the getint() function does an ungetch() in case of an invalid character and returns 0, so if you keep calling getint() in this case you will be in an infinite loop. Your program (not shown above) doesn't even check for a returned 0.


  12. Question (Mon Feb 14 23:41:22 CST 2005): You mentioned that if a 0 is returned, our main program should terminate. But in your example input file one of the numbers is a 0, which is returned and printed, yet your program goes on to read another number. How so?

    Answer: Remember that the int being read is returned in the reference parameter, not as the value of the function. The function returns either a 0 (could not read an int), or an end-of-file code (actually EOF or -1), or else a positive value to indicate an integer was successfully read. The positive value is the Ascii code for the last character of the integer. So if the function reads a 0, then an integer 0 is returned in the parameter, and the character code for a 0, namely a 48, is returned as the function value. (Wheh!)


  13. Question (Sun Feb 27 20:00:34 CST 2005): About Recitation 6 I was wondering: when inserting characters into the array, you said only letters. Do you mean literally alpha and no spaces and other delimeters?

    The reason I was asking because when I output the string, I have the sentence with no spaces. I was only inserting characters and ignoring everything else and my output looked messy. I was just wondering.

    I was also wondering if we can use rec4 since it handles everything and all I need is to include the reverse and strncopy functions, and maybe other modifications.

    Answer: Just as you pushed and inserted only letters (converted to lowercase) in Recitation 4, you should insert only letters (converted to lowercase) into the string to be reversed. You will be comparing the original string with the reversed string (letters only) to check for a palindrome. Separately you must output the original characters of the possible palindrome, as we did before. You can construct your program from scratch or by modifying your code for Recitation 4.


  14. Question (Tue Mar 22 20:47:52 CST 2005): I am having trouble with Part C of Recitation 8. Everything I have found says that when passing a two dimensional array to a function the first dimension can be ommited but the second dimension must be known at compile time. Any hints?

    Answer: What you say is true only in the case of a "normal" C 2-dimensional array, say declared with a[5][4]. When passing it as a parameter, C needs to know the length of a row, because it is represented as just a 1-dimensional array internally, so the length of a row is needed to pick off the correct row and column.

    However, Part C involves the case of an array of pointers to 1-dimensional arrays, where things are quite different. C basically needs to know how many rows there are, and it needs to know the length of each row, since they don't have to be the same length. But knowing these lengths is just to keep from going out of bounds in the array. No lengths are needed to pick off the correct row and column, since for row i and column j, C needs to go to the ith pointer to arrays, and following that pointer, it needs to go to the jth element. The storage for the original array of pointers, and for each 1-dimensional array pointed to must each be contiguous storage, but otherwise this storage can be all over the place.


  15. Question (Wed Mar 23 20:52:00 CST 2005): In Recitation 9 : One of the table entries is:

    
    Arithm Expr      RPN             Evaluated Result
    3^2^2^2$         3222^^^$        43046721.000000000000

    Is this 3^8 because the result is 3^16 to get 4304... so should it be 3^2^2^2^2?

    Answer: No. The exponentiation operator ^ associates right-to-left, so that 3^2^2^2 = 3^(2^(2^2)) = 3^(2^4) = 3^16 = 43046721.


  16. Question (Sat Mar 26 22:45:41 CST 2005): I was re-reading the translation segement in Recitation 9 and looking at rule 2) Always push left parenthesis. Does this mean literally push ( without worrying about precedence?

    Answer: Yes, first follow Rule 2 and always push a left parenthesis. Otherwise, Rule 3 would say not to push before popping, because a left parenthesis has lower priority than other operators.


  17. Question (Sat Mar 26 22:54:11 CST 2005): I was wondering if you can briefly explain the train sample with input: 2+3*4-(5^6^7)$

    Answer: Here goes:
    Output Stack Rest of Input Action Rule and details
        2+3*4-(5^6^7)$    
    2   +3*4-(5^6^7)$ Output 2 1
    2 + 3*4-(5^6^7)$ Push + 3 empty stack
    23 + *4-(5^6^7)$ Output 3 1
    23 +* 4-(5^6^7)$ Push * 3 + lower prec than *
    234 +* -(5^6^7)$ Output 4 1
    234* + -(5^6^7)$ Pop * 4 * higher prec than -
    234*+   -(5^6^7)$ Pop + 4 + equal prec to -, L assoc
    234*+ - (5^6^7)$ Push - 3 empty stack
    234*+ -( 5^6^7)$ Push ( 2
    234*+5 -( ^6^7)$ Output 5 1
    234*+5 -(^ 6^7)$ Push ^ 3 ( lower prec than ^
    234*+56 -(^ ^7)$ Output 6 1
    234*+56 -(^^ 7)$ Push ^ 4 + equal prec to -, R assoc
    234*+567 -(^^ )$ Output 7 1
    234*+567^ -(^ )$ Pop ^ 4 ^ higher prec than )
    234*+567^^ -( )$ Pop ^ 4 ^ higher prec than )
    234*+567^^ -() $ Push ) 4 ( equal prec to ), R assoc
    234*+567^^ - $ Delete () 6 delete adjacent () on top
    234*+567^^-   $ Pop - 7 first part
    234*+567^^-$     Output $ 7 second part


  18. Question (Mon Mar 28 17:12:11 CST 2005): In Recitation 9 how do we implement 2 seperate stacks from one header file? I asked you about this last thursday after the quiz, and you said there would be example code on the website but i couldnt find any.

    Answer: As I wrote in the Recitation, you need two separate stacks, and if they are going to be in the same directory, even function names like empty() need to be different for the two stacks. One holds doubles and the other holds chars. You should use separate files for the implementation of each stack. You should also use separate header files. Thus translate.c will include one header file, and evaluate.c will include the other. The sample stack in Stack can serve as a model for either of the new stacks, except that you should check for underflow and overflow.


  19. Question (Mon Mar 28 19:05:52 CST 2005): For the evaluation part of the assignment, are we to use a second stack to hold the operators we collect or do you suggest some method of handling them individualy as we come to them?

    Answer: During RPN evaluation, there is no collection of operators. Each operator is immediately applied to two previous operands (on the stack at the time that the operator is encountered), and then you are done with that operator forever.


  20. Question (Tue Apr 5 21:01:42 CDT 2005): In the following code from the stack.c example program in Recitation 10, what is s and where is it declared?

    Answer: You need to look at the whole file stack.c. It has a global variable s, which is actually the key variable. This is the stack itself, initialized to NULL (an empty stack). When you push something on, you malloc storage and store a pointer to it in the variable t. Eventually t's value gets assigned to s, and now s points to a non-empty stack. (Here, s is a "global variable", but it is really more like a data member of a stack class.)


  21. Question (Thu Apr 7 08:12:36 CDT 2005): Can we create a function, say with prototype void Openfile(FILE *fp1); to open a file? I noticed when I declare FILE *fp; then use fopen() I have no trouble reading from the file but I want to try to call it in a function, and when I do that I get a core dump.

    and it works when I remove my function call and initialize fp1 and fp2 directly. If I try to run as is, I get a core dump.

    Answer: This is not correct. C passes parameters by value, meaning that the value of the parameter is copied into the function. In this case, two unitialized file pointers are passed into the function fopens. They are given values inside the function, but these values are lost when you return from the function. You could use a FILE ** parameter, or better, just return the file parameter after opening, but this is what fopen already does.

    You can pass the file pointer after opening to a function to read from the file.


  22. Question (Sun Apr 10 14:05:37 CDT 2005): I have Recitation #11 working (matched the wordcounts of the files with my counts of the three categories of words), but had a question about the "Alphabetic order" problem. I solved the problem by just adding 32 to the first letter's ascii value before the string compare, and subtracting it afterward before printing it back to the outfile. [I assume that you checked that this first letter was uppercase.] It sounds like in the writeup you want us to just check the first letter of the words to see if it is uppercase, and deal with it from there. I noticed that on the long UNIX wordlist, there are several acronym-type words ("AC", "ACM") that have the second and third letters uppercase as well as the first. This messed up the alphabetic order on my outfile. I have not implemented changes in the code yet to check for second, third, etc letters as uppercase and convert them to lowercase before the string compare. Should we check for uppercase letters all the way down our word buffers, or just for the 1st letter?

    Answer: You need to check uppercase for all the letters, and not just the first one. I promised a hint about how to do this. The adding and subtracting 32 works, but it gets unwieldy if you handle more than the first letter. A much better solution is to write your own version of the strcmp function. Inside this function, you should apply the tolower function to each character that you handle (including the characters in the final return). This way no words are changed, but you just have a different string comparison.


  23. Question (Wed Apr 13 20:35:51 CDT 2005): I have a question about the web page concerning 2 dimensional arrays in c. Under the topic Two different approaches: approach 1. You say that the formula to get to the correct position is 4*i + j is this really just trying to do j*i + j since j = 4, or is the 4 really constant?

    Answer: If a 2-dimensional array is declared int a[M][N], where M and N are constants defined with #define, then the general formula for array element a[i][j] is a + N*i + j. In other words, we start at the address of the 0th element of a, then skip over i rows each of length N, and go j further on the row number i. We must know the number N, the length of a row = the number of columns. The formula doesn't need M, the number of rows. You should also have the array subscripts in bounds, that is 0 <= i && i < M && 0 <= j && j < N.

    In the special case of the example on the web page, the length of each row is 4. The formual for a[i][j] in this case is a + 4*i + j and NOT just 4*i + j. There is no mention of j = 4 on this page.

    Notice that you must not use this formula for an array of pointers to 1-dimensional arrays.


  24. Question (Sat Apr 16 19:23:59 CDT 2005): I'm stuck on rec12. My program only prints the last string in the file. I ran it through a debugger and noticed that after the first iteration the root is set to "Jan". After that, (p -> ch) on line 26 is always equal to the paramater c. I 'm guessing they point to the same location.

    Answer: I looked at your code, and you are making a fairly subtle mistake that others may make also: You are reading each string into a single buffer c in your main function. A pointer to this buffer eventually gets passed to your newnode function:

    Think about this function carefully. It allocates new storage for the struct, but then the ch is set to point to the original buffer back in main! The first time you do this, it is for the root node. When you read a different word into the buffer, the root node still points to the same buffer, so the root node acts like it has the second word in it, rather than the first.

    I hope the fix for this problem will be clear to you. If not, ask me again.


  25. Question (Sat Apr 23 23:27:02 CDT 2005): On Rec 13, are we supposed to create a non-dynamic array of hashtables? So far the way I approached this was:

    to create a dynamic hashtable with dynamic nodes, and the table will contain a invalid index to inform me which lic plate is invalid. so I can skip over that plate and look for a new entry point, but if the array is full I can identify an invalid plate, free the location and insert the new plate.

    Will this interfere with the lookup of the plate? I was thinking it would, so if my array is full I was just going to print a message, free mem and quit.

    Answer: You might be able to something with what you have above, but it is more complicated than I had in mind. Your struct hashtable is still just a single struct with a struct inside it. It's not an array or a collection of nodes, but just a single node.

    When I said "hash table", I meant for you just to use a simple array of pointers to struct hnode, either declared as an array, or allocated dynamically with malloc.


  26. Question (Tue Apr 26 23:21:18 CDT 2005): In Rec 13, given an array of structs, how does one access a particular struct element? Say I have a struct

    and declare an array of these as such...

    To access the license plate in array element 5 I would think it should be

    This is what I have read elsewhere also. However on compile I get an error.

    Answer: The variable parking is an array of pointers to structs. Thus parking[5] is a pointer to a struct. You must first dereference it before you can pick off a field in the struct: (*parking[5]).license. In practice, C programmers almost never write that, but instead use the shorthand -> operator: parking[5]) -> license.


  27. Question (Tue Apr 26 23:31:22 CDT 2005): In Rec 14, you did not mention how to convert the string in the .dat especially for the numbers that are not single digit. Should we use use the: long strtol(const char* s, char** endp, int base); or should we write our own. I have a very good how to write a converter. Is it worth the effort?

    Answer: strtol is pretty high-tech, but you can use it. A simple function is just atoi. You can also use sscanf. However, I intended for you just to use fscanf to read the file.


  28. Question (Thu Apr 28 22:20:11 CDT 2005): In Rec 14, would think it might be easier to instead of using the two arrays to keep track of the visited nodes and shortest nodes, to just put two extra int types in the struct?

    So when we traverse the graph, visiting the node, we can check the current node, instead of looking in the array.

    Answer: This approach is not workable. The problem is that the struct defines an edge, not a vertex. (It is on a list giving all edges that start with a given vertex, and its vertex is the end of one of these edges.) There may be several edges that end in vertex 4, for example, and it won't be clear which one you should use to store the information about a vertex. (Or else it would be a lot of trouble to store the information in each one.)


  29. Question (Fri Apr 29 19:22:22 CDT 2005): In Rec 14, this is what I have constructed so far:

    I just cant figure out how to run down the array and each linked list while at the same keeping track of the weights of the paths to the next vertex... Can you try to explain how to do this with a bit more elaboration?

    Answer: OK, I'll take on this challenge. I'm going to be referring to the writeup for Recitation 14, in the section Computing the length of the shortest path from vertex 0 to each vertex. First give values to the two "magic" arrays: all 0's into status and all MAXPOS into shortest, except that shortest[0] is set to 0.

    Now comes the part that is bothering you.

    So in pseudocode, your loop starts out:

    Of course you're going to need an inner loop to evaluate the while condition. Good luck!


  30. Question (Tue, 03 May 2005 20:15:12): In Recitation 14 I am trying to pick off an element in a struct and I am deferencing it now as you said to do like so.... (*g[cv]).v = getnum(infile); but I am still getting a segmentation fault when it attempts this operation. What is wrong now? (My code follows.)

    Answer: (You must be using a C++ compiler that doesn't require all declarations at the start. That's OK.) First of all, (*g[cv]).v is correct, but nobody writes this. Instead they write the equivalent: g[cv] -> v.

    Your function getnum should work, but it would be easier just to write: fscanf(fp, "%i", &j); and then return j.

    Your program has a fundamental flaw related to not allocating storage. First you declare struct gnode *g[N];. This is an array of N pointers to the struct, all initialized to the NULL pointer. To actually put any data into one of the structs, you will need to allocate storage: After you read a value for cv, you will need:

    Now you could store values into the two fields.

    Another problem: You should only do the above in case g[cv] is NULL. If it isn't NULL, then you already have at least one vertex patched in. For the next vertex that comes along, you will need to allocate another struct and patch it into the head of a linked list starting with g[cv]. (This means setting the next field of the new struct to point where g[cv] points, and then setting g[cv] to point to the new struct.)

    I didn't debug the above code, so there may be other problems. (In particular the code above will need to read till EOF.)


Copyright © 2011, Neal R. Wagner. Permission is granted to access, download, share, and distribute, as long as this notice remains.