Searching for values in strings

closed account (NCRLwA7f)
Hello, I am new to string manipulation and I am having a difficult time searching for values in another string.
I have successfully transferred the data from elements from a .txt document into a linked list. I have to now read in another text file with some formulas and match it up to my linked list to calculate my data.

the Data:
In my linked list I have the abbreviation of an element name and then atomic weight:

the data looks like this:

Al 24.305
Na 1.0080
K 18.9984
Te 196.9665
V 126.9045
Fe 55.847
Br 1.334
C 3.5642

1
2
3
4
5
6
struct node
      {
	string eName;
	double eWght;
	node *point;
       };



Now I have to read in another document with the formulas and calculate the molecular weight of the combined elements.

Formula Doc:

Al(2)O(3)SiO(2)
AgBr
NiC(4)H(6)O(4)
Na(2)VO(4)
Na(3)P(5)O(4)
TeCl(4)
V(2)O(5)
K(2)Cr(2)O(7)

my problem is how to read in the data and compare it to my linked list.
I'm confused if I should use getline() or inFile.get(), or inFile >>
Also, once I have the data how can I split it up to compare?
I need help coming up with a molecular weight function.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <iostream>
#include <fstream>
#include <string>
#include <cstdlib>
#include <cctype>

using namespace std;

struct node
{
    string eName;
    double eWght;
    node *point;
};

node *Alpha = nullptr;



node *NEW_NODE();
void BUILD_LIST(node *elements);
void MOLECULAR_WEIGHT(node *elements);


	ifstream inElem;
	ifstream inForm;

int main()
{
	inElem.open("Elements.txt");
	inForm.open("Formulas.txt");
		
	node *elements = nullptr;
     // double molecularWgt = 0.0; // possible use, not sure if my fuction will be void or double 
		
	BUILD_LIST(elements);
	MOLECULAR_WEIGHT(elements);
	
	inElem.close();
        inForm.close();
		

return 0;
}

node *NEW_NODE()
{
   node *temp = nullptr;
		
   temp = new node;
   temp->eName = '\0';
   temp->eWght = 0.0;
   temp->point = nullptr;
		
   return temp;
}


void BUILD_LIST(node *elements)
 {
node *temp = nullptr;
	
  elements = NEW_NODE();
  Alpha = elements;
  temp = elements;
  inElem >> elements->eName;
  inElem >> elements->eWght;
		
	while(!inElem.eof())
	{
	  elements = NEW_NODE();
	  inElem >> elements->eName;
	  inElem >> elements->eWght;
	  temp->point = elements;
	  temp = elements;
	}

  elements = NEW_NODE();
  elements = nullptr;
  temp->point = nullptr;
}

void MOLECULAR_WEIGHT(node *elements)
{
  //Some way to calculate the weight
	
}


note: The formula and molecular data are not "correct" it's only for running the program.
Thank you for the help.
Last edited on
@DaRealFonz,
Why store your element/atomic-weight pairs in a linked list?

Why not store them as map<string,double> MyMap;

Then you could simply access the atomic weight of aluminium as
MyMap["Al"],
or for any string element:
MyMap[element]
Last edited on
closed account (NCRLwA7f)
I am not familiar with that, but that sounds way better. How exactly does that work?

Also, I have been given the restriction to only use linked list :(
Formula doc looks like one hell of a file because the numbering pattern in not consistent. for eg. AgBr would have been better represented as Ag(1)Br(1) and TeCl(4) as Te(1)Cl(4) so that same code for the other lines could be used. The way it is now makes parsing unnecessarily messy
closed account (NCRLwA7f)
yes, I agree with you on that gunnerfunner. How could the file be parsed if it did have (1) for all the single elements? I could probably come up with a separate function to take care of the singles.
Last edited on
How exactly does that work?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>
#include <fstream>
#include <string>
#include <map>
using namespace std;

int main()
{                                   
   map<string,double> WtMap;
   string element;
   double weight;

   ifstream in( "elements.txt" );
   while ( in >> element >> weight ) WtMap[element] = weight;
   in.close();

   for ( auto e : WtMap ) cout << e.first << '\t' << e.second << endl;

   cout << "The relative atomic mass of Aluminium is " << WtMap["Al"] << endl;
}
Al	26.982
B	10.811
Be	9.012
C	12.011
F	18.998
H	1.008
He	4.003
Li	6.941
Mg	24.305
N	14.007
Na	22.99
Ne	20.18
O	15.999
The relative atomic mass of Aluminium is 26.982


I have been given the restriction to only use linked list :(

That is a crying shame. You are associating a number ... with a name ... and an associative container ... is called a map, not a list.


It is straightforward to parse a molecular formula in this notation. You can break it down into components ... at each UPPER-CASE letter.

Suggestion:

(1) Read a line into a string - e.g. "NiC(4)H(6)O(4)"

(2) Remove blanks for convenience (erase-remove idiom)

(3) Tokenise into a vector of strings by cutting at each new upper-case letter; e.g.
Ni
C(4)
H(6)
O(4)

(4) Start a sum for the molecular mass.

(5) For each of the tokenised strings, search for '('.

(6)(i) If it has no '(' then just use the Rel. At. Mass of that element and add to the sum.
(ii) Otherwise stringstream the substring after the bracket into an int; it will ignore ')'. Use this to add the appropriate number of times the mass of the base element to the sum.


You could probably also use a regex - but that is not something I can offer advice on.
Last edited on
Topic archived. No new replies allowed.