C++: Get numbers between two string delimiters and values after extracting desired integer from string using stringstream - getline

```
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <fstream>
using namespace std;
bool findCurrentNumber (int currentNumber, int foundNumber)
{
if (currentNumber == foundNumber)
{
return true;
}
return false;
}
int main()
{
ifstream inputFile;
inputFile.open("C:\\Projects\\data.txt");
if (!inputFile)
{
cerr << "Error reading file ";
}
else
{
int searchCurrentNumber;
cout << "Please type in the number you are looking for: ";
cin >> searchCurrentNumber;
bool foundRelevantSection = false;
string delimiter = "energy";
size_t pos = 0;
string token;
string line;
while (getline(inputFile, line))
{
while ((pos = line.find(delimiter)) != string::npos)
{
token = line.substr(0, pos);
//check the found token
//cout << token << endl;
line.erase(0, pos + delimiter.length());
stringstream ss;
//store the whole string into stringstream
ss << token;
string temp;
int found;
while (!ss.eof())
{
//extract the word by word from stream
ss >> temp;
//Check the given word is integer or not
if (stringstream(temp) >> found)
cout << "Number found: " << found << " " << endl;;
//no space at the end of string
temp = "";
}
if (findCurrentNumber (searchCurrentNumber, found) == true)
{
while (getline (inputFile, line))
{
if (foundRelevantSection)
{
//if no matches were found, the function returns "string::npos"
if(line.find("total") != string::npos)
{
//relevant section ends now
foundRelevantSection = false;
}
else
{
cout << line << endl;
}
}
else
{
if (line.find("point") != string::npos )
{
foundRelevantSection = true;
}
}
}
}
else
{
cout << "The number is not equal on this line compared to what is typed in!" << endl;
}
}
} //closes the while-loop
} //closes the if/else-statement
inputFile.close();
return 0;
}
```
Hi all,
I would like to parse an input file having this format:
point 152 # energy # 0.5
152 152 152 152 152 152
152 152 152 152 152 152
total 0.011 0.049 0.035
point 153 # energy # 1.5
153 153 153 153 153 153
153 153 153 153 153 153
total 0.015 0.050 0.040
The code accepts an user-supplied integer and compares it to the number extracted from e.g. the string "point 152 # energy". If the user enters the number "152", the code should give following numbers:
output:
152 152 152 152 152 152
152 152 152 152 152 152
Unfortunately, my code returns exactly the opposite if number 152 is entered or if number 153 is entered no values are returned.
Could anyone help me and tell me what I am doing wrong? I am grateful for any hint!
Thanks in advance!
Best wishes,
DaveS

Fix for 2nd bug added at the end.
You should work on getting better with a debugger, I found your problem with one:
while (!ss.eof())
{
//extract the word by word from stream
ss >> temp;
//Check the given word is integer or not
if (stringstream(temp) >> found)
cout << "Number found: " << found << " " << endl;;
//no space at the end of string
temp = "";
}
doesn't stop on finding 152 in "point 152 # ", but goes on to process # which turns found into 0.
This code with a break fixes that part:
while (!ss.eof())
{
//extract the word by word from stream
ss >> temp;
//Check the given word is integer or not
if (stringstream(temp) >> found)
{
cout << "Number found: " << found << " " << endl;
foundRelevantSection = true;
break; /* exits the while now */
}
//no space at the end of string
temp = "";
}
or you could test found in the while, by first setting it to 0, and testing with && found == 0
Then the part calling findCurrentNumber (int currentNumber, int foundNumber) is garbage (or a placeholder for something way more complex?) as if (findCurrentNumber (searchCurrentNumber, found) == true) is simply if (searchCurrentNumber == found) which is much easier to read!
I didn't check if there are more bugs farther down the code, but with the break you definitely get the correct value in found.
part 2
You already found "point", so you shouldn't look for it again!
I added foundRelevantSection in the code above, before break.
Change the next part to (no if relevant, no if point found):
while (getline (inputFile, line) && foundRelevantSection)
{
//if no matches were found, the function returns "string::npos"
if(line.find("total") != string::npos)
{
//relevant section ends now
foundRelevantSection = false;
}
else
{
cout << line << endl;
}
}
hoping it was the last bug...

I checked your code, although isn't straightforward but I was able to understand what you're trying to achieve at least. Anyways, here is my own contribution to your question. I hope it helps you or at least gives you a better view of the solution
#include <iostream>
#include <fstream>
#include <regex>
int main()
{
using namespace std;
ifstream inputFile;
inputFile.open("sample.dat");
if (!inputFile)
{
cerr << "Error reading file ";
}
else
{
int searchCurrentNumber;
bool foundRelevantSection = false;
cout << "Please type in the number you are looking for: ";
cin >> searchCurrentNumber;
//while we are still having data to read
std::string currentLine;
while (std::getline(inputFile, currentLine))
{
//remove the top and bottom section of the log
if((currentLine.find("point") == string::npos) && (currentLine.find("total") == string::npos ))
{
//now all the numbers are in the middle then search for the number
size_t pos = currentLine.find(std::to_string(searchCurrentNumber));
if(pos!= string::npos){
//we found the number so we are in the section hopefully
string line;
while (std::getline(inputFile, line))
{
if (foundRelevantSection)
{
//if no matches were found, the function returns "string::npos"
if(line.find("total") != string::npos)
{
//relevant section ends now
foundRelevantSection = false;
}
else
{
cout << line << endl;
}
}
else
{
if (line.find("point") != string::npos )
{
foundRelevantSection = true;
}
}
}
}
}
}
}
return 0;
}

Related

why do i get this compile error: " error: cannot bind non-const lvalue reference of type ‘Matrix&’ to an rvalue of type ‘Matrix’ "?

Ok so i'am writting this code for an exercise we have to write a class for matrices and then to check it we use a code that the teacher wrote to check if it performes the normal operations.
And i don't get exactly where i am wrong it seems to bother the compiler that i return a type Matrix but really i dont get what is a lvalue or rvalue .
But i get this when i try to compile
anthony#anthony-linux:~/Documents/CS/Ex6$ g++ -Wall simplematrixtest.cc Matrix.cc -o simplematrixtest
simplematrixtest.cc: In function ‘int main()’:
simplematrixtest.cc:70:24: error: cannot bind non-const lvalue reference of type ‘Matrix&’ to an rvalue of type ‘Matrix’
70 | Matrix g = f.multiply(a);
| ~~~~~~~~~~^~~
In file included from simplematrixtest.cc:4:
Matrix.hh:13:18: note: initializing argument 1 of ‘Matrix::Matrix(Matrix&)’
13 | Matrix(Matrix &m);
| ~~~~~~~~^
this is my class Matrix:
#include "Matrix.hh"
#include <cmath>
#include <iostream>
using namespace std;
// Default constructor: initializes the Matrix.
Matrix::Matrix() {
nrows=0;
ncols=0;
values=0;
}
// Initializes the Matrix with rows and cols.
Matrix::Matrix(int numberOfRows,int numberOfCols) {
nrows=numberOfRows;
ncols=numberOfCols;
values = new double[nrows*ncols] ;
for (int i = 0; i < nrows*ncols; i++) {
values[i] = 0;
}
}
// Copy constructor
Matrix::Matrix(Matrix &m)
{
nrows=m.getRows();
ncols=m.getCols();
int sizeOfM=m.getRows()*m.getCols();
values = new double[sizeOfM];
for (int i = 0; i < sizeOfM; ++i) {
values[i] = m.values[i];
}
}
// Destructor - Matrix allocates no dynamic resources.
Matrix::~Matrix() {
delete[] values;
// no-op
}
// Mutators:
void Matrix::setElem(int rowIndex,int colIndex,double val){
values[rowIndex*ncols+colIndex]=val; /*See Jasper i listen to what you say ! No return for a void function :) */
}
void Matrix::subtract(Matrix &m) {
for (int i = 0; i < nrows*ncols; i++) {
values[i] -=m.values[i];
}
}
void Matrix::add(Matrix &m) {
for (int i = 0; i < nrows*ncols; i++) {
values[i] +=m.values[i];
}
}
Matrix Matrix::multiply(Matrix &m) {
if(ncols!=m.getRows()){
cout << " Error :invalid matrix multiplication"<< endl;
Matrix ret(0,0);
return ret;
}
else{
Matrix ret(nrows,m.getCols());
for (int rowIndex = 0; rowIndex < ret.nrows; rowIndex++) {
for (int colIndex = 0; colIndex < ret.ncols; colIndex++) {
for(int count=0; count <= ncols; count++) {
ret.values[rowIndex*ncols+colIndex] +=(values[rowIndex*ncols+(count)]*m.values[count*ncols+colIndex]);
}
}
}
return ret;
}
}
// Accessors:
int Matrix::getRows() {
return nrows;
}
int Matrix::getCols() {
return ncols;
}
double Matrix::getElem(int rowIndex,int colIndex){
return values[rowIndex*ncols+colIndex];
}
bool Matrix::equals(Matrix &m) {
if(m.getRows()!=nrows||m.getCols()!=ncols){return false;}
for (int i = 0; i < nrows*ncols; i++) {
if(values[i] !=m.values[i]){return false;}
}
return true;
}
Apparently the problem is in multiply here is the test code
#include <iostream>
using namespace std;
#include "Matrix.hh"
// Have some fun playing with a Matrix!
int main(void) {
// Create a new matrix with two rows and three columns
Matrix a(2, 3);
// Print out some information about the size of this matrix:
cout << "Matrix a is " << a.getRows() << " rows tall." << endl;
cout << "Matrix a is " << a.getCols() << " columns wide." << endl;
// Print out the contents of this matrix (should be all zeroes!):
for(int r = 0; r < a.getRows(); r++) {
for(int c = 0; c < a.getCols(); c++) {
cout << "Element (" << r << ", " << c << ") = " << a.getElem(r,c) << endl;
}
}
// Fill in a few values
a.setElem(1, 2, -5280); // bottom right element is now -5280
a.setElem(0, 1, 123); // top center element is now 123
// Create an identical copy of this matrix
Matrix b = a;
// Change the original matrix some more
a.setElem(1, 2, 555); // bottom right element is now 555
// Examine some elements of each matrix
cout << "(1,2) of a = " << a.getElem(1,2) << " [should be 555]" << endl;
cout << "(1,2) of b = " << b.getElem(1,2) << " [should be -5280]" << endl;
// So if a and b are different, let's copy a into a new matrix and add b to it:
Matrix c = a;
c.add(b);
// Now let's copy c into another new matrix, d, and subtract a from it:
Matrix d = c;
d.subtract(a);
// Hmm... that means d should be b, no?
if (d.equals(b)) {
cout << "Yay! d = b!" << endl;
} else {
cout << "Uh-oh! Something went wrong, d isn't b!" << endl;
}
// Let's create a tiny 0 by 0 matrix using the default constructor:
Matrix e;
cout << "0x0 matrix e is " << e.getRows() << " by " << e.getCols() << endl;
// Of course, e and d are different, since they have different sizes!
if(!e.equals(d)) {
cout << "e and d are indeed different!" << endl;
} else {
cout << "Oh well, back to the drawing board...." << endl;
}
Matrix f(2,2);
f.setElem(0, 0, 2.0);
f.setElem(1, 0, 3.0);
f.setElem(0, 1, 5.0);
f.setElem(1, 1, 7.0);
Matrix g = f.multiply(a);
if (g.getElem(1, 2) == 3885.0) {
cout << "Multiply seems to work!" << endl;
} else {
cout << "Error in multiply() !" << endl;
}
// Okay, enough of this; destroy all those matrices and end the program:
return 0;
}
If i write
Matrix g = a ;
f.multiply(a);
The code compiles without any problem so it is a problem with this line: Matrix g =f.multiply(a);

for loop not running in C plus plus program, without showing any error - CLOSED

It is a very simple program and I have just started learning c++ but the for loop is not working in this program. can anyone tell me why the for loop in this c++ program is not running?
#include <iostream>
#include <string>
using namespace std;
class PrimeNo
{
int a;
int c;
public:
// function to check prime number
void chk_Prime(void)
{
cout << "Enter the number: " << endl;
cin >> a;
c=a/2; // to store the condition
for (int i = 2; i < c; ++i)
{
if (a == 0 || a == 1)
{
cout << "The number is not a prime number" << endl;
break;
}
else if (a % i == 0)
{
cout << "This number is not a prime number" << endl;
break;
}
else //if upper conditions are false a number is a prime number
{
cout << "This number is a prime number" << endl;
break;
}
}
}
};
int main()
{
PrimeNo Num;
Num.chk_Prime();
return 0;
}

Complementary DNA(C++)

Task:Write a code to the new string of Dna According to its pattern. Just so you know In DNA strings, symbols "A" and "T" are complements of each other, as "C" and "G".
Fore example:DNA_strand ("ATTGC") //returns "TAACG" or DNA_strand ("GTAT") //returns "CATA"
My Code=>
#include <string>
#include <vector>
#include <iostream>
std::string DNAStrand(const std::string& dna)
{
std::string Sym;
std::string c;
std::stringstream s;
s << Sym;
s >> c;
for(int i = 0; i < dna.size() - 1; i++) {
switch (dna[i]) {
case ('A'):
Sym[i] = 'T';
break;
case ('T'):
Sym[i] = 'A';
break;
case ('C'):
Sym[i] = 'G';
break;
case ('G'):
Sym[i] = 'C';
break;
default:
std::cout << "invalid";
} return c.str();
}
int main() {
std::cout << DNAStrand("ATTGC") << "\n"; //retun "TAACG"
std::cout << DNAStrand("GTAT") << "\n"; //retun "CATA"
}
}
You have created a vector<string>, but in the if statements, you are setting the elements of the vector to chars. You want to build a string, not a vector<string>.
You should replace subsequent if statements with else if, or use a switch statement. Otherwise if statements subsequent to a satisfied if statement are executed needlessly.
Replace this vector with an ostringstream. Naming the stream as s, you would append a char named c with s << c. At the end of iterating over dna, return s.str().

logic error in prime # program. The program just ends after I answer the prompt so I can't see the numbers

//Purpose: Display first 'n' (user chosen) number if emirps to the console, five per line.
//Note: An "emirp" is a prime number that is also prime when reversed.
#include <iostream>
using namespace std;
bool isPrime(int value); //Prototyle for "prime number function"
int reverse (int value2); //Prototype for "emirp function"
int main()
{
//Ask the user for a positive number
cout << "Please enter a positive number: ";
int n;
cin >> n;
//Reject negative value input
if ( n < 1)
{
cout << "INVALID NUMBER \n";
}
else
{
//Calculate all emirps up to 'n'.
int test = 0;
int number = 2;
while (test < n)
{
if (isPrime(number) && reverse(number))
{
cout << "\n" << reverse(number) << "\t\t\t";
test++;
}
else
{
test++;
}
}
}
system("pause");
return 0;
}
bool isPrime(int value)
{
//If value is prime, the remainder (count) will be zero twice--for 1 and itself.
int divisor = 1;
int count = 0;
int prime = 0;
if (value % divisor == 0)
{
count++;
++divisor;
}
if (count = 2)
{
return true;
}
else
{
return false;
}
}
int reverse(int value2)
{
//reverse the number
value2*=10;
value2 = value2 %10;
value2/=10;
//same procedure as prime function
int divisor2 = 1;
int count2 = 0;
int emirp = 0;
if (value2 % divisor2 == 0)
{
count2++;
++divisor2;
}
if (count2 = 2)
{
int emirp = value2;
}
return emirp;
}
How does this even build?
if (count = 2)
{
...
}
Also:
your reverse function just returns an int, what do you expect
if (isPrime(number) && reverse(number)) to do with that result?
It's not a good way of working to do the whole calculation again btw:
cout << "\n" << reverse(number) << "\t\t\t"; //you already did this in your "check"
Edit:
And no wonder it doesn't work.
You check the number-value (2) every time, not n
If it is just about viewing the console output :
Press CTRL+F5 to run application in Visual studio.
just provide a getch()in main() function
And your code syntax is not in a right way :
if (count = 2) //count ==2
{
return true;
}
if (isPrime(number) && reverse(number))
{
cout << "\n" << reverse(number) << "\t\t\t";
test++;
}
will call reverse() 2 times.
modify it something like ;
int RevNum = reverse(number);
if (isPrime(number) &&RevNum)
{
cout << "\n" << RevNum << "\t\t\t";
test++;
}

How to get a glyph outline of a true type character on a linux system

I'm searching for a library to get the outline of a glyph in a true type font on a linux system. We are using Pango and Cairo but unfortunatly I didn't find anything.
I'm looking for somethig similar to GlyphTypeface.GetGlyphOutline under .NET
Any help or hints are appreciated!
Thanks in advance
The solution is to use FreeType, it offers the range of function I need:
#include <string>
#include <iostream>
#include <freetype/ftglyph.h>
#include <freetype/freetype.h>
//******************* check error code ********************
void Check(FT_Error ErrCode, const char* OKMsg, const char* ErrMsg)
{
if(ErrCode != 0)
{
std::cout << ErrMsg << ": " << ErrCode << "\n";
std::cout << "program halted\n";
exit(1);
}
else
std::cout << OKMsg << "\n";
}
//******************** get outline ************************
int GetOutLine(FT_Glyph glyph, FT_OutlineGlyph* Outg)
{
int Err = 0;
switch ( glyph->format )
{
case FT_GLYPH_FORMAT_BITMAP:
Err = 1;
break;
case FT_GLYPH_FORMAT_OUTLINE:
*Outg = (FT_OutlineGlyph)glyph;
break;
default:
;
}
return Err;
}
//*********** print outline to console ***************
int PrintOutLine(FT_OutlineGlyph Outg)
{
int Err = 0;
FT_Outline* Ol = &Outg->outline;
int Start = 0; //start index of contour
int End = 0; //end index of contour
short* pContEnd = Ol->contours; //pointer to contour end
FT_Vector* pPoint = Ol->points; //pointer to outline point
char* pFlag = Ol->tags; //pointer to flag
for(int c = 0; c < Ol->n_contours; c++)
{
std::cout << "\nContour " << c << ":\n";
End = *pContEnd++;
for(int p = Start; p <= End; p++)
{
char Ch = *pFlag++ + '0';
std::cout << "Point " << p <<": X=" << pPoint->x << " Y="<<pPoint->y << " Flag=" << Ch << "\n";
pPoint++;
}
Start = End + 1;
}
return Err;
}
//*********** get glyph index from command line *************
FT_UInt GetGlyphIndex(int argc, char* argv[], int Nr)
{
if(argc > Nr)
{
return atoi(argv[Nr]);
}
else
{
return 36;
}
}
//*********** get font name from command line *************
void GetFontName(int argc, char* argv[], int Nr, std::string& FontName)
{
if(argc > Nr)
{
FontName += argv[Nr];
}
else
{
FontName += "FreeMono.ttf";
}
}
//*********** get font size from command line *************
int GetFontSize(int argc, char* argv[], int Nr)
{
short FontSize = 50 * 64;
if(argc > Nr)
FontSize += atoi(argv[Nr]);
return FontSize;
}
//******************** M A I N ************************
// par1: FontName, par2:Glyph-Nr, par3: FontSize as FT_F26Dot6
int main(int argc, char* argv[])
{
FT_Face face;
FT_Library library;
FT_Error error;
error = FT_Init_FreeType( &library );
Check(error, "", "error initializing FT lib");
std::string FontName;
FontName = "/usr/share/fonts/truetype/freefont/";
GetFontName(argc, argv, 1, FontName);
error = FT_New_Face( library, FontName.c_str(), 0, &face );
Check(error, "", "error loading font");
FT_F26Dot6 font_size = GetFontSize(argc, argv, 3);
error = FT_Set_Char_Size( face, font_size, font_size, 72, 72 );
Check(error, "", "error setting char size");
FT_UInt glyph_index = GetGlyphIndex(argc, argv, 2);
FT_Int32 load_flags = FT_LOAD_DEFAULT;
error = FT_Load_Glyph( face, glyph_index, load_flags );
Check(error, "", "error loading glyph");
FT_Glyph glyph;
error = FT_Get_Glyph( face->glyph, &glyph );
Check(error, "", "error getting glyph");
FT_OutlineGlyph Outg;
error = GetOutLine(glyph, &Outg);
Check(error,"", "error getting outline");
std::cout << "=======================================================\n";
std::cout << "Font: " << FontName << "\n";
std::cout << "Glyph Index: " << glyph_index << "\n";
std::cout << "=======================================================\n";
error = PrintOutLine(Outg);
Check(error,"", "error printing outline");
return 0;
}
Cairo has this capability builtin.
cairo_glyph_path() will get the glyph outline and make it the current path, and allow you to get the current path and iterate over it.

Resources