title: using getline to parse a string and put it into a linked list c++
body: <p>I have been tasked with writing the classic "shopping cart" linked list project in c++. Each of my nodes has an itemname, an itemcost, and a next. I use a function called insertNode(string name, double cost) that builds the list in alphabetical order. The input is a text file where the first line is the budget and every line after that is in the form of "Itemname, itemcost". I use getline() and stringstream to read the lines of the file and check if it is a string or a number. It works well until I hit a line with an item that is two words (ex: "Ice cream, 4.50"). Visual Studios tells me that it throws a "read access violation" exception, . I haven't had any luck googling my problem because it's so specific (keeping white space in string parse + reading string from file + putting it into a linked list). If y'all could give me any direction (+ any general coding tips) it would be greatly appreciated!! This is the last thing I have left on this assignment. Apologies for poor formatting, I'm kinda new here!</p>
  
  <p>Example input (in a .txt file):</p>
  
  <p>15.00<br>
  Apples, 1.50<br>
  Broccoli, 2.00<br>
  Yogurt, 4.00<br>
  Chocolate, 3.80<br>
  Paper towels, 2.20<br>
  Milk, 1.70<br>
  Ice cream, 4.50  </p>
  
  <p>main.cpp:</p>
  
  <pre><code>//  main.cpp
  #include &lt;iostream&gt;
  #include &lt;cstdlib&gt;
  #include &lt;cstring&gt;
  #include &lt;fstream&gt;
  #include &lt;iomanip&gt;
  #include &lt;string&gt;
  #include "List.h"
  
  bool isNum(string);
  using namespace std;
  
  int main(int argc, char * argv[]) {
  
  string infilename = ("1.txt");
  string outfilename = ("output.txt");
  
  ifstream infile;
  
  List list;
  double budget = 0;
  string iname;
  double iprice = 0;
  
  infile.open(infilename.c_str());
  
  if (infile.fail()) {    //check for file failure (did not open)
      exit(1);
  }
  
  string temp;
  getline(infile, temp);  //grab the budget, catch exceptions
  try {
      budget = stod(temp);
      if (budget &lt; 0)
          throw - 3;
  }
  catch (int e) {
      return -1;
  }
  catch (...) {
      cerr &lt;&lt; "No budget given. Exiting";
      return -1;
  }
  
  string line = "";
  string tempdata;
  bool proceed = true;
  double tempcost = 0;
  
  while (!infile.eof()){
      getline(infile, line);
      istringstream ss;   //create ss object
      ss.str(line);       //converts string to stringstream
      if (isNum(line)) {  //is line a number (price)?
          proceed = false;    //yes, is the end of the line
      }
  
      if (proceed) {          //no, "import" name &amp; cost using stringstream
          getline(ss, line, ',');
          getline(ss, tempdata);
          bool duplicated = list.isDuplicate(line);   //checks if name is already included in the list
  
          try {
              if (!duplicated &amp;&amp; stod(tempdata) &gt; 0) {        //make sure the item doesn't already exist &amp; the price is a positive number
                  tempcost = stod(tempdata);
                  list.insertNode(line, tempcost);    //everything looks great, add it to the list
              }
          }
          catch (...) { /* price is not a number, item is already in list*/
          }
      }
      proceed = true;
  
  }
  infile.close();
  
  cout &lt;&lt; "unaltered, sorted list: " &lt;&lt; endl;
  list.displayList();
  cout &lt;&lt; endl;
  
  return 0;
  }
  
  bool isNum(string s) {
  int n = s.length();
  char char_array[50];
  strcpy_s(char_array, s.c_str());
  
  for (int i = 0; i &lt; n; i++) {
      if (!isdigit(char_array[i])) {
          return false;
          break;
      }
      return true;
  }
  </code></pre>
  
  <p>List.h:</p>
  
  <pre><code>// List.h
  // hw1
  #ifndef LIST_H
  #define LIST_H
  
  
  #include &lt;cstdlib&gt;
  #include &lt;string&gt;
  using namespace std;
  
  
  class List {
  private:
  
  typedef struct Node {   //creates node architecture
      double itemcost;
      string itemname;
      Node* next;
  }* ptr;
  
  ptr head;
  ptr current;
  ptr temp;
  ptr tail;
  int count;
  
  
  public:             // where functions go
  List();
  void insertNode(string addName, double addCost);
  bool isEmpty();
  bool isDuplicate(string name);
  void displayList();
  
  };
  
  
  #endif /* LIST_H */
  </code></pre>
  
  <p>List.cpp:</p>
  
  <pre><code>#include &lt;cstdlib&gt;
  #include &lt;iostream&gt;
  #include &lt;fstream&gt;
  #include &lt;iomanip&gt;
  #include "List.h"
  
  using namespace std;
  
  List::List() {
  head = NULL;
  current = NULL;
  temp = NULL;
  tail = NULL;
  count = 0;
  }
  
  void List::insertNode(string addName, double addCost) {
  ptr nodePtr;
  ptr previous = NULL;
  bool spotFound;
  
  ptr incomingNode = new Node;
  incomingNode-&gt;itemcost = addCost;
  incomingNode-&gt;itemname = addName;
  incomingNode-&gt;next = NULL;
  
  if (head == NULL) {         //does a list exist already? No
      head = incomingNode;    //since there is no list, incomingNode becomes head &amp; tail
      tail = incomingNode;
      count++;
  }
  else {                      //yes, list exists
      nodePtr = head;
      spotFound = false;
  
      while (!spotFound &amp;&amp; nodePtr != NULL) {                   //start at head
          if (nodePtr-&gt;itemname &gt;= incomingNode-&gt;itemname) {    //is the cost of the current node more than or equal to the incomingNode?
              spotFound = true;
          }
          else {
              previous = nodePtr;
              nodePtr = nodePtr-&gt;next;
          }
      }
      if (nodePtr == head) {          //is the current the head?
          incomingNode-&gt;next = head;  //yes, the incomingNode inserts itself in front of the head
          head = incomingNode;        //the incomingNode now labels itself as head
          count++;
      }
      else {                              //current is not the same as the head
          previous-&gt;next = incomingNode;  //the incomingNode gets pointed to by the node after the current (nodePtr)
          incomingNode-&gt;next = nodePtr;   //the incomingNode now points to the current one (nodePtr)
          if (nodePtr == NULL){       //is the current node NULL?
              tail = incomingNode;    //if yes, then the incomingNode is actually the last in the list (tail)
          }
           count++;
      }
  
  }
  }
  
  bool List::isEmpty() {
  if (count == 0)
      return true;
  else
      return false;
  }
  
  bool List::isDuplicate(string name) {
  temp = head;
  while (temp != NULL) {
      if (temp-&gt;itemname == name) {
          return true;
      }
      else {
          temp = temp-&gt;next;
      }
  }
  return false;
  }
  
  
  void List::displayList() {
  ptr curr = head;
  while (curr) {
      cout &lt;&lt; curr-&gt;itemname &lt;&lt; ", " &lt;&lt; curr-&gt;itemcost &lt;&lt; endl;
      curr = curr-&gt;next;
  }
  }
  </code></pre>