I've got the task to create a graph's adjacency matrix from a list of adjacent nodes, stored in a file (don't need the weights) into a bitset array in C++. I successfully read the adjacent nodes from the file, but when I try to store it in the bitset array the outcome is not right.
My function is the following:
bitset<N>* read_graph(string filepath)
{
FILE *fp;
char line[100];
bitset<N> bs[N];
fp = fopen(filepath.c_str(), "r");
if(fp != NULL)
{
while(!feof(fp))
{
fgets(line, 100, fp);
//cout << line << endl;
if(line[0] == 'a')
{
string str = "";
int i(0);
for(i = 2; line[i] != ' '; i++)
{
if(line[i] != ' ')
{
str += line[i];
}
}
int fi = atoi(str.c_str());
i++;
str = "";
for(int j = i; line[j] != ' '; j++)
{
if(line[j] != ' ')
{
str += line[j];
}
}
int si = atoi(str.c_str());
si--;
fi--;
//cout << "string: " << str << endl;
cout << "fi: " << fi;
//cout << "string: " << str << endl;
cout << " si: " << si << endl;
bs[fi][si]= 1;
}
}
}
fclose(fp);
return bs;
}
The outcome is the following (fi stands for first index and si stands for second index):
sample.gr
fi: 0 si: 1
fi: 0 si: 2
fi: 1 si: 3
fi: 2 si: 4
fi: 3 si: 2
fi: 3 si: 5
fi: 4 si: 1
fi: 4 si: 5
fi: 4 si: 5
000000
000001
011000
001000
000000
000000
The indexes are right, I've checked them, but the matrix should be the following (it is mirrored because of the bitset's right side positioning):
000000
010001
001001
000010
000100
011000
I guess the error is somewhere around the bitset element accessing but I cannot find out what exactly is wrong.
I appreciate any help. Thanks.
With the pointer to a local array problem fixed, your code runs for me and prints what's expected (except mirrored).
But wouldn't it be easier to use C++ I/O in this case?
#include <vector>
#include <bitset>
#include <iterator>
#include <fstream>
#include <sstream>
#include <iostream>
const int N=6;
std::vector<std::bitset<N> > read_graph(const std::string& filepath)
{
std::vector<std::bitset<N> > bs(N);
std::ifstream fp(filepath.c_str());
for(std::string line; getline(fp, line); )
{
if(line.size() > 1 && line[0] == 'a')
{
std::istringstream str(line.substr(1));
int fi, si;
str >> fi >> si;
std::cout << "fi: " << fi << " si: " << si << '\n';
bs[--fi][--si]= 1;
}
}
return bs;
}
int main()
{
std::vector<std::bitset<N> > v = read_graph("sample.gr");
copy(v.rbegin(), v.rend(),
std::ostream_iterator<std::bitset<N> >(std::cout, "\n"));
}
test run: https://ideone.com/z7Had
You are returning a pointer to a local array. Undefined Behavior.
Use a vector<bitset<N> > or similar instead.
Related
I am confused as to how to take multiple strings that have numbers in them and convert them into an int. I have multiple lines of strings that are stored in data into ints and then insert them into a 2 dimensional arrays called values. A similar question was posted earlier on StackOverflow; however it does not seem to be working for me. I printed out what each line in data is, each string in data is as follows.
75
95 64
17 42 82
18 35 87 10
However when I output the numbers from value by using two for loops in main, it outputs as this.
75
0
0
0
95
64
0
0
95
64
0
0
17
42
82
0
17
42
82
0
18
35
87
10
18
35
87
10
0
0
0
0
I found that there are 8 columns and 8 elements in the array values when I printed the sizeof(values) and sizeof(values[0]); however, it appears that the program terminated as the last print statement, where I print hello does not occur. I provided the code I'm using below. I would like to know why this is occurring
and how I can fix it? Thanks.
//const char DELIMITER = ' ';
int **values, // This is your 2D array of values, read from the file.
**sums; // This is your 2D array of partial sums, used in DP.
int num_rows; // num_rows tells you how many rows the 2D array has.
// The first row has 1 column, the second row has 2 columns, and
// so on...
bool load_values_from_file(const string &filename) {
ifstream input_file(filename.c_str());
if (!input_file) {
cerr << "Error: Cannot open file '" << filename << "'." << endl;
return false;
}
input_file.exceptions(ifstream::badbit);
string line;
vector<string> data;
try {
while (getline(input_file, line)) {
data.push_back(line);
num_rows ++;
}
input_file.close();
} catch (const ifstream::failure &f) {
cerr << "Error: An I/O error occurred reading '" << filename << "'.";
return false;
}
for(int x = 0; x < data.size(); x++){
cout << data[x] << endl;
}
//https://stackoverflow.com/questions/1321137/convert-string-containing-several-numbers-into-integers
//Help on making multiple numbers in a string into seperate ints
values = new int*[num_rows];
vector<int> v;
for(int y = 0; y < data.size(); y++){
istringstream stream(data[y]);
values[y] = new int[y + 1];
int z = 0;
while(1) {
int n;
stream >> n;
if(!stream)
break;
values[y][z] = n;
z++;
}
z = 0;
}
sums = values;
return true;
}
int main(int argc, char * const argv[]) {
if (argc != 2) {
cerr << "Usage: " << argv[0] << " <filename>" << endl;
return 1;
}
string filename(argv[1]);
if (!load_values_from_file(filename)) {
return 1;
}
cout << sizeof(values) << endl;
cout << sizeof(values[0]) << endl;
for(int x = 0; x < sizeof(values); x++){
for(int y = 0; y < sizeof(values[x]); y++){
cout << values[x][y] << endl;
}
cout << endl;
}
cout << "hello" << endl;
return 0;
}
See this :
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;
int main()
{
string str;
ifstream fs("D:\\Myfolder\\try.txt", ios::in);
stringstream ss;
std::string item;
if (fs.is_open())
{
ss << fs.rdbuf();
str = ss.str();
cout << str << endl;
fs.close();
}
cout << "\n\n Output \n\n";
while (std::getline(ss, item, ' '))
{
cout << std::atoi(item.c_str()) <<" ";
}
return 0;
}
i need a little help with this problem,
How do you break a char array like this "char* text" into individual words based on specific delimiters and save them in the form "char* text[]" without using the strtok function or any libraries besides "iostream".
In a normal situation i would use strings instead of char arrays and the strtok function, but in this situation, i am simply not allowed to.
Thanks,
Update:
i have included what i have attempted
#include <iostream>
#include <fstream>
//#define MAX_CHARS_PER_LINE = 512;
//#define MAX_TOKENS_PER_LINE = 5;
using namespace std;
char stringToken(char* input_string);
int main(int argc, char* argv[])
{
char input_string[512];
ifstream infile;
infile.open(argv[1]);
while(!infile.eof())
{
infile.getline(input_string, 512);
cout << "Main line: " << input_string << endl;
stringToken(input_string);
}
infile.close();
return 0;
}
char stringToken(char* input_string)
{
//char* word;
//cout << "String token function: " << input_string << endl;
/*while(input_string >> word)
{
cout << word << endl;
}*/
char *tempone;
char *temptwo[5];
int ii=0,
jj=0;
while(input_string[ii] != '\0' && jj<5)
{
if((int)input_string[ii]!= 32 && (int)input_string[ii]!= 9 && (int)input_string[ii] != 44)
{
tempone[ii]=input_string[ii];
//cout << "\n\nindiv char" << input_string[ii] << "\t\t" << (int)input_string[ii] << "\n\n";
}
else
{
temptwo[jj]=tempone;
jj++;
//testing
cout << temptwo << endl;
}
ii++;
}
return 0;
}
Here a pseudo code
words split(line, delims)
{
nb_words = cound_words(line);
words = allocate_words(nb_words + 1); // words is a array of pointer
i = 0
j = 0
while true
{
while line[i] in delims // we transform every delims into a end string
{
line[i] = end_string
i++
}
if line[i] not end_string
{
words[j] = line + i // we stock the address of line[i]
j++
while line[i] not in delims and line[i] not end_string
{
i++
}
}
else
{
words[j] = NULL // we end the array by NULL pointer
return words
}
}
}
count_word use a similar loop. I let you find it. The purpose of this algorithm is to transform the line into multiple word. So line must life as long that you use words.
I wanted to break the loop when the user doesn't want to add anymore:
#include<iostream>
using namespace std;
int main() {
int i = 0, a = 0, h = 0;
cout << "Enter numbers to be added:\n ";
for(i=0; ??; i++) {
cout << "\n" << h << " + ";
cin >> a;
h = h+a;
}
return 0;
}
Use std::getline to read an input line and exit the loop when the line is empty.
#include<iostream>
#include <sstream>
int main() {
int a = 0, h = 0;
std::cout << "Enter numbers to be added:\n ";
std::string line;
std::cout << "\n" << h << " + ";
while (std::getline(std::cin, line) && // input is good
line.length() > 0) // line not empty
{
std::stringstream linestr(line);
while (linestr >> a)// recommend better checking here. Look up std::strtol
{
h = h+a;
std::cout << "\n" << h << " + ";
}
}
return 0;
}
And output:
Enter numbers to be added:
0 + 1 2 3 4 5 6 7 8 9
1 +
3 +
6 +
10 +
15 +
21 +
28 +
36 +
45 +
Note that this allows multiple entries per line and looks pretty ugly, so OP is probably more interested in:
#include<iostream>
int main() {
long a = 0, h = 0;
std::cout << "Enter numbers to be added:\n ";
std::string line;
std::cout << "\n" << h << " + ";
while (std::getline(std::cin, line) && // input is good
line.length() > 0) // line not empty
{
char * endp; // will be updated with the character in line that wasn't a digit
a = std::strtol(line.c_str(), &endp, 10);
if (*endp == '\0') // if last character inspected was the end of the string
// warning: Does not catch ridiculously large numbers
{
h = h+a;
}
else
{
std::cout << "Very funny, wise guy. Try again." << std::endl;
}
std::cout << "\n" << h << " + ";
}
return 0;
}
Output
Enter numbers to be added:
0 + 1
1 + 1 2 3 4
Very funny, wise guy. Try again.
1 + 2
3 + 44444
44447 + jsdf;jasdklfjasdklf
Very funny, wise guy. Try again.
44447 + 9999999999999999999999
-2147439202 +
It is easier to use a sentinel value that you can check against, something like this:
#include<iostream>
#include<string>
using namespace std;
int main()
{
int sum = 0;
string userInput;
while(true)
{
cout<<"Enter number to be added ('q' to quit): ";
cin >> userInput;
if( (userInput == "q") || (userInput == "Q") )
{
break;
}
try
{
sum += stoi( userInput );
}
catch( const std::invalid_argument& e )
{
cerr << "Invalid input \"" << userInput << "\" received!" << endl;
return EXIT_FAILURE;
}
}
cout << "Sum: " << sum << endl;
return EXIT_SUCCESS;
}
std::getline(std::istream&, std::string&) happily gives all lines including empty lines:
#include <iostream>
#include <string>
int main() {
long long accumulator = 0;
while (true) {
// read a (possibly empty) line:
std::string buf;
if (!std::getline(std::cin, buf)) {
std::cerr << "The input stream is broken." << std::endl;
break;
}
// was the entered line empty?
if (buf.empty()) {
std::cerr << "You entered a blank line" << std::endl;
break;
}
// convert string to integer
std::size_t pos;
long long summand;
try {
summand = std::stoll(buf, &pos, 10);
} catch (std::invalid_argument &) {
std::cerr << "Not an integer: " << buf << std::endl;
continue;
} catch (std::out_of_range &) {
std::cerr << "Out of range: " << buf << std::endl;
continue;
}
if (pos != buf.size()) {
std::cerr << "Not an integer on its own: " << buf << std::endl;
continue;
}
// do something with the data:
accumulator += summand;
}
std::cout << "accumulator = " << accumulator << std::endl;
return 0;
}
I have a char array (lets' say "13 314 43 12") and i want to put the first number (13) into a separate integer . how do i do that ? is there any way like splitting the first number into 10 + 3 and then adding them to the int ?
I am not sure what you mean by getting 1 and 3, but if you want to split the space-separated string into integers I suggest using a stream.
std::istringstream iss(s);
int n;
while(iss >> n)
{
std::cout << "Integer: " << n << std::endl;
}
[edit] Alternatively, you could parse the string yourself, something like this:
char* input = "13 314 43 12";
char* c = input;
int n = 0;
for( char* c = input; *c != 0; ++c )
{
if( *c == ' ')
{
std::cout << "Integer: " << n << std::endl;
n = 0;
continue;
}
n *= 10;
n += c[0] - '0';
}
std::cout << "Integer: " << n << std::endl;
#include <cstring>
#include <iostream>
#include <stdlib.h>
int main ()
{
char str[] = "13 45 46 96";
char * pch = strtok (str," ");
while (pch != NULL)
{
std::cout << atoi(pch) << "\n"; // or int smth=atoi(pch)
pch = strtok (NULL, " ");
}
return 0;
}
If you just want the first number, just use a function like atoi() or strtol(). They extract a number until it runs into the null terminated character or a non-numeric number.
According to your question I think following code will give some idea.
#include <string>
#include <iostream>
using namespace std;
int main(){
char s[] = "13 314 43 12";
//print first interger
int v = atoi(s);
cout << v << std::endl;
//print all integer
for (char c : s){
if (c == ' ' || c == '\0'){
}else{
int i = c - '0';
cout << i << std::endl; // here 13 print as 1 and 3
}
}
}
If you want to print first number you can use
int v = atoi(s);
cout << v << std::endl;
If you want to split and print all integers Ex: 13 as 1,3
for (char c : s){
if (c == ' ' || c == '\0'){
}else{
int i = c - '0';
cout << i << std::endl; // here 13 print as 1 and 3
}
}
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.