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;
}
Related
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
Similar things have been asked before but I am having trouble applying the concept. I would like to to keep track of the indices of the pairs in my vector of pairs then, once sorted, std::cout the input order.
e.g.
cin >> 5 6 1 5 1 2 1 2 3 5
cout << 1 2 1 2 1 5 3 5 5 6
cout >> 3 4 2 5 1 //and this is where I am having trouble.
I was thinking of converting to triples, where one of the elements is the index but I couldn't get that to conform to my needs.
Any help would be appreciated. Thank you.
#include <iostream>
#include <cmath>
#include <vector>
#include <cstdlib>
using namespace std;
bool compare(const pair<int,int>&A, const pair<int,int>&B);
int main()
{
vector<pair<int,int>> v;
pair<int,int> tok;
while(cin >> tok.first>>tok.second){v.push_back(tok);}
sort(v.begin(),v.end(), compare);
for(int i = (signed int)v.size()-1; i >= 0 ; i--)
{
cout << v.at(i).first << " ";
cout << v.at(i).second << " ";
}
cout << endl;
return 0;
}
bool compare(const pair<int,int>&A, const pair<int,int>&B)
{
return A.first > B.first;
}
Here's one way to do it. Long time since I did someone's homework for them ;-)
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
const string input_data = "5 6 1 5 1 2 1 2 3 5";
typedef pair<int, int> integer_pair;
typedef pair<int, integer_pair> integer_pair_with_input_order;
bool less_by_integer_pair(const integer_pair_with_input_order& l,
const integer_pair_with_input_order& r)
{
return l.second < r.second;
}
int main()
{
// note - I did this to avoid having to type numbers in.
std::istringstream simulate_cin(input_data);
vector<integer_pair_with_input_order> v;
integer_pair tok;
int input_order = 0;
while(simulate_cin >> tok.first >> tok.second) {
v.push_back(make_pair(++input_order, tok));
}
sort(v.begin(),v.end(), less_by_integer_pair);
for (int i = 0 ; i < v.size() ; ++i)
{
const integer_pair_with_input_order& elem = v[i];
cout << "input order : " << elem.first
<< " { " << elem.second.first
<< ", " << elem.second.second << " }\n";
}
return 0;
}
I have this code that convert a decimal number into a binary one:
#include <iostream>
#include <windows.h>
#include <vector>
#include <algorithm>
using namespace std;
void space(){ cout << endl << endl << endl; }
int main(int argc, char const *argv[]){
system("color 1F");
unsigned long int n, copy_n;
vector<int> v;
cout << "# Decimal: "; cin >> n; cout << endl; copy_n = n;
while (n != 0){
if (n % 2 == 0){ v.push_back(0); }else{ v.push_back(1); }
n = int(n / 2);}
cout << endl << "# Binary: ";
reverse(v.begin(), v.end());
for (size_t i = 0; i < v.size(); i++){cout << v.at(i);}
space(); system("Pause"); return 0;
}
... and this ...
#include <iostream>
#include <windows.h>
using namespace std;
void space(){ cout << endl << endl << endl; }
int main(int argc, char const *argv[]){
system("color 1F");
unsigned long int n, copy_n, nr = 0 ;
cout << "# Decimal: "; cin >> n; copy_n = n; cout << endl;
while (copy_n != 0){ nr++; copy_n = int(copy_n / 2); }
int* v = new int[nr];
for (int i = 0; i < nr; i++){if (n % 2 == 0){ v[i] = 0; }else{ v[i] = 1; }n = int(n / 2);}
cout << endl << "# Binary: ";
for (int i = nr-1; i >= 0;i--){cout << v[i] << "";}
space(); system("Pause"); return 0;}
... and this ...
#include <iostream>
#include <windows.h>
#include <bitset>
using namespace std;
void space(){ cout << endl << endl << endl; }
int main(int argc, char const *argv[]){
system("color 1F");
unsigned int n;
cout << "# Decimal: "; cin >> n; cout << endl;
bitset<16>binary(n);
cout << endl << "# Binary: " << binary << endl;
space(); system("Pause"); return 0;
}
But my question is:
How can I use reverse() function from algorithm and print the vector with range-based for loop
Ex: Decimal = 2
with
reverse(v.begin(), v.end());
for (size_t i = 0; i < v.size(); i++){cout << v.at(i);}
program prints 10
with
reverse(v.begin(), v.end());
for(auto i : v){cout<<v.at(i);}
program pritns 01
Why? And how can I fix this?
This for statement
reverse(v.begin(), v.end());
for(auto i : v){cout<<v.at(i);}
is simply wrong.
The valid code will look like
reverse(v.begin(), v.end());
for(auto i : v){ cout << i;}
Also if you are paid for the number of symbols entered in the source code then this statement
if (n % 2 == 0){ v.push_back(0); }else{ v.push_back(1); }
looks very good because it contains many symbols. Otherwise it would be better to write
v.push_back( n % 2 );
Also in one of your programs you allocate dynamically an array
int* v = new int[nr];
but not free it. In this case it would be better to use smart pointer std::unique_ptr.
You could also try to write a recursive function. For example
#include <iostream>
#include <vector>
std::vector<unsigned int> & dec_to_bin( std::vector<unsigned int> &v,
unsigned int x )
{
const unsigned int Base = 2;
static size_t n;
unsigned int digit = x % Base;
++n;
if ( x /= Base )
{
dec_to_bin( v, x );
}
else
{
v.reserve( n );
n = 0;
}
v.push_back( digit );
return v;
}
int main()
{
while ( true )
{
std::cout << "Enter a non-negative number (0-exit): ";
unsigned int x = 0;
std::cin >> x;
if ( !x ) break;
std::vector<unsigned int> v;
dec_to_bin( v, x );
for ( auto digit : v ) std::cout << digit;
std::cout << std::endl;
}
return 0;
}
If to enter sequentially
15
7
3
1
0
then the program output will be
Enter a non-negative number (0-exit): 15
1111
Enter a non-negative number (0-exit): 7
111
Enter a non-negative number (0-exit): 3
11
Enter a non-negative number (0-exit): 1
1
Enter a non-negative number (0-exit): 0
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.
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.