In the follwing program I was searching of lowest comman ancesstor in a BST.
The main problem here is that !root doesn't works like root!=nullptr.
Here line 1 works perfect. But line 2 gives wrong answer.
Please tell why line 2 desn't works but line 1 does.
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
int small=min(p->val, q->val);
int big=max(p->val, q->val);
while(root!=nullptr){ // line 1
// while(!root){ // line 2
int x=(root->val);
if(x>big){
root=root->left;
}
else if(x<small){
root=root->right;
}
else{
return root;
}
}
return nullptr;
}
};
Short of defining nullptr to be something weird (like 7), there should be no difference between x != nullptr and ! x, for any given pointer x.
It may be worthwhile printing out nullptr and root just inside the loop as well as the comparison results (and pointers, just in case your tree is corrupt), to see if something weird is happening, something like:
while (!root) {
std::cout
<< static_cast<void*>(root) << ' '
<< static_cast<void*>(root->left) << ' '
<< static_cast<void*>(root->right) << ' '
<< static_cast<void*>(nullptr) << ' '
<< (! root) << ' '
<< (root != nullptr) << std::endl;
int x=(root->val);
// ... and so on
The output of that may go a great deal toward showing what's wrong with your situation(a).
(a) One of my favourite mantras is "when in doubt, print it out", right up there with:
Get it working first, then get it working fast.
You can't get any less optimised than "wrong".
:-)
Related
Problem description
I read the mesh from the file "blank.off" and load it into the a surface_mesh variable blank. One file named "hepoints49.txt" stores point clouds. I use function CGAL::advancing_front_surface_reconstruction() to convert this point cloud to surface_mesh sv, and then use function corefine_and_compute_difference(blank,sv,res) to perform the Boolean subtraction between blank and sv.But the program throws an exception and terminates. The following is displayed on the terminal:
Using context 4 . 3 GL
load sv...
Using context 4 . 3 GL
start difference...
CGAL error: precondition violation!
Expression : CGAL::is_valid_polygon_mesh(tm)
File : D:\dev\vcpkg\installed\x64-windows\include\CGAL/Polygon_mesh_processing/orientation.h
Line : 190
Could you please help me solve this problem?
code
#include<iostream>
#include<io.h>
#include<fstream>
#include<algorithm>
#include<array>
#include<CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include<CGAL/Advancing_front_surface_reconstruction.h>
#include<CGAL/Surface_mesh.h>
#include<CGAL/disable_warnings.h>
#include<CGAL/draw_surface_mesh.h>
#include<ctime>
#include<string>
#include<CGAL/polygon_mesh_processing/corefinement.h>
#include<CGAL/polygon_mesh_processing/remesh.h>
#include<CGAL/boost/graph/selection.h>
#include<CGAL/polygon_mesh_processing/repair_self_intersections.h>
using std::cin;
using std::cout;
using std::endl;
using std::string;
namespace PMP = CGAL::Polygon_mesh_processing;
typedef std::array<std::size_t, 3> Facet;
typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel;
typedef Kernel::Point_3 Point_3;
typedef CGAL::Surface_mesh<Point_3> Mesh;
struct Construct {
Mesh& mesh;
template <typename PointIterator>
Construct(Mesh& mesh, PointIterator b, PointIterator e):mesh(mesh) {
for (; b != e; ++b) {
boost::graph_traits<Mesh>::vertex_descriptor v;
v = add_vertex(mesh);
mesh.point(v) = *b;
}
}
Construct& operator=(const Facet f) {
typedef boost::graph_traits<Mesh>::vertex_descriptor vertex_descriptor;
typedef boost::graph_traits<Mesh>::vertices_size_type size_type;
mesh.add_face(vertex_descriptor(static_cast<size_type>(f[0])),
vertex_descriptor(static_cast<size_type>(f[1])),
vertex_descriptor(static_cast<size_type>(f[2])));
return *this;
}
Construct& operator*() { return *this; }
Construct& operator++() { return *this; }
Construct& operator++(int) { return *this; }
};
int main() {
//load blank
Mesh blank, sv,res;
std::ifstream fin("blank.off");
fin>>blank;
fin.close();
CGAL::draw(blank);
//load sv
string filename = "hepoints49.txt" ;
std::cout << "load sv..."<< std::endl;
fin.open(filename);
std::vector<Point_3> points;
std::vector<Facet> facets;
std::copy(std::istream_iterator<Point_3>(fin),
std::istream_iterator<Point_3>(),
std::back_inserter(points));//load points
fin.close();
Construct construct(sv, points.begin(), points.end());
CGAL::advancing_front_surface_reconstruction(points.begin(), points.end(), construct);//convert sv to surface_mesh
CGAL::draw(sv);
std::cout << "start difference..." << std::endl;
bool valid_difference = PMP::corefine_and_compute_difference(blank,sv,res);
if (valid_difference) {
std::cout << "difference was successfully computed. " << std::endl;
CGAL::draw(res);
}
else {
std::cout << "difference could not be completed. Skip. " << endl << endl;
}
//CGAL::draw(res);
return 0;
}
Runtime environment
CGAL version: 5.3
IDE: VS2017
Solution Configuration: Debug x64
I tried to run this program in Release mode, of course there is no exception thrown. But the result I got turned out to be the opposite of what I want.
Files
Files that appearing in the code are provided below:
https://github.com/wenzaifou/for-stack-overflow-question3.git
Github link is provided because the file is relatively large.
The way the mesh is constructed from advancing front output does not filter out isolated vertices, which causes the exception to be raised. Adding a call to CGAL::Polygon_mesh_processing::remove_isolated_vertices(sv) will solve the problem.
Then you might encounter the issue that your meshes are not outward oriented (meaning then represent an infinite portion of space). Adding the following calls will solve the problem:
if (!CGAL::Polygon_mesh_processing::is_outward_oriented(blank))
CGAL::Polygon_mesh_processing::reverse_face_orientations(blank);
if (!CGAL::Polygon_mesh_processing::is_outward_oriented(sv))
CGAL::Polygon_mesh_processing::reverse_face_orientations(sv);
Doc refs here and there.
The following parser does not compile when I use std::optional<std::string> for values of a -lexeme[+alpha] rule: something breaks in the attribute management.
The grammar works fine if instead of std::string I use int as a base type, it also works if I use twice std::string (i.e., no std::optional). However it does not work with boost::optional either. In the real grammar there is a difference between the absence of the string, and an empty string: I want to use std::optional (or its Boost predecessor).
The full example is available on Coliru, but here are the relevant bits:
struct pair_t
{
std::string first;
std::optional<std::string> second;
};
BOOST_FUSION_ADAPT_STRUCT(pair_t, first, second)
const auto pair_rule = lexeme[+alpha] >> -lexeme[+alpha] >> eoi;
for (std::string i: {"ab", "ab cd"})
{
auto res = pair_t{};
auto first = i.cbegin();
auto last = i.cend();
auto r = x3::phrase_parse(first, last, pair_rule, space, res);
if (r && first == last)
std::cout << i << ": " << res << '\n';
else
std::cout << i << ": failed\n";
}
My compiler reports:
clang++-mp-5.0 -std=c++17 -isystem /opt/local/include/ x3-optional.cc && ./a.out
In file included from x3-optional.cc:8:
In file included from /opt/local/include/boost/spirit/home/x3.hpp:14:
In file included from /opt/local/include/boost/spirit/home/x3/auxiliary.hpp:11:
In file included from /opt/local/include/boost/spirit/home/x3/auxiliary/any_parser.hpp:17:
/opt/local/include/boost/spirit/home/x3/support/traits/move_to.hpp:180:9: error: no matching function
for call to 'move_to'
detail::move_to(std::move(src), dest
^~~~~~~~~~~~~~~
/opt/local/include/boost/spirit/home/x3/char/char_parser.hpp:31:29: note: in instantiation of
function template specialization 'boost::spirit::x3::traits::move_to<const char &,
std::__1::basic_string<char> >' requested here
x3::traits::move_to(*first, attr);
^
Don't hate cause of Turbo, I already hate my school!
I wish to show an error msg if a character is entered instead of an int or float in some file such as age or percentage.
I wrote this function:
template <class Type>
Type modcin(Type var) {
take_input: //Label
int count = 0;
cin>>var;
if(!cin){
cin.clear();
cin.ignore();
for ( ; count < 1; count++) { //Printed only once
cout<<"\n Invalid input! Try again: ";
}
goto take_input;
}
return var;
}
but the output is not desirable:
How do I stop the error msg from being repeated multiple times?
Is there a better method?
NOTE: Please make sure that this is TurboC++ that we are talking about, I tried using the approach in this question, but even after including limits.h, it doesn't work.
Here, a code snippet in C++.
template <class Type>
Type modcin(Type var) {
int i=0;
do{
cin>>var;
int count = 0;
if(!cin) {
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
for ( ; count < 1; count++) { //Printed only once
cout<<"\n Invalid input! Try again: ";
cin>>var;
}
}
} while (!cin);
return var;
}
The variables are tailored to match yours' so you can understand better. This code isn't perfect though.
It can't handle cases like "1fff", here you would just get a 1 in return. I tried solving it but then a infinite loop was being encountered, when I'll fix it, I'll update the code.
It also can't function in TurboC++ effectively. I don't know if there are alternatives but the numeric_limits<streamsize>::max() argument gives a compiler error ('undefined symbol' error for numeric_limits & streamsize and 'prototype must be defined' error for max()) in Turbo C++.
So, to make it work in Turbo C++. Replace the numeric_limits<streamsize>::max() argument with some big int value such as 100.
This will make it so that the buffer is only ignored/cleared till 100 characters are reached or '\n' (enter button/newline character) is pressed.
EDIT
The following code can be executed on both Turbo C++ or proper C++. The comments are provided to explain the functioning:
template <class Type> //Data Integrity Maintenance Function
Type modcin(Type var) { //for data types: int, float, double
cin >> var;
if (cin) { //Extracted an int, but it is unknown if more input exists
//---- The following code covers cases: 12sfds** -----//
char c;
if (cin.get(c)) { // Or: cin >> c, depending on how you want to handle whitespace.
cin.putback(c); //More input exists.
if (c != '\n') { // Doesn't work if you use cin >> c above.
cout << "\nType Error!\t Try Again: ";
cin.clear(); //Clears the error state of cin stream
cin.ignore(100, '\n'); //NOTE: Buffer Flushed <|>
var = modcin(var); //Recursive Repeatation
}
}
}
else { //In case, some unexpected operation occurs [Covers cases: abc**]
cout << "\nType Error!\t Try Again: ";
cin.clear(); //Clears the error state of cin stream
cin.ignore(100, '\n'); //NOTE: Buffer Flushed <|>
var = modcin(var);
}
return var;
//NOTE: The '**' represent any values from ASCII. Decimal, characters, numbers, etc.
}
I'm currently in a traineeship and I currently have to softwares I'm working on. The most important was requested yesterday and I'm stucked on the failure of its main feature: saving passwords.
The application is developped in C++\CLR using Visual Studio 2013 (Couldn't install MFC libraries somehow, installation kept failing and crashing even after multiple reboots.) and aims to generate a password from a seed provided by the user. The generated password will be save onto a .txt file. If the seed has already been used then the previously generated password will show up.
Unfortunately I can't save the password and seed to the file, though I can write the seed if I don't get to the end of the document. I went for the "if line is empty then write this to the document" but it doesn't work and I can't find out why. However I can read the passwords without any problem.
Here's the interresting part of the source:
int seed;
char genRandom() {
static const char letters[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
int stringLength = sizeof(letters) - 1;
return letters[rand() % stringLength];
}
System::Void OK_Click(System::Object^ sender, System::EventArgs^ e) {
fstream passwords;
if (!(passwords.is_open())) {
passwords.open("passwords.txt", ios::in | ios::out);
}
string gen = msclr::interop::marshal_as<std::string>(GENERATOR->Text), line, genf = gen;
bool empty_line_found = false;
while (empty_line_found == false) {
getline(passwords, line);
if (gen == line) {
getline(passwords, line);
PASSWORD->Text = msclr::interop::marshal_as<System::String^>(line);
break;
}
if (line.empty()) {
for (unsigned int i = 0; i < gen.length(); i++) {
seed += gen[i];
}
srand(seed);
string pass;
for (int i = 0; i < 10; ++i) {
pass += genRandom();
}
passwords << pass << endl << gen << "";
PASSWORD->Text = msclr::interop::marshal_as<System::String^>(pass);
empty_line_found = true;
}
}
}
I've also tried replacing ios::in by ios::app and it doesn't work. And yes I have included fstream, iostream, etc.
Thanks in advance!
[EDIT]
Just solved this problem. Thanks Rook for putting me on the right way. It feels like a silly way to do it, but I've closed the file and re-openned it using ios::app to write at the end of it. I also solved a stupid mistake resulting in writing the password before the seed and not inserting a final line so the main loop can still work. Here's the code in case someone ends up with the same problem:
int seed;
char genRandom() {
static const char letters[] =
"0123456789"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"abcdefghijklmnopqrstuvwxyz";
int stringLength = sizeof(letters) - 1;
return letters[rand() % stringLength];
}
System::Void OK_Click(System::Object^ sender, System::EventArgs^ e) {
fstream passwords;
if (!(passwords.is_open())) {
passwords.open("passwords.txt", ios::in | ios::out);
}
string gen = msclr::interop::marshal_as<std::string>(GENERATOR->Text), line, genf = gen;
bool empty_line_found = false;
while (empty_line_found == false) {
getline(passwords, line);
if (gen == line) {
getline(passwords, line);
PASSWORD->Text = msclr::interop::marshal_as<System::String^>(line);
break;
}
if (line.empty()) {
passwords.close();
passwords.open("passwords.txt", ios::app);
for (unsigned int i = 0; i < gen.length(); i++) {
seed += gen[i];
}
srand(seed);
string pass;
for (int i = 0; i < 10; ++i) {
pass += genRandom();
}
passwords << gen << endl << pass << endl << "";
PASSWORD->Text = msclr::interop::marshal_as<System::String^>(pass);
empty_line_found = true;
}
}
passwords.close();
}
So, here's an interesting thing:
passwords << pass << endl << gen << "";
You're not ending that with a newline. This means the very end of your file could be missing a newline too. This has an interesting effect when you do this on the final line:
getline(passwords, line);
getline will read until it sees a line ending, or an EOF. If there's no newline, it'll hit that EOF and then set the EOF bit on the stream. That means the next time you try to do this:
passwords << pass << endl << gen << "";
the stream will refuse to write anything, because it is in an eof state. There are various things you can do here, but the simplest would be to do passwords.clear() to remove any error flags like eof. I'd be very cautious about accidentally clearing genuine error flags though; read the docs for fstream carefully.
I also reiterate my comment about C++/CLR being a glue language, and not a great language for general purpose development, which would be best done using C++ or a .net language, such as C#. If you're absolutely wedded to C++/CLR for some reason, you may as well make use of the extensive .net library so you don't have to pointlessly martial managed types back and forth. See System::IO::FileStream for example.
What does that * means before u, what kind of the variable it is, and what will be the output of this function.
Thanks
void inidat (int nx, int ny, float* u)
{
int ix, iy;
for (ix = 0; ix <= nx-1; ix++)
{
for (iy = 0; iy <= ny-1; iy++)
{
*(u+ix*ny+iy) = (float)(ix * (nx - ix - 1) * iy * (ny - iy - 1));
}
}
}
This is a pointer. A pointer is an object whose value refers to another value stored elsewhere in the computer memory using its address. A pointer references a location, and one can get the object stored at that location by "dereferencing" the pointer.
float * x;
cout << *x;
cout << x;
To get the value of the pointer, you do the 2nd line.
To get the location of the pointer you do the 3rd line.
* means that the follow variable is defined or used (to be used, as in this case, it must've been defined before) as a pointer.
As for the output of the function: it's void so it won't return any value but change some in the last line, I would need the context of the function to see what it's actually doing.