Tuesday, November 15, 2016

Materials for Monday Nov. 14 Lab

Last night's topic was reading and writing files. There is no PowerPoint presentation this week. Here is a list of the main points:

  • Copy the colors in the next post into four text files: English.txt, French.txt, German.txt, and Spanish.txt.
  • Put the files in a place that you can easily type out the full path to. I suggest using your desktop or a folder on your desktop.
    • Mac desktop file example: /Users/markb/Desktop/French.txt
    • Windows desktop file example: c:\\Users\\davidf\\Desktop\\German.txt
    • Not that the Windows version has double backslashes. The backslash is an escape character in C++. In order to circumvent this, we escape the backslash itself by putting another backslash before it. You can look this up on the interwebs.
  • You must also have write permissions to the folder where you are going to put your files, if you are going to write new files into that folder.
  • Include <fstream> at the top of your code to get the file stream library functions.
  • An input file stream (reading a file) uses ifstream.
  • An output file stream (writing a file) uses ofstream.
Code for reading a file into a vector and using its data:
//
//  main.cpp
//  Nov14
//

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <cmath>
using namespace std;

// This is a forward declaration
int lookupColor (vector<string> , string );

int main(int argc, const char * argv[]) {
    
    vector<string> colors;
    vector<int> colorNumbers;
    
    string s;
    cout << "What language would you like to use?";
    cout << "([E]nglish, [F]rench, [G]erman, [S]panish)\n";
    cin >> s;
    
    // Choose the file based on the user choice.
    // Could you put this in a separate function?
    // Remember, the function should not open the file,
    // because we don't do I/O operations in a function.
    // Instead, the function should return the file name
    // so the main function can open it.
    ifstream infile;
    switch (s[0]) {
        case 'E':
        default :
            infile.open("/Users/markb/Desktop/English.txt");
            break;
        case 'F':
            infile.open("/Users/markb/Desktop/French.txt");
            break;
        case 'G':
            infile.open("/Users/markb/Desktop/German.txt");
            break;
        case 'S':
            infile.open("/Users/markb/Desktop/Spanish.txt");
            break;
    }

    // Example of Windows path using escaped backslashes
    // c:\\Users\\davidf\\Desktop

    // Could we make the following block into a function that 
    // reads the contents of the file into a vector?

    // Check first to make sure we actually opened the file successfully
    if (infile.good()) {

        // Loop through all lines of the file until we reach the end of the file
        while (!infile.eof()) {
            // infile >> s;
            getline (infile, s);
            // cout << s << endl;
            colors.push_back(s);
        }
    }
    
    // Get the user's input (3 colors)
    // Could this be made into a function? Should it be?
    cout << "Please enter the color names: ";
    
    for (int i=1; i<=3; i++) {
        cout << i << ":";
        cin >> s;
        colorNumbers.push_back(lookupColor(colors, s));
    }
    
    // cout << colorNumbers[0] << " " << colorNumbers[1] << " " << colorNumbers[2];
    
    // cout << s << " has value " << lookupColor(colors, s) << endl;
    
    // Do the computation to get the resistor value.
    // Could this be made into a function? Should it be?
    // Remember, we shouldn't actually write to the output (cout)
    // from inside a function. 
    cout << "Resistance is " <<
        (colorNumbers[0] * 10 + colorNumbers[1]) *
        pow (10, colorNumbers[2]) << " ohms." << endl;
    
    return 0;
}

// Why does this function need both the haystack (vector)
// and the needle? Couldn't we just make the colors vector
// global and access the global variable? 
int lookupColor (vector<string> haystack, string needle) {
    for (int i=0; i<haystack.size(); i++) {
        if (haystack[i] == needle) {
            return i;
        }
    }
    return -1;
}



Code for writing a file to the disk:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main(int argc, const char * argv[]) {
    
    ofstream outfile;
    outfile.open ("/Users/markb/Desktop/names.txt");
    
    cout << "Please input names or a blank line when finished.\n";
    string s;
    
    do  {
        getline (cin, s);
        // cout << "ok";
        outfile << s << endl;
    }
        while (s != "");
    
    return 0;
}


Here is the main function composed of other functions that do all the work. Is this main function easier to read? If you want to complete it, you just need to write all the other functions that get invoked.
int main(int argc, const char * argv[]) {
    
    vector<string> colors;
    vector<long> colorNumbers;
    
    // This function will prompt user for language, which
    // is OK because that is its primary purpose.
    string lang = getLanguage();
    
    ifstream infile;
    infile.open (getFileName(lang));
    
    if (infile.good()) {
        readFileIntoVector (infile, colors);
    }
    
    // This function will prompt user for colors, which
    // is OK because that is its primary purpose.
    getUserColorsIntoVector (colors, colorNumbers);
    
    cout << "Resistance is " << computeResistance(colorNumbers) << " ohms\n";
    
    return 0;
}


No comments:

Post a Comment