I hope someone can help me again with this issue. I am creating a HTML lexical analyzer in c++. According to the teacher I am supposed to have 3 files. one header and 2 main .cpp and it should be able to read a file
This is my file try.txt
<<<<<Hello there <H1 style=”BOLD”>header!!</H1>
<<
<< =
This is my header
#ifndef tokens_h
#define tokens_h
#include <string>
#include <iostream>
enum tokens {TEXT, LANGLE = 60, RANGLE = 62, SLASH = 47, ID, EQ = 61, QSTRING = 34, OTHER, END};
/* TEXT = 0
LANGLE = 60
RANGLE = 62
SLASH = 47
ID = 48
EQ = 61
QSTRING = 34
OTHER = 36
END = 36
*/
int getToken(std::istream *br, std::string a);
#endif
This is my main.cpp
#include <iostream>
#include <fstream>
#include <vector>
#include "tokens.h"
using namespace std;
int main(int argc, char *argv[])
{
//defineTokens();
istream *br;
ifstream infile;
string output;
int a;
vector<int> count;
int langle = 0;
string line;
if(argc == 1){
while(cin.good() ){ //Get continous input
br = &cin;
getline(cin,line);
getToken(br,line);
}
}
else if(argc != 2){
return 1;
}else{
infile.open(argv[1]);
if( infile.is_open()){
br = &infile;
while(!infile.eof()){
getline(infile,output);
getToken(br,output);
}
}
else{
cout << argv[1] << "Can't Be Opened" << endl;
return 1;
}
}
}
and this is my tokens.cpp where I print the results
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include <map>
#include <utility>
#include "tokens.h"
using namespace std;
void compar(int ch)
{
vector<int> text;
vector<int> langle;
//string langle;
vector<int> rangle;
vector<int> slash;
vector<int> id;
vector<int> eq;
vector<int> qstring;
vector<int> other;
map <string, int> result;
int c=0;
int d=0;
int sum;
string r;
switch(ch){
case 60:static int countlangle = 0;
countlangle ++;
result["LANGLE"]= countlangle;
cout << "LANGLE: " << result["LANGLE"] << " ";
break;
case 62:static int countrangle = 0;
countrangle ++;
result["RANGLE"]= countrangle;
cout << "RANGLE: " << result["RANGLE"] << " ";
break;
case 47:static int countslash = 0;
countslash ++;
result["SLASH"]= countslash;
cout << "SLASH: " << result["SLASH"] << " ";
break;
case 61:static int counteq = 0;
counteq ++;
result["EQ"]= counteq;
cout << "EQ: " << result["EQ"] << " ";
break;
case 34:static int countqstring = 0;
countqstring ++;
result["QSTRING"]= countqstring;
cout << "QSTRING: " << result["QSTRING"] << " ";
break;
}
}
int getToken(istream *br, string a)
{
int b;
string d = "no";
string f = "no";
string r;
vector<char> st;
vector<string> trial;
vector<int> countr;
vector<int> countl;
vector<char> quotes;
string ans;
int x=0;
r = a;
cout << a[27];
int found;
found = a.find('\"');
cout << found<<"XXxxxxxX";
for(int i = 0; i< a.length();i++){ //read entire string
if(a[i] == '<'){
// cout << LANGLE << " ";
d="yes";
x +=1;
countr.push_back(LANGLE);
//cout << count.size();
//cout << x;
compar(LANGLE);
b =LANGLE;
// return LANGLE;
}
else if(a[i]== '>' && d == "yes"){
f = "yes";
b = RANGLE; //assing to the int variable the value from the enum header
compar(RANGLE);
}
else if(a[i]== '/' && d == "yes"){
compar(SLASH);
}
else if(a[i] == '=' && d == "yes"){
compar(EQ);
}
else if(a[found] == '\"' && d == "yes"){
// for(int k =0;k < quotes.size();k++)
//cout << r[found] <<"XXX";
compar(QSTRING);
}
}
return 0;
}
The teacher want the program to print just the Final value of each case. However, when I print I get this
LANGLE: 1 ID: 1 EQ: 1 ID: 2 RANGLE: 1 ID: 3 LANGLE: 2 SLASH: 1 RANGLE: 2 LANGLE: 3 ID: 4 RANGLE: 3 LANGLE: 4 LANGLE: 5 LANGLE: 6 ID: 5 RANGLE: 4 LANGLE: 7 LANGLE: 8 EQ: 2
Is there any way to get something like this?
LANGLE = 8
RANGLE = 4
EQ = 2
SLASH = 1
ID = 4
thanks in advance
You are calling the compar() function multiple times, and printing the current count of token in every call.
This will give you every intermediate value of the count of each token.
Try to modify your compar() function to only increment the counts. DO NOT print values in it. Once the entire contents have been parsed, print the token value pairs by iterating over the map.
Related
I am trying to get some values line by line from a text file:
17.09 284.60 486.01 34.12 12.04 1.20 2.33 36.85 73.44
31.25 196.09 323.26 69.76 47.33 79.82 11.42 27.97 66.61
28.76 41.45 992.29 1.29 42.33 10.83 19.16 5.86 1.88
Taking these values and putting it into a vector. Each row has values to be used in a calculation.
My code:
#include <iostream>
#include <fstream>
#include <string>
#include <iterator>
#include <vector>
using namespace std;
int main() {
ifstream xfile;
string input;
double num=0;
int count = 0;
vector <double> myvector;
cout << "Input the file: ";
cin >> input;
xfile.open(input);
if (xfile.is_open()) {
cout << "File accessed!" << endl;
while (getline(xfile, input)) {
count++;
myvector.push_back(num);
}
}
else {
cout << "File opening failed!"<<endl;
}
cout << "Numbers of lines in the file : " << count << endl;
for (int i = 0; i < myvector.size(); i++) {
cout << myvector[i] << "\t";
}
cin.fail();
return 0;
}
My output is somewhat correct, only that it is printing out just zeroes:
https://ibb.co/xqwT1hR
EDIT: the input is for the name of file. "ahu_long.txt"
You never used your num variable.
double num=0;
....
....
size_t pos = 0;
std::string token;
while (getline(xfile, input)) {
count++;
// you need convert your "input" to a double and save it to "num"
while ((pos = input.find(" ")) != std::string::npos) {
token = input.substr(0, pos);
// std::cout << token << std::endl;
num = atof(token.c_str());
myvector.push_back(num);
input.erase(0, pos + delimiter.length());
}
}
Change your variable with what you read from the file.
I'm trying to find a way to display all the characters in a string and the number of times they occur.
This is what I have so far:
//Any unused includes are part of the default code
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <cmath>
#include <string>
using namespace std;
int main()
{
string st = "";
cout << "Input a sentence: " << endl;
getline(cin, st);
int index = 0;
int index2 = 0;
int counters[26] = {0};
for(int i = 0; i < st.length(); i++)
{
int counter = 0;
index = st.find(st[i],0);
for(int j = 0; j < st.length(); j++)
{
index2 = st.find(st[j]);
if(index == index2)
{
counter++;
}
}
cout << st[i] << ": " << counter << endl;
}
//cout << st[i] <<": " << counters[st[i] - 'a'] << endl;
return 0;
}
and I return this:
Input a sentence:
hello
h: 1
e: 1
l: 2
l: 2
o: 1
so I kind of have something but I can't figure out how to make the letters not repeat more than once. I know that I need to store them in an array but it's out of my ken.
You were very close, nice try! I liked the approach with the counters array, where every cell would represent the frequency of a letter in the given string.
So, just go and update this array, as this answer implies How to get character's position in alphabet in C language?, without the plus one they mention there, since you want the index of the letter in your array. In other words, for 'a', you need 0, 'b', you need 1 and so on.
Then, in the printing phase, just use the above link's suggestion in the reverse way. When you print the i-th non-zero element of counters, print the i-th element of the element, which will reveal the letter in question.
Putting all together, you get:
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <cmath>
#include <string>
using namespace std;
int main()
{
string st = "";
cout << "Input a sentence: " << endl;
getline(cin, st);
int index = 0;
int index2 = 0;
int counters[26] = {0};
for(size_t i = 0; i < st.length(); i++)
{
int counter = 0;
index = st.find(st[i],0);
for(size_t j = 0; j < st.length(); j++)
{
index2 = st.find(st[j]);
if(index == index2)
{
counter++;
}
}
counters[st[i] - 'a'] = counter; // update 'counters' array
}
for(int i = 0; i < 26; ++i)
if(counters[i] != 0) // print non-zero counters
cout << (char)(i + 'a') << ": " << counters[i] << endl;
return 0;
}
Output:
e: 1
h: 1
l: 2
o: 1
I would do something like this:
#include <iostream>
#include <map>
#include <string>
int main()
{
std::string st;
std::cout << "Input a sentence: " << std::endl;
std::getline(std::cin, st);
std::map<char, int> m;
for (const char c : st)
++m[c];
for (const std::pair<char, int>& me : m)
std::cout << me.first << ": " << me.second << std::endl;
}
lechuga2000 beat me to the post, but this is my suggestion:
#include <iostream>
#include <map>
#include <string>
int main()
{
std::string input_sentence = "Now is the time for all good men to come to the aid of the party.";
/*
std::cout << "Input a sentence: " << std::endl;
std::getline(std::cin, input_sentence);
*/
std::map<char, int> character_counts;
for (const auto character : input_sentence)
++character_counts[character];
for (const auto counted_character : character_counts)
std::cout << counted_character.first << ": " << counted_character.second << '\n';
return 0;
}
And here is the output:
: 15
.: 1
N: 1
a: 3
c: 1
d: 2
e: 6
f: 2
g: 1
h: 3
i: 3
l: 2
m: 3
n: 1
o: 8
p: 1
r: 2
s: 1
t: 7
w: 1
y: 1
This question already has answers here:
Convert a String In C++ To Upper Case
(31 answers)
Closed 7 years ago.
I am writing a program that can count the number of times a word is found in a external file. The words that are to be searched for are also in an external file but I am able to retrieve those just fine. I realised that it will only update the value of count if the word exactly matches. So for example if I was searching for the word "School" and the word "school" was in the textfile I don't think the value of count would be changed. I also think that count wouldn't be changed if the word to be search for was "SCHOOL" and the word in the textfile was "school". So how do I edit my if statements so that for example the word "school" would match "SCHOOL" AND "School"?
This is my main function:
#include <iostream>
#include "ReadWords.h"
#include "Writer.h"
#include <cctype>
#include <string>
using namespace std;
int main() {
int x = 9;
int count = 0;
int count0;
int count1;
int count2;
int count3;
int count4;
int count5;
int count6;
int count7;
int count8;
int count9;
int scount;
const int size = 10;
string word_search[size];
string word;
cout << "Please enter a filename: " << flush;
char filename[30];
cin >> filename;
ReadWords reader(filename);
while (reader.isNextWord()){
count = count + 1;
reader.getNextWord();
}
cout << "There are: " << count << " words in the play" << endl;
cout << "Please enter the name of the file with the search words: " << flush;
char filename1[30];
cin >> filename1;
ReadWords reader1(filename1);
scount = 0;
while (reader1.isNextWord()) {
word_search[scount] = reader1.getNextWord();
++scount;
}
cout << "" << endl;
while (reader.isNextWord()) {
This is where I attempted to convert the input to upper case to see if the word matches the uppercase version of itself but this didn't work. Here I also need to check if the word matches itself if the first letter is capital?
if (reader.getNextWord() == word_search[0] || toupper(reader.getNextWord()) == word_search[0]) {
count0 = count0 + 1;
}
if (reader.getNextWord() == word_search[1]) {
count1 = count1 + 1;
}
if (reader.getNextWord() == word_search[2]) {
count2 = count2 + 1;
}
if (reader.getNextWord() == word_search[3]) {
count3 = count3 + 1;
}
if (reader.getNextWord() == word_search[4]) {
count4 = count4 + 1;
}
if (reader.getNextWord() == word_search[5]) {
count5 = count5 + 1;
}
if (reader.getNextWord() == word_search[6]) {
count6 = count6 + 1;
}
if (reader.getNextWord() == word_search[7]) {
count7 = count7 + 1;
}
if (reader.getNextWord() == word_search[8]) {
count8 = count8 + 1;
}
if (reader.getNextWord() == word_search[9]) {
count9 = count9 + 1;
}
}
cout << "Please enter the name of the file to write to: " << flush;
char filename2[30];
cin >> filename2;
Writer reader2(filename2);
cout << "File has been written too.." << endl;
reader2.writeInt(count);
reader2.writeString("Hello my name is Joshua Ogunnote");
return 0;
}
This is a separate file where some of my functions are declared:
#include "ReadWords.h"
#include <cstring>
#include <iostream>
using namespace std;
void ReadWords::close(){
wordfile.close();
}
ReadWords::ReadWords(const char *filename) {
wordfile.open(filename);
if (!wordfile) {
cout << "could not open " << filename << endl;
exit(1);
}
}
string ReadWords::getNextWord() {
string n;
if(isNextWord()){
wordfile >> n;
int len = n.length();
for(int i = 0; i < len ; i++) {
if (ispunct(n[i]))
{
n.erase(i--, 1);
len = n.length();
}
}
cout << n << endl;
return n;
}
}
bool ReadWords::isNextWord() {
if (wordfile.eof()) {
return false;
}
return true;
}
If you're just using English, a simple tolower() transform will do.
std::string tolower( std::string s )
{
for (char& c : s) c = std::tolower( c );
return s;
}
Now you can compare them:
if (tolower( "Hello" ) == tolower( "HELLO" ))
If you are working with Unicode, you should perform a conversion called case folding on the text, and compare the resulting string data.
I hope someone can help me with this issues. I am creating a HTML lexical analyzer in c++. According to the teacher I am supposed to have 3 files. one header and 2 main .cpp and it should be able to read a file
This is my file try.txt
<<<<<Hello there <H1 style=”BOLD”>header!!</H1>
<<
<< =
This is my header
#ifndef tokens_h
#define tokens_h
#include <string>
#include <iostream>
enum tokens {TEXT, LANGLE = 60, RANGLE = 62, SLASH = 47, ID, EQ = 61, QSTRING = 34, OTHER, END};
/* TEXT = 0
LANGLE = 60
RANGLE = 62
SLASH = 47
ID = 48
EQ = 61
QSTRING = 34
OTHER = 36
END = 36
*/
int getToken(std::istream *br, std::string a);
#endif
This is my main.cpp
#include <iostream>
#include <fstream>
#include <vector>
#include "tokens.h"
using namespace std;
int main(int argc, char *argv[])
{
//defineTokens();
istream *br;
ifstream infile;
string output;
int a;
vector<int> count;
int langle = 0;
string line;
if(argc == 1){
while(cin.good() ){ //Get continous input
br = &cin;
getline(cin,line);
getToken(br,line);
}
}
else if(argc != 2){
return 1;
}else{
infile.open(argv[1]);
if( infile.is_open()){
br = &infile;
while(!infile.eof()){
getline(infile,output);
getToken(br,output);
}
}
else{
cout << argv[1] << "Can't Be Opened" << endl;
return 1;
}
}
}
and this is my tokens.cpp where I print the results
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <algorithm>
#include <numeric>
#include <map>
#include <utility>
#include "tokens.h"
using namespace std;
void compar(int ch)
{
vector<int> text;
vector<int> langle;
//string langle;
vector<int> rangle;
vector<int> slash;
vector<int> id;
vector<int> eq;
vector<int> qstring;
vector<int> other;
map <string, int> result;
int c=0;
int d=0;
int sum;
string r;
switch(ch){
case 60:static int countlangle = 0;
countlangle ++;
result["LANGLE"]= countlangle;
cout << "LANGLE: " << result["LANGLE"] << " ";
break;
case 62:static int countrangle = 0;
countrangle ++;
result["RANGLE"]= countrangle;
cout << "RANGLE: " << result["RANGLE"] << " ";
break;
case 47:static int countslash = 0;
countslash ++;
result["SLASH"]= countslash;
cout << "SLASH: " << result["SLASH"] << " ";
break;
case 61:static int counteq = 0;
counteq ++;
result["EQ"]= counteq;
cout << "EQ: " << result["EQ"] << " ";
break;
case 34:static int countqstring = 0;
countqstring ++;
result["QSTRING"]= countqstring;
cout << "QSTRING: " << result["QSTRING"] << " ";
break;
}
}
int getToken(istream *br, string a)
{
int b;
string d = "no";
string f = "no";
string r;
vector<char> st;
vector<string> trial;
vector<int> countr;
vector<int> countl;
vector<char> quotes;
string ans;
int x=0;
r = a;
cout << a[27];
int found;
found = a.find('\"');
cout << found<<"XXxxxxxX";
for(int i = 0; i< a.length();i++){ //read entire string
if(a[i] == '<'){
// cout << LANGLE << " ";
d="yes";
x +=1;
countr.push_back(LANGLE);
//cout << count.size();
//cout << x;
compar(LANGLE);
b =LANGLE;
// return LANGLE;
}
else if(a[i]== '>' && d == "yes"){
f = "yes";
b = RANGLE; //assing to the int variable the value from the enum header
compar(RANGLE);
}
else if(a[i]== '/' && d == "yes"){
compar(SLASH);
}
else if(a[i] == '=' && d == "yes"){
compar(EQ);
}
else if(a[found] == '\"' && d == "yes"){
// for(int k =0;k < quotes.size();k++)
//cout << r[found] <<"XXX";
compar(QSTRING);
}
}
return 0;
}
The program reads <>= without a problem but when I try to read a '\"' with cout << a[27];
I get this: ?
if I print cout << a;
i get <<<<<Hello there <H1 style=”BOLD”>header!!</H1> // this is the string I am trying to read
when I use found = a.find('\"'); it gives me a -1
My question is why my program cannot recognized quotes? is it the way I am reading the file?
thanks in advance
Your file contains:
”
whereas your lexer looks for:
"
These are distinct.
I have the following C++ Program:
//============================================================================
// Name :
// Author : Bryce Sandlund
// Version :
// Copyright :
// Description : Code skeleton
//============================================================================
#include <iostream>
#include <iomanip>
#include <set>
#include <vector>
#include <algorithm>
#include <cmath>
#include <complex>
#include <cstdlib>
#include <sstream>
#include <list>
#include <map>
#include <fstream>
#include <string>
#include <time.h>
#include <queue>
#include <tuple>
#include <functional>
#include <unordered_set>
#include <unordered_map>
#define INF 1000000000
#define all(c) (c).begin(),(c).end()
#define tr(c,i) for(typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define EP .00001
using namespace std;
typedef pair<int, int> ii;
typedef vector<int> vi;
typedef vector<bool> vb;
typedef vector<vi> vvi;
typedef vector<vb> vvb;
typedef vector<ii> vii;
typedef vector<double> vd;
typedef vector<vd> vvd;
typedef long long LL;
vvi adjList;
unordered_map<string, int> targs;
int add(string &s)
{
if (targs.count(s))
return targs[s];
targs[s] = targs.size();
adjList.push_back(vi());
return targs.size()-1;
}
void connect(int si, int ti)
{
if (si == ti)
return;
for (int i = 0; i < adjList[si].size(); ++i)
{
if (adjList[si][i] == ti)
return;
}
adjList[si].push_back(ti);
}
vi bfs(int s)
{
queue<ii> q;
q.push(ii(s, -1));
vi dist(adjList.size(), INF);
while (!q.empty())
{
int top = q.front().first;
int hops = q.front().second;
q.pop();
if (dist[top] != INF)
continue;
dist[top] = hops;
for (int i = 0; i < adjList[top].size(); ++i)
{
q.push(ii(adjList[top][i], hops+1));
}
}
return dist;
}
int main() {
int caseNum = 1;
cout << "Case " << caseNum << ":" << endl;
string line;
while (getline(cin, line))
{
stringstream ss(line);
string command;
ss >> command;
if (command == "add")
{
string s, t;
ss >> s;
int si = add(s);
if (ss >> t)
{
int ti = add(t);
connect(si, ti);
connect(ti, si);
}
}
else if (command == "connections")
{
string s;
ss >> s;
if (!targs.count(s))
{
cout << "target does not exist" << endl;
continue;
}
int st = targs[s];
if (adjList[st].empty())
{
cout << "no connections" << endl;
}
else
{
vi dist = bfs(st);
vi away(adjList.size(), 0);
int maxd = -1;
for (int i = 0; i < dist.size(); ++i)
{
if (dist[i] == INF || dist[i] == -1)
continue;
++away[dist[i]];
maxd = max(maxd, dist[i]);
}
for (int i = 0; i <= maxd; ++i)
{
cout << i << ": " << away[i] << endl;
}
}
}
else if (command == "associated")
{
string s, t;
ss >> s >> t;
if (!targs.count(s) || !targs.count(t))
{
cout << "target does not exist" << endl;
continue;
}
int si = targs[s], ti = targs[t];
vi dist = bfs(si);
if (dist[ti] == INF)
{
cout << "no" << endl;
}
else
{
cout << "yes " << dist[ti] << endl;
}
}
else
{
adjList.clear();
targs.clear();
cout << "----------" << endl;
cout << "Case " << ++caseNum << ":" << endl;
}
}
cout << "----------" << endl;
return 0;
}
I am using this as input:
add a b
add a c
add b d
add e b
add c f
add c g
add f h
add h i
add j k
associated a i
associated i a
associated f k
associated a h
connections a
connections i
add k g
associated a j
connections a
add h a
connections a
associated a h
add m
add n n
connections n
add a n
connections n
In Visual C++, the code produces this output (it does so on Debug or Release):
Case 1:
yes: 3
yes: 3
no
yes: 2
0: 2
1: 4
2: 1
3: 1
0: 1
1: 1
2: 1
3: 2
4: 1
5: 2
yes: 3
0: 2
1: 4
2: 2
3: 2
0: 3
1: 5
2: 1
3: 1
yes: 0
no connections
0: 1
1: 3
2: 5
3: 1
4: 1
----------
On gcc g++, it produces this output:
Case 1:
no
no
yes 0
no
0: 2
1: 2
2: 2
3: 1
0: 1
no
0: 2
1: 2
2: 2
3: 1
0: 3
1: 2
2: 2
3: 1
yes 0
----------
For reference, I am trying to solve this problem: https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=620&page=show_problem&problem=4574.
Any ideas why the input and output would be different on the different compilers? I don't believe I am using any undefined behavior.
The cause of the differences in the behavior of the code in the two platforms is the add function. You have:
int add(string &s)
{
if (targs.count(s))
return targs[s];
targs[s] = targs.size();
adjList.push_back(vi());
return targs.size()-1;
}
In that function, the problematic line is:
targs[s] = targs.size();
The line is tricky because depending on which side of the assignment operator gets evaluated first, you get different behavior. Please note that targs[s] involves a function call that changes the object.
You can change the function a little bit to make it consistent and predictable across platforms.
int add(string &s)
{
if (targs.count(s))
return targs[s];
int size = targs.size();
targs[s] = size;
adjList.push_back(vi());
return size;
}