How to Read a Line an Parse in C++

CS330 C++ File I/O and Parsing Line Input


Highlights of this lab:

  • C++ File IO
  • Reading a Line from Input
  • C String Versus String
  • Splitting C Strings into Tokens
  • Dynamic Arrays of C Strings
  • Review of Creating a Course in C++
  • References

C++ File IO

There are three predefined streams in C++:

  • cin
  • cout
  • cerr

Note: make sure you have #include<iostream> and have used "using namespace std;" at the start of the program.

To open a file for reading, you can use lawmaking like the following:

ifstream inFile("name", ios::in);

To open a file for output, you can utilise lawmaking similar:

ofstream outfile("proper noun", ios::out);

Make certain you have #include<fstream> before using these functions.

To input a character from an input stream, use the go() office:

char ch; inFile.get(ch);

To output a character, apply the put() function:

outFile.put(ch);

Here is a sample program that gets characters from standard input and puts them into the file copy.out

#include <fstream>  int main() {    //open up a file copy.out for output    ofstream outFile("re-create.out");     if (! outFile)    {       cerr << "cannot open \"copy.out\" for output\due north";       return -ane;    }     char ch;    while (cin.get(ch))       outFile.put(ch); }      
To open a file for input just, an ifstream course object is used.
#include <fstream>  int main() {    cout << "filename: ";    string file_name;    cin >> file_name;     //open a file copy.out for input    ifstream inFile(file_name.c_str() );     if (! inFile)    {       cerr << "unable to open input file: " 	   << file_name << " --bailing out! \n";       return -1;    }     char ch;    while (inFile.get(ch))       cout.put(ch); }      

Reading a Line from Input

The above section described single grapheme I/O. Often yous want to read a line at a time. The function to practice that is getline. There are two versions of getline:

  1. For reading C strings.
    The prototypes are:
    istream& getline (char* s, streamsize n); istream& getline (char* s, streamsize n, char delim);          
    For the latter prototype, if you want your lines to be delimited past something other than than a '\n' (the default), then you tin can specify this as a tertiary, delim, statement. The following is an example that uses the first prototype to read a line at a fourth dimension of a file and repeat it to standard output:
    #include <iostream> #include <fstream> using namespace std;  const int MAXLINE=256;  int main() {    ifstream inFile ("examination.txt");    char oneline[MAXLINE];     while (inFile)    {        inFile.getline(oneline, MAXLINE);        cout << oneline << endl;    }     inFile.close();     return 0; }
    Notes:
    • the C string getline is a member part (yous use inFile.getline).
    • the 2d statement is the number of characters you can read in. It will simply ever read in up to MAXLINE - ane and so that there is room to store '\0' in the last spot of the character array.
    • if you meet a line that is more than 256 characters, reading from the file will terminate. (You lot tin use member function, clear, to go along reading).

  2. For reading strings.
    The prototypes are:
    istream& getline (istream& is, cord& str); istream& getline (istream& is, cord& str, char delim);          
    One time again, you can specify a delimiter other than '\n'. The following is an example that uses the first paradigm to read one line at a time and echo information technology to standard output:
    #include <iostream> #include <fstream> #include <cord> using namespace std;  int main() {     ifstream inFile("test.txt");     string strOneLine;      while (inFile)     {        getline(inFile, strOneLine);        cout << strOneLine << endl;     }      inFile.close();      return 0; }          
    Notes:
    • getline for reading strings is useful if you suspect that you lot will have longer lines, since strings are dynamically allocated.
    • this getline is implemented every bit a global function instead of as fellow member of the stream course

C Cord Versus Cord

It'southward probably been a long time since you've idea nigh C strings and strings. The post-obit sections is meant to give you lot a review on these two programming topics.

C Strings

C strings are based on the "old" C way of creating a string. Just because the word old is used doesn't mean that C strings aren't used and useful. There are times and places where you lot see C strings and it's very practiced to know these foundations.

A C string is an array of characters that is nothing terminated. Functions that are used with C strings include:

  • strlen(const char *s)

Returns the length of the string s (the length does non include the terminating zilch character)
  • strcpy(char *s1, const char *s2)

Copies the string s2 into cord s1, including the terminating null graphic symbol. The programmer must ensure that s1 points to enough space to hold the issue.
  • strncpy(char *s1, const char *s2, size_t n)

Copies n characters (or until the null terminator has been encountered) from string s2 to cord s1. If s2 has less than north characters, so s1 will be padded with '\0' up to n.

The following lawmaking provides examples of different means of creating C strings and the apply of the functions listed above:

#include <iostream> #include  <cstring> using namespace std;  int main() {    char s1[four]="1"; //recall there will exist one space for null terminator    char s2[]="two";    char s3[4];    char *s4;         //s4 will bespeak to the first of the array of chars    char s5[6];     //Assigning characters to s3    s3[0]='b';    s3[1]='a';    s3[2]='t';    s3[three]='\0';      //Need to classify space otherwise get core dump when do strcpy. Two ways:    //s4=new char[6];               //specify size direct    s4=new char[strlen("hello") + 1];   //utilise strlen to determine size     //Copy the strings    strncpy(s4,"hello",6);        // specify the size of the string + 1 for null       //s5="good day";   // 21: error: ISO C++ forbids assignment of arrays. Instead:    strncpy(s5, "bye", (strlen("bye") + 1));      cout << s1 << endl;    cout << s2 << endl;    cout << s3 << endl;    cout << s4 << endl;    cout << s5 << endl;     //make clean up infinite allocated for s4    delete [] s4;     return 0; }      

The output:

one two bat hello good day      

The following is a diagrammatic representation of the C Strings created in the in a higher place program:

A POSIX Shortcut

This snippet from the example above:

        s4=new char[strlen("how-do-you-do") + i];   //use strlen to determine size    //Re-create the strings    strncpy(s4,"howdy",6);        // specify the size of the string + 1 for nothing      //...     delete[] s4;      
or the C version:
        s4= (char*)malloc(strlen("howdy") + one);   //use strlen to determine size    //Copy the strings    strncpy(s4,"hello",6);        // specify the size of the cord + 1 for null     //...     free(s4);      
is so common that an efficient shortcut was included in the POSIX standards. It is non a part of the C or C++ standard. If you lot are lucky plenty to be programming on a POSIX compliant OS such as Linux (the lab) or Solaris (Hercules) or Mac OS Ten 10.5 and so yous can simplify the snippet in a higher place with this role:
  • strdup(const char *s)

returns a pointer to a new string that is a duplicate of the cord pointed to by s. The returned arrow should be released with free() considering the space for the new string is obtained using malloc. If the new string cannot be created, a nix pointer is returned.

The above snippets would then look like this:

        s4=strdup("how-do-you-do");   //make copy of "how-do-you-do"     //...     costless(s4);      
and because there is only one role call instead of three, the compiled code is probable more efficient.

Notes:

  • When yous allocate space for a character array, e'er remember to count the space taken up past the null terminator "\0"
  • You lot cannot do assignment as in:
    char s5[half dozen];     s5="adieu"; // **WRONG**
    Y'all must instead use the strncpy part. (Or the strdup role if it is available.)
  • Don't forget to release any memory you asking while copying strings subsequently you lot are done using information technology.
  • In C code, when you use C String functions, yous will employ
    #include <string.h>
    In C++, when you use C String functions, you volition see instead:
    #include <cstring>
  • In C code, when you use malloc and free functions, you volition use
    #include <stdlib.h>
    In C++, when you employ malloc and free you volition see instead:
    #include <cstdlib>

Strings

In C++, strings are objects. As such, the functions associated with strings are member functions (such as str.length()). The following code provides example of the different ways that y'all can create strings (with different constructors):

#include <iostream> #include <string> using namespace std; // For a list of constructors see: // http://world wide web.cppreference.com/cppstring/string_constructors.html  int main() {    cord str1="one";    string str2("two");    string str3;    string str4(str1);    string str5(eight,'a');    string str6(str2,ane);    string str7(str2,1,i);     str3="hello";     //show the employ of the length function    cout << "The length of '" << str3 << "' is: " << str3.length() << endl;     //evidence the use of the suspend function    cout << "str6 earlier: " << str6 << endl;    //The version of append used here is:    //string& append( const string& str, size_type index, size_type len );    str6.append(str1,i,1);    cout << "str6 afterwards: " << str6 << endl;     //show the utilise of the + (concatenation) operator    cout << "str1 earlier: " << str1 << endl;    str1=str1 + ", " + str2;    cout << "str1 afterward: " << str1 << endl;     cout << str1 << endl;    cout << str2 << endl;    cout << str3 << endl;    cout << str4 << endl;    cout << str5 << endl;    cout << str6 << endl;    cout << str7 << endl;     render 0; }

The output:

The length of 'howdy' is: 5 str6 earlier: wo str6 after: won  str1 earlier: i str1 subsequently: one, 2  1, 2 two hello one aaaaaaaa won w      

Notes:

  • With C++ strings yous do not have to worry nigh allocating space and ending the string with the nada terminator.
  • You tin can still travel through the string using the index note equally in:
                cout << "Cycling through one character at a time" << endl;    for(int i=0; i<str1.length(); i++)    {       cout << str1[i];    }
  • If yous ever want to (which you might want to for this lab practice--HINT HINT), y'all can use a part c_str to alter a string into a graphic symbol assortment:
                cord str3;     str3= "hello";     char *cstr2;    cstr2=new char[str3.length() + 1];      strncpy(cstr2, str3.c_str(), (str3.length() + 1));    cout << "cstring2 " << cstr2 << endl <<endl;         //At end, clean upwardly space allocated for cstr2    delete [] cstr2;

Splitting C Strings into Tokens

Sometimes you may want to split a line into tokens or words. To do that, there is a C Cord function chosen strtok. The prototype is:
char * strtok (char * str, const char * delimiters)
where str is the line (or C cord) that yous want to split into tokens or words, and delimiters are an array of characters in which any one of the characters delimits or marks the boundaries between words.

The following is an example of using strtok:

#include <iostream> #include <cstring> using namespace std;  int master(int argc, char *argv[]) {    char cstr1[]="This is a sample string. Is information technology working?";    char delim[]=" ,.-;!?";    char *token;     cout << "cstr1 earlier beingness tokenized: " << cstr1 << endl << endl;     //In the get-go call to strtok, the starting time argument is the line to be tokenized    token=strtok(cstr1, delim);    cout << token << endl;      //In subsequent calls to strtok, the outset argument is Nada    while((token=strtok(Goose egg, delim))!=NULL)    {          cout << token << endl;    } }

The output:

cstr1 earlier being tokenized: This is a sample cord. Is it working?  This is a sample cord Is it working      

At that place are a couple of "catches" with strtok:

  1. In the outset call to strtok, the outset statement is the line or C string to be tokenized; in subsequent calls to strtok, the starting time statement is NULL. Find the two calls from the lines to a higher place:
    • token=strtok(cstr1, delim)
    • token=strtok(Nix, delim)
  2. The original C string is modified when it is tokenized then that delimiters are replaced by zilch terminators ('\0'). The post-obit represents what the C string in the sample lawmaking will look like afterwards tokenizing:

Dynamic Arrays of C Strings

Sometimes you want to have a dynamically created assortment of C Strings. The following code demonstrates this:

#include <iostream> #include <cstring> using namespace std;  int master () {   char **words;   char endWord[]="330!";    words = new char *[4]; //allocate pointers to four words    //words[0] to words[ii] are assigned constant strings.  For variable   //consignment, you should classify space and then employ strncpy    //(every bit washed for words[three])   words[0] = "hello";   words[one] = "in that location";   words[2] = "CS";    words[three] = new char[strlen(endWord) +ane];   strncpy(words[3],endWord,(strlen(endWord)+1));    for (int i=0; i<4; i++)   {      cout << words[i] << endl;   }    //Make clean upward everything that you allocated:   delete [] words[iii];  // cleans upward words[3]= new char[strlen(endWord +one];    delete [] words;     // cleans upwards words = new char *[4]; }

Review of Creating a Course in C++

In previous computer science classes, you have learned that the typical design of C++ programs is to have ii files when you create a class:

  • .h file -- provides an overview of the class including the public and individual members. Typically only the prototypes of the functions are in here.
  • .cpp file -- provides the implementation of the functions

In one case you have the grade divers, then you lot demand a master function to exam the code. Good programming practice involves putting the main function in a dissever file. This makes a total of three files.

If you accept been working in Java or any other programming languages, you may exist foggy on the C++ syntax. The following is an example of a Circle class with a principal.cpp file used to exam this lawmaking.

circle.h

#include <iostream> using namespace std; #define PI 3.14159  grade Circle {    public:       //Constructors       Circle();       Circle(double radius);        //Functions       double getRadius();       istream &readRadius(istream& is);       void setRadius(double radius);       double getArea();       double getCircumference();     individual:       double radius; };

circle.cpp

#include "circle.h"  //Constructors. If no radius is specified, the default is 5. Circle::Circumvolve() {    radius = 5.0; } Circle::Circle(double radius) {    //considering the data member is also called radius, you need to use "this->"    this->radius=radius; }   //Functions double Circumvolve::getRadius() {    return radius; }  //Read the radius from some input stream (for instance cin or an ifstream object) istream& Circle::readRadius(istream& is) {    is >> radius;    render is; }  void Circle::setRadius(double radius) {    this->radius=radius; }  double Circle::getArea() {    render (PI*radius*radius); }  double Circle::getCircumference() {    return (2*radius*PI); }

main.cpp

#include "circle.h" #include <iostream> using namespace std;  int main() {    Circle c1;    Circle c2(20.ii);    Circle c3;     cout << "Please Enter the radius for c3:  ";
c3.readRadius(cin);
cout << endl << "Details of c1:" << endl; cout << "Radius is: " << c1.getRadius() << endl; cout << "Area is: " << c1.getArea() << endl; cout << "Circumference is: " << c1.getCircumference() << endl; cout << endl << "Details of c2:" << endl; cout << "Radius is: " << c2.getRadius() << endl; cout << "Expanse is: " << c2.getArea() << endl; cout << "Circumference is: " << c2.getCircumference() << endl; cout << endl << "Details of c3:" << endl;
cout << "Radius is: " << c3.getRadius() << endl;
cout << "Area is: " << c3.getArea() << endl;
cout << "Circumference is: " << c3.getCircumference() << endl; render 0; }

To compile and run this code, y'all tin can use the following commands on the control-line:

  • yard++ -c primary.cpp
  • g++ -c circle.cpp
  • g++ -o circle chief.o circle.o
  • circle

Notes:

  • retrieve the semicolon after the closing curly subclass in the .h file
  • remember the ClassName::functionName syntax in the .cpp file

References

  • http://www.cplusplus.com/reference/iostream/istream/getline.html -- more than near getline for C strings
  • http://world wide web.cplusplus.com/reference/cord/getline.html -- more than about getline for strings
  • http://www.cppreference.com/cppstring/index.html -- contains a listing of functions for C++ strings
  • http://www.cppreference.com/cppstring/string_constructors.html -- lists the C++ string constructors
  • A Book on C past Al Kelley and Ira Pohl

cassidybeggermse.blogspot.com

Source: https://www.cs.uregina.ca/Links/class-info/330/ParsingLine/parsingline.html

0 Response to "How to Read a Line an Parse in C++"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel