CSCI 1200 Data Structures
Spring 2017

Home
  Contact Information
  Announcements
   Forums (Piazza)

Syllabus
  Learning Outcomes
  Prerequisites
  iClickers in Lecture
  Course Grades

Calendar
  Lecture notes
  Lab materials
  Homework
  Test reviews

Weekly Schedule
  Office Hours
  Lab Times

Getting Help
  Tutoring
  Advice from TAs
  Advice from Students

Homework
  Due Date and Time
  Late Day Policy
  Compilers
  Submitty
  HW Grading Criteria

Collaboration Policy &
Academic Integrity

C++ Development
  Code Editors & IDEs
  OS Choices
  Install Cygwin
  Memory Debugging
    Valgrind
    Dr. Memory

References
  Optional Textbooks
  Web Resources
  Misc. C++ Programming
    Command Line Args
    File I/O
    string → int/float

Misc. C++ Programming Information

The following C++ programming details will helpful in completing the initial homeworks for the course.

Command Line Arguments

Most of the programs we write will expect additional information from the user when the program is launched. We will do this by providing this data on the command line:

  ./my_program.exe blue 3.14159 my_input_data_file.txt my_output_data_file.txt

In order for your program to receive arguments from the command line, you will make use of the optional arguments to the main function. Here is the prototype:

  int main(int argc, char* argv[])

The parameter argc contains the number of strings on the command line, including the executable name. For the example above, argc = 5. The array argv stores those C-style strings. You can access the executable name with argv[0] and the arguments with argv[1], argv[2], etc.

Important Note: To compare command line argument strings using the == operator, you must cast this data to a STL C++-style string:

  if (std::string(argv[1]) == std::string("blue")) {
     std::cout << "my favorite color is blue too!" << std::endl;
  }

Command Line Arguments in Visual Studio

You can also specify command line arguments when running the program inside of the Visual Studio development environment. Go to "Project" → "Properties" → "Configuration Properties" → "Debugging" and in "Command arguments" enter:

  blue 3.14159 my_input_data_file.txt my_output_data_file.txt

Note, that the default directory for files is the working directory.

Converting a C/C++ String to an Integer or Floating Point Value

This is done using the atoi (char-to-integer) and atof (char-to-float) functions. First, be sure to #include <cstdlib>. Then, to convert a C++-style STL std::string variable to an int:

  std::string my_stl_string = "17";
  int x = atoi(my_stl_string.c_str());

Similarly, to convert C-style char array (C-style string) to a float:

  char* my_char_string = argv[2];
  float y = atof(my_char_string);

Reading From & Writing To Files

The STL streams std::cin & std::cout are used to read data from and write data to the "console". Often, we would rather read data from a file and/or write the output to a file. We can do this using the STL file stream library:

  #include <fstream>

Here's an example fragment of code that attempts to open an input file stream for a file name specified on the command line above:

  std::ifstream in_str(argv[3]);

It is good coding practice to verify that the input stream was successfully opened:

  if (!in_str.good()) {
    std::cerr << "Can't open " << argv[3] << " to read.\n";
    exit(1);
  }

Likewise here's how to open a stream for output:

  std::ofstream out_str(argv[4]);
  if (!out_str.good()) {
    std::cerr << "Can't open " << argv[4] << " to write.\n";
    exit(1);
  }

Once the streams are created, you can use in_str & out_str just like you use std::cin & std::cout.

In general, for this course, we encourage you to use the stream operator>> for all input parsing, rather than using getline, eof, getc, etc. We will not deduct points for using the other methods of parsing, but we have designed the assignment input format specifications for easy parsing with >>.

Note that the following code has a bug. If the input file ends with one or more extra newlines, the inner loop will "do something" with the last successfully read element twice. It is important to check the return value of each >> expression to be sure the read was successful.

  while (!in_str.eof()) {
    in_str >> my_variable;
    // do something with my_variable
  }

A simpler and more robust way to write the same code is:

  while (in_str >> my_variable) {
    // do something with my_variable
  }

File Parsing Example with different data types

For example, if your input file contains family last name, number of children, and ages of the children:

  Smith   3   4.5   6.0   8.1
  Jones   1  13.6
  Lee     2   1.5   4.2

Here is code to read all of this data:

  std::string last_name;
  int num_children;
  std::vector<float> ages;
  float tmp;
  while (in_str >> last_name) {
    in_str >> num_children;
    // error checking to make sure num_children is not negative
    assert (num_children >= 0);				  
    // clear out ages data from the last family
    ages.clear();  
    for (int i = 0; i < num_children; i++) {
       in_str >> tmp;
       ages.push_back(tmp);
    }				  
    // Do something interesting with the last_name and ages variables!
  }

Note that we do not use getline or attempt to find a newline character, so we are not relying on the newlines or spaces or tabs being in specific places in the file. We only assume that data is consistent -- the number of children is non-negative and the number of floats matches the specified number of children. We could do more error checking on each >> operation to make sure each read did not fail, but most of the time in this course its ok to assume the input won't be terribly broken. If there is an error in the input, this code will get confused and break or crash. Robustly handling all broken input is beyond the scope of this course.

Comparing Two Text Files

To check the correctness of your program, you can compare your output text file to the provided sample output text file using the UNIX utility diff (available on Cygwin & MacOSX):

  diff my_output.txt sample_output.txt

Any lines in the two files that are not identical (including whitespace), will be printed to the console. WinDiff is another option for Windows users. Please see a TA or the instructor in office hours if you have a question about these programs.

Redirecting Input & Output

What if you have an interactive program that uses std::cin & std::cout to read from and write to the "console", but you'd like to take the input from a file and you'd rather not rewrite the program to use the input & output streams described above? This following trick is handy for repeated testing and debugging an interactive program (you'd rather not have to manually type in the same input test data many times). Asking the executable to read from a file instead of the console and/or write to a file instead of the console is called I/O redirection.

  • First, create the input.txt file that contains input which you would otherwise type at the console during program's execution.

  • Then on the Cygwin/Linux/FreeBSD/UNIX command prompt simply type:

       program.exe < input.txt > output.txt
    
  • When the program has finished, look in the newly created file output.txt.

You can do the same thing in Visual Studio. (See section on "Command Line Arguments in Visual Studio" above).

Warning: There is a I/O re-direction bug in some versions of Visual Studio .NET. The program does not change to the working directory before command line I/O takes place (< input.txt > output.txt). One workaround is to specify the full path of these files on your computer, e.g., c:\Documents and Settings\username\My Documents\ds\hw\hw1\input.txt. However, you can't have spaces in your file name. So you should put the files in a place with no spaces, like c:\input.txt.

< c:\input.txt > c:\output.txt