|
Unless LONG_MAX and LONG_MIN are valid input values, you can check return value first then check errno without being busy with errno before the function call.
<br />
long lVal = strtol(pszNum, &pEndPtr, 10);<br />
if((LONG_MAX == lVal) || (LONG_MIN == lVal))<br />
{<br />
}<br />
Your concern is valid when input value equals either LONG_MAX or LONG_MIN. Because, it returns LONG_MAX or LONG_MIN (defined limits.h) if an overflow (or underflow) condition occurs.
modified on Saturday, April 26, 2008 6:14 PM
|
|
|
|
|
Ozer Karaagac wrote: Unless LONG_MAX and LONG_MIN are valid input values
They are valid inputs and will not cause an error.
Ozer Karaagac wrote: Your concern is valid when input value equals either LONG_MAX or LONG_MIN.
Any string that equates to an integral value larger than these as well.
I guess I'm still unsure whether I can just reset errno before the call to strtol or am I required to read it, reset it, call strtol, check error, restore errno to it's original value?
|
|
|
|
|
I will try to help your decision.
For larger decimal values, you may consider to use different functions like _atoi64() or strtod() to widen the limits.
When it comes to errno, it is an immediate value. You don't have to save/restore errno unless you are going to use it afterwards. I think, this is not a good practice also. If you plan to use that value later, you should save it in another variable. Thus, resetting it before the function call is enough to see whether LONG_MAX is real result or the error flag.
Runtime library functions change this variable only when an error occurs and report the situation by returning an error value. It's also beneficial to inspect runtime library source codes that may come with your compiler (in MSVCDIR\CRT\SRC for MSVC).
I did inspect the strtol() source code just now. And it only assigns ERANGE value to errno in one line. So, any value other than ERANGE will not be related to strtol() also. But,
if((LOMG_MAX == lVal) || (LONG_MIN == lVal))
{
if(ERANGE == errno)
else
}
modified on Sunday, April 27, 2008 11:15 AM
|
|
|
|
|
Thanks for the guidance.
I think I have something upwards of 100+ books on C/C++, MFC, Windows, etc...
not to mention MSDN and none of them are very explicit about resetting errno before the call to strtol.
Granted, what they do say about it and what intuition tells me is getting pretty clear. Your comments have helped.
|
|
|
|
|
Hi All,
Having romped in the Elysian field that is C# I'm now being forced to learn C++. To this end I've managed to crawl through this book to Chapter 8 but I'm having trouble with 8-3 - using iterators instead of passing a vector.
Briefly, how is the template supposed to operate on the vector if the vector isn't passed in one form or another??
I have, without doubt, got the wrong end of the stick here...
I'm not looking to be spoon fed the answer (I don't expect anything in C++ to be easy), but an indication of how to proceed would be of immense help.
Thanks
Si
|
|
|
|
|
I think you are making a wrong assumption that people here have read the C++ book you are reading. Always ask complete question rather than pointing to the book.
If I understand question completely that you are asking how a function which is passed an iterator will operate on vector. Well the iterators point to the vector! Think of iterators as pointers so when you pass an iterator to the vector you are passing a pointer to the vector. Now iterator is not exactly a pointer but it follows pointer semantics i.e. you can deference it *it, increment it ++it, decrement it --it, etc.
If you want to read more about STL then try SGI STL[^] and it has good introduction to iterators[^].
-Saurabh
|
|
|
|
|
Hi Saurabh & thanks for replying. Actually, the assumption I was making,probably wrongly, was that only people familiar with the book would reply but perhaps I should have made that more clear; in any case apologies.
To make the question more general - we have a template function that takes a vector as an argument:
template <class T>
T median(vector<T> v)
{...}
The task is this: instead of passing the vector ('v')by value, rewrite the function to operate on iterators.
This is probably v. trivial but has me stumped.
Here's the code I have so far if anyone's interested
#include "stdafx.h"
#include <algorithm>
#include <stdexcept>
#include <iostream>
#include <vector>
using namespace std;
template <class T>
T median(vector<T> v)
{
typedef typename vector<t>::size_type vec_sz;
vec_sz size = v.size();
if (size == 0)
throw domain_error("median of an empty vector");
sort(v.begin(), v.end());
vec_sz mid = size/2;
return size % 2 == 0 ? (v[mid] + v[mid-1]) / 2 : v[mid];
}
int main()
{
vector <float> v1;
vector <int> v2;
for (int i=0; i < 10; i++)
{
v1.push_back(i+5);
v2.push_back(i+5);
}
int size = median(v1);
double sf = median(v1);
cout << "The median of the float vector v1 is " << median(v1) << endl;
cout << "The median of the int vector v2 is " << median(v2)<< endl;
system ("pause");
return 0;
}
I think what I'm asking is that if the vector isn't present in the template function, how can iterators like begin() & end() possibly work on it?
Also, why does C++ have to be so awkward and obscure and frustrating (actually no reply needed to that - I know you all love it and I don't want to start a row).
Thanks
Si
|
|
|
|
|
Okay first lets consider an example using pointers. Lets say there is an array of ints.
int array[11];
Now let us pretend that this array is only of size 10. Last element is used to mark as end of the vector.
int* begin = &array[0];
int* end = &array[10];
Now we can write a mean function as (I choose mean because its easier to show concept of iterators):
int Mean(int* begin, int* end)
{
int _mean = 0;
int _count = 0;
while(begin != end)
{
_mean += *begin;
_count++;
begin++;
}
return _mean/_count;
}
You will notice two things about this code. First, I have not passed array at all but I am able to compute mean. Second, the last location that we reserved in the array is used to find when to stop iterating an array. Thats it, this is the concept of STL iterators. Just imagine pointer is wrapped in an class and we call it iterator.
We can write mean function using generic container as:
template<typename InputIterator>
typename InputIterator::value_type Mean(InputIterator begin, InputIterator end)
{
typename InputIterator::value_type _mean = 0;
int _count = 0;
while(begin != end)
{
_mean += *begin;
_count++;
begin++;
}
return _mean/_count;
}
Now lets see the requirement in the type of InputIterator. begin and end are used in 3 places in Mean function - begin != end, *begin, and begin++. So the iterator class should should only support these operators. Notice all these three operations are supported by pointer as well. So you can call this mean function for arrays we well.
double points[11] = {0};
double mean = Mean(&points[0], &points[10]);
You can also do this:
std::vector<int> points;
points.push_back(1.0);
points.push_back(2.0);
points.push_back(3.0);
.
.
.
points.push_back(10.0);
double mean = Mean(points.begin(), points.end());
Hope this makes things clear.
-Saurabh
modified on Sunday, April 27, 2008 8:55 AM
|
|
|
|
|
Hi Saurabh,
Yes indeed that makes things crystal clear! - thank you very much for a brilliant answer. In my head I somehow equated iterators with variables. But, then, I am an idiot so that's not particularly surprising. What do iterators do? They iterate, of course: 1,2,3,4,etc. etc. So if iterators are passed you aren't passing fixed values but the ability to process through a range that they contain. How could I be so thick??
Thanks again for your patience and a really clear and concise answer.
Si
|
|
|
|
|
Hey Oliver,
You are most welcome. You got it correctly. Iterators iterate over a container and more importantly they iterate through a given range. So using iterators you can process only a part of array which is not possible when passing array itself and its size without extra arguments.
-Saurabh
|
|
|
|
|
Hi Saurabh,
OK here's the code I've knocked together as a solution:
#include "stdafx.h"
#include <algorithm>
#include <stdexcept>
#include <iostream>
#include <vector>
using namespace std;
template<typename inputiterator>
typename InputIterator::value_type median(InputIterator begin, InputIterator end)
{
vector<typename> v;
typedef typename vector<typename>::size_type vec_sz;
//After the while loop, below, begin == end so can't use the while loop again.
//So chuck everything in a vector and work on that
//Does this save processing over simply passing a vector into
// the template?
//Is this the way it should be done??
//Who knows - all I know is it works and I can finally move on
//Some people do this for fun, you know...
while (begin != end)
{
v.push_back(*begin);
begin++;
}
vec_sz size = v.size();
if (size == 0)
throw domain_error("median of an empty vector");
sort(v.begin(),v.end());
vec_sz mid = size/2;
return size % 2 == 0 ? (v[mid] + v[mid-1]) / 2 : v[mid];
}
int main()
{
vector <int> v2;
v2.push_back(3);v2.push_back(13);v2.push_back(7);v2.push_back(5);v2.push_back(21);v2.push_back(23);
v2.push_back(23);v2.push_back(40);v2.push_back(23);v2.push_back(14);v2.push_back(12);
v2.push_back(56);v2.push_back(23);v2.push_back(29);
//median of v2 shuld be 22. See http://www.mathsisfun.com/median.html
cout << "The median of the int vector v2 is " << median(v2.begin(),v2.end())<< endl;
system ("pause");
return 0;
}
The only niggle is that after using the while loop to get the size, 'begin' equalled 'end' and so I couldn't iterate through again to find the mid point. In the end I created a vector and put everything in there. This kind of made sense but I can't help feeling I'm missing something by using another vector... perhaps there is a way to reset the iterators after they have been used once (i.e. in the while loop)
Cheers
Si
|
|
|
|
|
Okay try this code.
template<typename InputIterator>
typename InputIterator::value_type median(InputIterator begin, InputIterator end)
{
size_t _size = end - begin;
if(_size == 0)
{
throw std::domain_error("median of an empty vector");
}
sort(begin, end);
size_t mid = _size/2;
return _size % 2 == 0 ? (*(begin+mid) + *(begin+mid-1)) / 2 : *(begin+mid);
}
sort function in STL needs that InputIterator be a model of RandomAccessIterator i.e. ith element in the array can be accessed using array[i]. Thus Inputiterator for Median should also be RandomAccessIterator. For random iterators we can determine size of array simply by subtracting last iterator from the first iterator (they behave exactly like pointers to array) Rest all is just like an array, simple pointer arithmetic. This function has a serious side effect that it sorts the original v2. It you don't want to sort it then try nth_element function in the <algorithm class="">.
-Saurabh
|
|
|
|
|
Of course - begin and end reference the place in the vector as well as the contents of that place. Superb - I think that covers that question pretty completely.
Thanks once again, Saurabh - you've saved me a whole load of time trying to sort this one out.
Question 8-4 next...what's the betting I'll be back on here tomorrow !!
Cheers,
Si
|
|
|
|
|
You are most welcome Oliver.
-Saurabh
|
|
|
|
|
Hi,
I was just trying to get one of the sample programs compiled. It has customized entry point function configured using directive
#pragma comment (linker, "/entry:\"something\"") which the compiler didn't seem to recognize, it returned something like "error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTStartup LIBCMTD.lib". How can I get this right? I'm using VS 2005.
Thanks,
|
|
|
|
|
I think the problem is in the syntax. There is no need for quotes for the function name. Try this.
#pragma comment(linker, "/entry:something")
-Saurabh
|
|
|
|
|
how to write other language font(text) in edit control not english
Trioum
|
|
|
|
|
|
I need code in c++ not in .net
Trioum
|
|
|
|
|
Hi...
Install new font(what u would like to see in u r edit control)
1) Create variable for Edit control m_font.
CEdit m_ctrlEdit;
2) Create varible for CFont
CFont m_font;
3)Initialize with new Font..
m_font = CreateFont(,.....,....,m_fontName) /* see in MSDN
m_edit.SetFont(&m_font);
Try this..
I am able to display "xxxxxxx.ttf" with this appproach..
|
|
|
|
|
Oh it was my mistake anyway you can use of CFont class of MFC and then use of SetFont.
|
|
|
|
|
Here is a code snippet about CListCtrl from MSDN. And I don't think MSDN give correct code.
int index = m_myListCtrl.GetTopIndex();<br />
int last_visible_index = index + m_myListCtrl.GetCountPerPage();<br />
if (last_visible_index > m_myListCtrl.GetItemCount())<br />
last_visible_index = m_myListCtrl.GetItemCount();<br />
<br />
while (index <= last_visible_index)<br />
{<br />
<br />
index++;<br />
}
IMO, variable last_visible_index is more than one. So the While statement should be written like this:
while (index < last_visible_index)
Am I wrong? Or MSND?
Thank you all!
A Chinese VC++ programmer
|
|
|
|
|
Your Question:
Is MSDN wrong?
You asked:
Am I wrong? Or MSND?
What is wrong? you...?
Anyway, Did you implement this code?
Mukesh Kumar
Software Engineer
|
|
|
|
|
Yes, I didn't run this code. But look at this :
last_visible_index = m_myListCtrl.GetItemCount();
The max index of a CListCtrl is m_myListCtrl.GetItemCount() - 1 not m_myListCtrl.GetItemCount().
Any way ,thank you!
A Chinese VC++ programmer
|
|
|
|
|
Mukesh Kumar wrote: What is wrong? you...?
Nope thats why asking the question!
"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow Never mind - my own stupidity is the source of every "problem" - Mixture
cheers,
Alok Gupta
VC Forum Q&A :- I/ IV
Support CRY- Child Relief and You
|
|
|
|