540 likes | 549 Views
RANDOM NUMBER GENERATOR & STREAMS (FILE I/O, STRING). CISC1600: Fall 2011. Compilation and linking. C++ compiler. Executable program (a.out, ageCal,…). linker. C++ source code. Compiler: translates each source code into object code
E N D
RANDOM NUMBER GENERATOR & STREAMS (FILE I/O, STRING) CISC1600: Fall 2011
Compilation and linking C++ compiler Executable program (a.out, ageCal,…) linker C++ source code • Compiler: translates each source code into object code • Object code is simple enough for a computer to “understand” • Linker: links your object code(s), library code • E.g. library code for input/output libraries, for vector, string, … • generate an executable program (or, executable) • default name for executable is a.out Object Code (*.o files) Library Object code 2
Compilation and linking Object Code (*.o files) Source code (*.cpp files) Executable program (a.out, ageCal, …) C++ compiler linker So far, we have learnt: • use a single command to do everything, without generating object codes g++ lab4.cpp date_func.cpp // default executable name: a.out • specify name for executable: g++ -o ageCalculator lab4.cpp date_func.cpp -o filename: name executable as the given name What if one type: g++ lab4.cpp –o date_func.cpp ? the executable is named date_func.cpp, i.e., whatever in date_func.cpp will be overwritten. Library Object code 3
Compilation and linking Object Code (*.o files) Source code (*.cpp files) Executable program (a.out, ageCal, …) C++ compiler linker • To compile and link separately g++ -c lab4.cpp date_func.cpp // compile source codes to object codes lab4.o, date_func.o g++ lab4.o date_func.o //link later • If you modify lab4.cpp only, you only need to recompile date_func.cpp, and link • g++ -c lab4.cpp • g++ lab4.o date_func.o Library Object code 4
Expressions and Operators • Expression is composed of one or more operations • Variables/values/sub-expressions to which operation are applied to are called operands. • Operations are represented by operators, such as ==, = , * • Unary operators: act on one operand • E.g., ! for negation • Binary operators: act on two operands, e.g., *, -, +, &&, || … • Compound expression: an expression with two or more operations • Precedence and associativity determine order of evaluation
Associativity • Arithmetic Operators: left-to-right • *, /, %, +, - • a*b/c: * first, / second • Equality, relational and logic operators: left-to-right • ==, != • <, <=, >, >= • &&, ||, ! • Assignment operators: right-to-left • i=4; //i is left operand, 4 is right operand • Store a new value (4) in left operand’s storage • expressioni=4 has a value of 4, it’s data type is same as that of i • i=j=10; // concatenated assignment operators • Variable j is assigned value of 10, and i is assigned the value of expression (j=10), which is 10
Operator precedence High • && • || • ?: arithmetic if • =, *=, /+, %=, … assignment operators • Array index: [ ] • Function call: ( ) • ++, -- • ! • Unary plus and minus: +, - • *, /, % • +, - • <, <=, >, >= • ==, != Q: What’s the order of evaluation for: ch = buf[bp++] != ‘\0’; When in doubt, use parenthesis ! low
Operator (cont’d) bool valid; valid = IsValidDate (month, day, year); if (!valid) { cout <<″Invalid date! Try again (Y/N)? ″; …. } Can be written more concisely : if ( (valid=IsValidData (month, day, year))==false){ cout <<″Invalid date ! Try again (Y/N)? ″; … } What if the highlighted () is omitted?
Operators: increment and decrement • Prefix increment/decrement: applied to int type (int, char, long) • e.g., ++count; • array[size] = input; ++size; • Postfix increment/decrement: similar • E.g., array[size] = input; size++; • What’s the difference? • int i=8; • int j=i++; // versus j = ++i; • Both change i’s value to 9 • What about j’s value?
Operators: increment and decrement inti=8; j = i++; • Postfix: increment iafter evaluating (i++) expression • j=i++; is same as • j = i; • i = i +1; • So j’s value is 8
Operators: increment and decrement inti=8; j = ++i; • Prefix: increment ibefore evaluating (++i) expression • j = i++; is same as • i = i +1; • j = i; • i = i +1;
Operators: increment and decrement j=9; inttmp = sqrt (j++); • What is the value of tmp? j? j=9; inttmp = sqrt (++j); • What is the value of tmp? j?
Operators: increment and decrement i=0; while (i<data.size()){ cout <<″Data at index″ <<i <<″:″<<data[++i]; } • which elements are printed out by the above code segment?
Arithmetic if operator • only ternary operator in C++: i.e, it takes three operands • expr1 ? expr2 : expr3; • expr1 is first evaluated; • If expr1 is true (i.e., any nonzero value), • expr2 is evaluated, and the whole expr takes expr2’s value • Otherwise, expr3 is evaluated, and the whole expr takes expr3’s value • cout <<″the larger value of ″<< i <<″ and ″ << j << ″ is ″ << (i>j ? i: j ) << endl; • cout <<″the value of ″<< i <<″ is ″ << (i % 2? ″odd ″ : ″ even″ ) << endl;
Computer simulation • Computer based simulator • use random numbers to simulate random events: toss a coin, roll a dice, inter-arrival time of customers,… • random number generator generates pseudo random numbers • cstdlib (c standard library) • rand() produces apparently random integers in interval [0, RAND_MAX] • RAND_MAX, a constant defined in cstdlib.h, typically 32767, or 2147483647
Computer simulation • rand() use an algorithm generates a sequence of apparently non-related numbers each time it is called. • a seed is used to generate the series • Same seed => same sequence of random number sequence • srand(): set the seed that rand() uses • During program debugging, sometimes it’s preferable that random number sequences are same during each run • i.e., we use the default seed for all testing run => same random number sequences …
Computer simulation • After debugging, you should seed generator (just once!) before using rand() Time now; int seed = now.seconds_from(Time(0, 0, 0)); srand(seed);
Scale random number • Sometimes, we want random integers on [a, b] • [1,6] for toss a six sided die • [0,1] for toss a coin, … • This is how to scale random number to [a, b] • There are b - a + 1 values between a and b • To get values on [0, b - a]: • rand() % (b - a + 1) • Add a to get values on [a, b] • int r = a + rand() % (b - a + 1);
1 #include <iostream> 2 #include <string> 3 #include <cstdlib> 4 #include <ctime> 5 6 using namespace std; 7 8 int main() 9 { 10 // Sets the seed of the random number generator. 11 srand(time(0)); 12 13 for (int i = 1; i <= 10; i++) 14 { 15 int d1 = 1 + rand() % 6; 16 int d2 = 1 + rand() % 6; 17 cout << d1 << " " << d2 << "\n"; 18 } 19 cout << "\n"; 20 return 0; 21 } Simulate toss a pair of dices for 10 times …
Random floating point value • To generate a floating-point number on [a, b]: • double r = a + (b - a) * (rand( ) * 1.0 / RAND_MAX); • Underlined part: scale the number to [0, 1] • 1.0 makes the numerator a double, rather than an int • We want to avoid integer division • Multiplied by (b-a) to scale to [0, b-a] • Added by a to range [a, b]
Reading and Writing Files • C++ input/output library is based on the concept ofstreams. • #include <iostream> • Common input/output streams: • Keyboard and terminal (cin, cout) • Files on your hard disk • Key: sequential access • An input stream is a source of data • Data arrives in an input stream one at a time, like items on a conveyor belt. • An output stream is a destination for data. • Data are sent to an output stream one at a time.
Reading and Writing Text Files • We focus on reading/writing text file • text file is made up of a stream of characters (letters, digits, special characters) • Each character is represented as a byte (8 bits) according to ASCII • Not all file is text file • e.g., your executable file (a.out, AgeCalculator), command file (g++). • it stores information as a stream of 0 and 1 bits, we call them binary files
Opening a Stream • To read or write a file stream, you need to openthe file • i.e., associating a stream variable with the file • First: declare stream variable, e.g. • ifstream in_file; • define an input stream variable named in_file: • Then: open the file • in_file.open("input.dat"); • to read a file named input.dat located in current directory: • stream variables are objects so we will use a method. • You use the name of disk file only when you open the stream.
File name • File names can contain directory path info., such as: UNIX in_file.open("~/nicework/input.dat"); Windows in_file.open("c:\\nicework\input.dat"); When you specify the file name as a string literal, and name contains backslash characters(as in a Windows path and filename), you must supply each backslash twice to avoid having escape characters in the string
Opening a Stream • open method only accepts C string • char filename[20]; //filename is a C string • Not C++ string, which is a class • string filaname; • C++ string => C string • Use string class ‘s c_strmethod to convert cout << "Please enter the file name:"; string filename; cin >> filename; ifstream in_file; in_file.open(filename.c_str());
Stream fail • Stream may be in a fail state if: • It couldn't be opened (doesn't exist, no permission) • You don't have write permission on an output file • The stream has discovered the end of an input file • Should test for failure immediately after open, read, • Test stream failure condition • Use fail() function • Or evaluate the input (>>) operation
Read a disk file with error checking in_file.open(filename.c_str()); // Check for failure after opening if (in_file.fail()) { cout <<“Failed to open file “ <<filename << endl; return 0; } // read the file… while (in_file >> name >> value) { // Process input } >> operator returns a “not failed” condition. expression has a true value if reading is successful, and a false value if something goes wrong If you have read ALL data from a file, incur same “failed state” to be returned
Closing a Stream • When the program ends, all streams that you have opened will be automatically closed. • To manually close a stream: use close member function: • in_file.close(); • Manual closing a stream is necessary if you want to open the file again in the same program run.
Writing to a Stream ofstream out_file; //create output stream variable out_file.open("output.txt");// open the file if (out_file.fail()) { // check for failure to open return 0; } //write to the file out_file << name << " " << value << endl; out_file << "CONGRAUTLATIONS!!!" << endl; //close the file out_file.close();
Writing Text Output • Use operator >> to write strings and numbers to an output stream ofstream out_file; out_file.open("output.txt"); if (in_file.fail()) { return 0; } out_file << name << " " << value << endl; • To write a single character: use put method: char ch; out_file.put(ch);
Passing Streams to Functions • Always pass a file stream variable to a function by reference • E.g., to read and return a vector of quiz questions: • vector<string> read_quiz (ifstream & in_file) • Both reading and writing operations on file modify stream variable • Stream variable is not the same thing as the disk file • Also keeps pointer to the current location into the file
Reading Text Input • There are more ways to read from streamvariables than you have seen before,and there are some details you need to understand. • These follow…
Reading strings What really happens when reading a string? string word; in_file >> word; • all whitespace characters are skipped(whitespace characters include: '\t' '\n' ''). • first non-whitespace character is added to word. More characters are added until either another whitespace occurs, or end of the file has been reached.
Reading A Whole Line: getline • getline() function: read a whole line up to the next newline character. stream to read from string to read into string line; getline(in_file, line); stops at '\n', the \n is taken from the stream and thrown away, i.e., not stored into the string line Until next newline character, all whitespace and all other characters are taken and stored into the string – except newline character – which is “thrown away”
Reading A Whole Line: getline • getline function • Return true, if it’s successful • Return false if it fails. • To process a whole file line by line: string line; while( getline(in_file, line)) { // Process line, such as save the //question to the vector of quizzes }
Processing a File Line by Line • Reading one line and then processing that line,taking it apart to get individual pieces of data from it • For example: a world population file Each line has: country name, its population, a newline character. (And there is some whitespace in there too.) China 1330044605 India 1147995898 United States 303824646 ...
Processing a File Line by Line To read this file line by line: // we've opened the file string line; while( getline(in_file, line)) { // Process line // extract data from line variable, // need to find out where country name ends and number // starts. }
Processing a File Line by Line // Locate the first digit of population int i = 0; while (!isdigit(line[i])) { i++; } // Find end of country name int j = i - 1; while (isspace(line[j])) { j--; }
Processing a File Line by Line string country_name = line.substr(0, j + 1); string population = line.substr(i); • But, population should be an integer, so that we can perform arithmetic operations on it • How to extract integer value from a string ? • recall that we can extract from standard input, or more generally, stream variable: int population; cin >> population; • Solution: use string stream, which we will talk about shortly
Reading Characters It is possible to read a single character – including whitespace characters. char ch; in_file.get(ch); The get method also returns the “not failed” condition: while (in_file.get(ch)) { // Process the character ch }
Reading File Character by Character to process a whole file one character at a time: char ch; while (in_file.get(ch)) { // Process the character ch }
Not Wanting What You .get() That which was got can be ungot! in_file.unget(); • You can look at a character after reading it and then put it back after if you so decide. • However you can only put back the very last character that was read. • This is called one-character lookahead.
Reading a Number A typical situation for lookahead is to look for numbers before reading them so that a failed read won’t happen: char ch; in_file.get(ch); if (isdigit(ch)) // Is this a number? { // Put the digit back so that it will // be part of the number we read in_file.unget(); // Read integer starting with ch int n; in_file >> n; }
STREAM ADAPTERS • To “extract” information held in a string • adaptstring type to have the same interface as stream types • use >> and << on strings string stream variable string variable
The istringstream Type • To extract month name, day, and year from a string "January 24, 1973“ • Use a istringstream variable named strm • #include <sstream> • istringstream strm; • strm.str("January 24, 1973"); • string month; • int day; • string comma; • int year; • strm >> month >> day • >> comma >> year; strm “January 24, 1973”