n=b.size()
n = max(n,(int)a.size());
where a and b are some user-Input strings and n is an integer. would anybody tell me why we use (int)a.size() and what is the purpose of using (int).
I am assuming that n is of type int, and your program will be something like this :
#include <iostream>
#include <string>
using namespace std;
int main ()
{
string a ("Test string");
string b ("Test two");
int n = b.size() ;
n = max(n,(int)a.size());
cout << "n : " << n ;
return 0;
}
Now if you see the documentation for the .size() method of the string class, you will see it returns value of type : size_t
size_t is an unsigned integral type (the same as member type
string::size_type)
: as per documentation
Now when we look at the documentation for max() you can see it uses templating (you can read more about templating here) what it essentially means is that you can use any type as parameter (int, float, etc..) but both the parameters need to be the same type.
Now since n was declared as an int when calling max(n,x);, x needs to be type of n which basically means int in our case.
Now this is the reason for using (int) before a.size(). What we are doing here is type casting, since a.size() returns in type size_t which is different from int (You can read more about this here), we need to typecast the return value to int which can be done by (int)a.size().
SIDE NOTE
int n = max(b.size(),a.size());
cout << "n : " << n << " \n";
would also work, since both are same type so no need to do type casting.
Related
In the following code
#include<iostream>
template<typename T,size_t N>
void cal_size(T (&a)[N])
{
std::cout<<"size of array is: "<<N<<std::endl;
}
int main()
{
int a[]={1,2,3,4,5,6};
int b[]={1};
cal_size(a);
cal_size(b);
}
As expected the size of both the arrays gets printed. But how does N automatically gets initialized to the correct value of the array-size (arrays are being passed by reference)? How is the above code working?
N does not get "initialized" to anything. It is not a variable. It is not an object. N is a compile-time constant. N only exists during compilation. The value of N as well as the actual T is determined by the process called template argument deduction. Both T and N are deduced from the actual type of the argument you pass to your template function.
In the first call the argument type is int[6], so the compiler deduces that T == int and N == 6, generates a separate function for that and calls it. Let's name it cal_size_int_6
void cal_size_int_6(int (&a)[6])
{
std::cout << "size of array is: " << 6 << std::endl;
}
Note that there's no T and no N in this function anymore. Both were replaced by their actual deduced values at compile time.
In the first call the argument type is int[1], so the compiler deduces that T == int and N == 1, generates a separate function for that as well and calls it. Let's name it cal_size_int_1
void cal_size_int_1(int (&a)[1])
{
std::cout << "size of array is: " << 1 << std::endl;
}
Same thing here.
Your main essentially translates into
int main()
{
int a[]={1,2,3,4,5,6};
int b[]={1};
cal_size_int_6(a);
cal_size_int_1(b);
}
In other words, your cal_size template gives birth to two different functions (so called specializations of the original template), each with different values of N (and T) hardcoded into the body. That's how templates work in C++.
It works because the type of a is "array of length 6 of int" and the type of b is "array of length 1 of int". The compiler knows this, so it can call the correct function. In particular, the first call calls the template instance cal_size<6>() and the second call calls cal_size<1>(), since those are the only template instantiations which match their respective arguments.
If you attempted to call an explicit template instance, it would only work if you got the size right, otherwise the arguments wouldn't match. Consider the following:
cal_size(a); // ok, compiler figures out implicitly that N=6
cal_size<int, 6>(a); // also ok, same result as above
cal_size<int, 5>(a); // ERROR: a is not of type "array of length 5 of int"
when you declare int a[] = {1,2,3} it is the same as (or will be rewritten as) int a[3] = {1,2,3} since the templated function is receiving argument in form of T a[N], then N will have value of 3.
do variables automatically convert to the type required by the function as the appropriate arguments?
#include <stdio.h>
void swap(int &i, int &j) { //the arguments here are int&
int temp = i;
i = j;
j = temp;
}
int main(void) {
int a = 10;
int b = 20;
swap(a, b); // but a and b does not match the exact types of arguments
cout >> "A is %d and B is %d\n" >> a >> b;
return 0;
}
The type conversion rules are rather complex to explain in general.
But for your example, both parameters are int&, which means "reference to int". Since you pass two valid int variables, it's exactly the type expected and the reference of the variables is passed as argument.
Would you have tried with a different type, it would have failed, for example :
long a=10,b=20; would have failed to compile since it is not possible to get an int reference to refer to the non-int original variables.
swap(10,20); would have failed, because the parameters are literal int values and not variables. It is not possible to get a reference to such a value.
const int a=10; would also have failed. This time because the const of the variable is an additional constraint that the parameter passing is not allowed to losen.
Not related: You should include <iostream> and the output should look like:
std::cout << "A is "<< a << " and B is " << b << std::endl;;
The short answer is "sometimes".
The long answer is very long, and you should read this web page: https://en.cppreference.com/w/cpp/language/implicit_conversion
There are a lot of rules for when various types are implicitly converted to other types -- and when they are not.
I am trying to implement a diffie-hellman key exchange system. For my P and G value, I plan to use the one defined in the RFC5114 2.1. So I have the following code:
#Code
#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>
using namespace boost::multiprecision;
using namespace std;
int main(){
uint1024_t P;
P = 0xB10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371;
cout << "P is: " << P << endl;
cout << "Maximum value for uint1024_t is:" <<std::numeric_limits<uint1024_t>::max() << endl;
return 0;
}
#Output
P is: 16077765716036174705
Maximum value for uint1024_t is:179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137215
// that value is equal to 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
// which is larger than the value that i try to assign to P
#Warning
warning: integer constant is too large for its type
so...
###What am I doing wrong here? And how can i fix this?
You can construct the integer from a string:
uint1024_t P = "0xB10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371";
However this will construct the literal at runtime. If you want to have it be constructed at compile time, you can use the user-defined literals provided by boost::multiprecision:
constexpr auto P = 0xB10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C69A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C013ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD7098488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708DF1FB2BC2E4A4371_cppui1024;
The type of an integer literal in C++ is at most (unsigned) long long int (or some larger type if the implementation supports it). In your case the literal is too large and will therefore be narrowed to that type.
See boost::multiprecision documentation part 1 and part 2.
#include <iostream>
using namespace std;
int main()
{
char x;
cout << "enter a character:";
cin >> x;
cout << "ASCII Value of " << x << "is" << string(x);
return 0 ;
}
the error is
main.cpp||In function 'int main()':|
main.cpp|10|error: invalid conversion from 'char' to 'const char*'|
main.cpp|10|error: initializing argument 1 of 'std::basic_string<_CharT, _Traits,_Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char, _Traits = std::char_traits<char>, _Alloc = std::allocator<char>]'|
||=== Build finished: 2 errors, 0 warnings ===|
std::cout << "ASCII Value of " << x << "is" << (int)x;
is one way (the cast circumvents the special treatement of a char type by the I/O stream library), but this will output your platform's encoded value of the character, which is not necessarily ASCII.
A portable solution is much more complex: You'll need to encode the ASCII set in a 128 element array of elements capable of storing a 7 bit unsigned value, and map x to a suitable element of that.
There are 3 approaches to solving this problem:
Use to_string
Passing the correct value to cout
Using the std::string class correctly
The solutions are marked (numbers in comment).
Use std::to_string
Since C++11, there is function to convert numbers to a string (to_string):
/*(1)*/ std::cout << std::to_string( x );
There is no specialization for a char parameter. So the value is implictly converted.
Passing the correct value to cout
cout would display the value of char object as a character.
If we want to output the value of a char object, we need to convert it to a type which is output by cout as a number instead of a character.
The C++ standard guarantees:
1 == sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long)
So any of those integer types can be used. Usually int is selected.
There are 4 conversions that can be used here:
1) Implicit - "Implicit conversions are performed whenever an expression of some type T1 is used in context that does not accept that type, but accepts some other type T2;"
/*(2)*/ int i = x;
std::cout << i;
2) Explicit - "Converts between types using a combination of explicit and implicit conversions."
/*(3)*/ std::cout << (int)x;
/*(4)*/ std::cout << int(x); // unsigned int(x) - is invalid,
// has to be a single-word type name
3) A named cast.
/*(5)*/ std::cout << static_cast<int>(x);
4) Use the T{e} notation for construction
/*(6)*/ std::cout << int{x};
The T{e} construction syntax makes it explicit that construction is desired. The T{e} construction syntax doesn’t allow narrowing. T{e} is the only safe and general expression for constructing a value of type T from an expression e. The casts notations T(e) and (T)e are neither safe nor general.
About conversions the C++ Core Guidelines specifies the following (among others)
ES.48: Avoid casts
ES.49: If you must use a cast, use a named cast
ES.64: Use the T{e}notation for construction
In this case I would suggest (3) or (4).
Using the std::string class correctly
string is a specialization of basic_string
using string = basic_string<char>;
basic_string has many constructors.
There are only 2 constructors, which can take a predefined number of chars;
basic_string( size_type count, CharT ch, const Allocator& alloc = Allocator() );
Constructs the string with count copies of character ch. The behavior is undefined if count >= npos.
/*(7)*/ std::string s = std::string( 1, x );
basic_string( const CharT* s, size_type count, const Allocator& alloc = Allocator() );
Constructs the string with the first count characters of character string pointed to by s. s can contain null characters. The length of the string is count. The behavior is undefined if s does not point at an array of at least count elements of CharT, including the case when s is a null pointer.
/*(8)*/ std::string s = std::string( &x, 1 );
#include <iostream>
using namespace std;
int main()
{
char x;
cout<< "enter a character:";
cin>>x;
cout<< "ASCII Value of "<< x<< "is"<< int(x);
return 0 ;
}
you mean return try this code
#include <iostream>
using namespace std;
int main()
{
char x;
cout<< "enter a character:";
cin>>x;
cout<< "ASCII Value of "<< x<< "is"<< char(x);
return 0 ;
}
try this its called return
I am trying to return values (namely rows and columns) upon a file read, and since I will be reading in multiple files and getting the same variables from each file, I thought it will be better for me to write a function rather than copying and pasting duplicate codes.
Anyway, I am trying to return 2 values and to use them too, please see my code below:
#include <iostream>
#include <fstream>
using namespace std;
int r(string fn);
int main()
{
int a, b = r("input_a.txt");
cout << "a --- " << a << endl;
cout << "b --- " << b << endl;
}
int r(string fn)
{
ifstream fin01;
string file = fn;
fin01.open(file.c_str());
...
...
...
// Suppose I should be getting 2 for 'rows' and 3 for 'cols'
return rows, cols;
}
I got 0x7fff670778ec and 0x7fff670778e8 for my output instead...
Any pointers?
You cannot return two values from a function that is declared to have a single int as return type:
int r(string fn){
/*...*/
return rows,cols; // <-- this is not correct
}
Also the way you call this function is not behaving as you might expect:
int a, b = r("input_a.txt");
this declares two integers and initializes the second one with the return value of the function, but the first one stays uninitialized (see TerraPass answer for more explanation on the comma operator).
You basically have two options. First option is to pass references to the function and the function assigns the results to those references:
void r(string fn, int& rows,int& cols) {
/*...*/
rows = x;
cols = y;
}
and you call it like this:
int a,b;
r("someString",a,b);
However, in this way the caller has to "prepare" those return values. Imho it is more convenient to use the return value to return results from a function (sounds logical, no?). To do this you just have to define a type that encapsulates the two integers:
struct RowAndCol { int row;int col; };
RowAndCol r(string fn) {
/*...*/
RowAndCol result;
result.row = x;
result.col = y;
return result;
}
and call it like this:
RowAndCol rc = r("someString");
Note that you could also use a std::pair<int,int> instead of defining your custom struct (see e.g. molbdnilos answer). However, IMHO whenever you know exactly what is contained in the pair, it is better to give it a reasonable name (e.g. RowAndCol) instead of using a naked std::pair<int,int>. This will also help you in case you need to add more methods to the struct later (e.g you might want to overload the std::ostream& operator<< for your struct to print it on the screen).
PS: Actually your output does not look like it was produced by the code you are showing. Theses are some memory addresses, but in your code there is neither a pointer nor an address-of operator.
I guess you're used to Python (I peeked at your profile), but the comma does not create a pair in C++.
(You may not have thought about it that way, but you can only return one value from a Python function, too. If you "return two values", you're returning one pair.)
Fortunately, there are tuples in the standard library.
#include <iostream>
#include <fstream>
#include <utility>
std::pair<int,int> r(std::string fn);
int main()
{
std::pair<int, int> result = r("input_a.txt");
cout << "a --- " << result.first << endl;
cout << "b --- " << result.second << endl;
// Or,
int a = 0;
int b = 0;
std::tie(a, b) = r("input_a.txt");
cout << "a --- " << a << endl;
cout << "b --- " << b << endl;
}
std::pair<int, int> r(std::string fn)
{
std::ifstream fin01(fn);
// ...
return std::make_pair(rows, cols);
}
Functions in C++ cannot return multiple values of their return type via a return statement.
int a, b = r("input_a.txt");
...
return rows, cols;
These 2 lines don't do what you think they do.
The line int a, b = r("input_a.txt"); is equivalent to:
int a;
int b = r("input_a.txt");
That is, you declare variables a and b and initialize b to the return value of r("input_a.txt"), while a remains uninitialized.
The line return rows, cols; is equivalent to:
rows;
return cols;
...and is an example of comma operator, which evaluates its left operand (in your case, rows), discards the result, then evaluates its right operand (in your case, cols) and returns the result of this evaluation. So, in effect, your function r(), as it is now, always returns a single value, cols.
If you need to return more than one value from a function, you should consider accepting additional arguments as non-const references for you to store resulting values to, or changing the return type of your function to some struct, which would contain all of the values you want to return. You can find an example of both these approaches in #tobi303's answer.