string::length has the return type of size_t, but it seems to able to be put into an int without any casting or anything. Why can I assign a size_t to an int in this case?
int main() {
string line;
getline(cin, line);
cout << line << endl;
int i = line.size();
int j = line.length();
cout << i << " " << j << endl;
}
The size_t values are being narrowed. In c++11, you could make this fail with an error by doing:
#include <string>
int main() {
std::string line;
int i{line.size()};
int j{line.length()};
}
The errors produced look like:
gh.cc:5:11: error: non-constant-expression cannot be narrowed from type 'size_type' (aka 'unsigned long') to 'int' in initializer list [-Wc++11-narrowing]
int i{line.size()};
^~~~~~~~~~~
gh.cc:5:11: note: override this message by inserting an explicit cast
int i{line.size()};
^~~~~~~~~~~
static_cast<int>( )
gh.cc:6:11: error: non-constant-expression cannot be narrowed from type 'size_type' (aka 'unsigned long') to 'int' in initializer list [-Wc++11-narrowing]
int j{line.length()};
^~~~~~~~~~~~~
gh.cc:6:11: note: override this message by inserting an explicit cast
int j{line.length()};
^~~~~~~~~~~~~
static_cast<int>( )
size_t is a 32 bit integer.
Go to your compiler directory and open the stdio.h file.
There is a declaration, something like this:
typedef unsigned int size_t;
Related
I would like to create a C++ script that uses map to execute heterogeneous functions, and stores the input/output in a map.
To deal with the heterogeneity I though to use the any type.
However, this creates problems, since the function pointer is not able to convert other type in any type.
Here is a minimal example that is not working, but illustrates what I would like to do:
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <map>
#include <any>
using namespace std;
string funct1(int a, int b)
{
int c= a+b;
string name = to_string(c);
return name ;
}
float funct2(int a, int b)
{
// float b2
float c=a-b;
return c ;
}
int main(void)
{
cout << "START" << endl;
std::map<std::string, std::any> ListObjIn; //
std::map<std::string, std::any> ListObjOut; //
typedef std::any (*FnPtr)(std::any, int);
std::map<std::string, FnPtr> ListCommand; //
//
ListObjIn["a1"] = 1;
ListObjIn["a2"] = 1.5;
ListCommand["do1"]= funct1;
ListCommand["do2"]= funct2;
// ListObjOut["res1"]= ListCommand["do1"]( std::any_cast<int>(ListObjIn["a1"]), 2);
ListObjOut["res1"]= ListCommand["do1"]( ListObjIn["a1"], 2);
cout << "RESULT 1=" << std::any_cast<string>(ListObjOut["res1"]) << endl;
ListObjOut["res2"]= ListCommand["do2"]( ListObjIn["a2"], 2);
cout << "RESULT 2=" << std::any_cast<string>(ListObjOut["res2"]) << endl;
cout << "END" << endl;
return(0);
}
I get the following error:
g++ -std=c++17 ./test.cpp
./test.cpp: In function ‘int main()’:
./test.cpp:34:24: error: invalid conversion from ‘std::__cxx11::string (*)(int, int) {aka std::__cxx11::basic_string<char> (*)(int, int)}’ to ‘std::map<std::__cxx11::basic_string<char>, std::any (*)(std::any, int)>::mapped_type {aka std::any (*)(std::any, int)}’ [-fpermissive]
ListCommand["do1"]= funct1;
^~~~~~
./test.cpp:35:24: error: invalid conversion from ‘float (*)(int, int)’ to ‘std::map<std::__cxx11::basic_string<char>, std::any (*)(std::any, int)>::mapped_type {aka std::any (*)(std::any, int)}’ [-fpermissive]
ListCommand["do2"]= funct2;
^~~~~~
I tried to change the input and output type of the function (ie string and float) to any, but this creates problems of conversion at other places.
So it is possible to have something very close to my original example, keeping the heterogeneity of type in/out and map of functions ? Or should think to workaround ? if so, which one ?
You should probably generify return type with std::any:
https://godbolt.org/z/G1EhqY
string phone_nb = "173";
char just_one_char = phone_nb[1];
int i_just_one_char = stoi(just_one_char);
I get these errors:
no matching function for call to 'stoi'
int i_just_one_char = stoi(just_one_char);
note: candidate function not viable: no known conversion from 'char' to 'const std::__1::string' (aka 'const basic_string<char, char_traits<char>, allocator<char> >') for 1st argument
_LIBCPP_FUNC_VIS int stoi (const string& __str, size_t* __idx = 0, int __base = 10);
note: candidate function not viable: no known conversion from 'char' to 'const std::__1::wstring' (aka 'const basic_string<wchar_t, char_traits<wchar_t>, allocator<wchar_t> >') for 1st argument
_LIBCPP_FUNC_VIS int stoi (const wstring& __str, size_t* __idx = 0, int __base = 10);
You can try something like this:
#include <iostream>
#include <string>
int main() {
std::string phone_nb = "173";
int i_just_one_char = phone_nb[0] - '0';
std::cout << i_just_one_char;
}
Which works by relying on how characters/ASCII is structured to convert from a character to its integer equivalent.
The above code will output a 1.
The easiest fix for your code would be to just use atoi instead of stoi
You can modify your code like this:
string phone_nb = "173";
char just_one_char_str[2];
just_one_char_str[0] = phone_nb[1];
just_one_char_str[1] = '\0';
int i_just_one_char = atoi(just_one_char);
You can read up more on atoi() here
Alternative
As mentioned by #RemyLebeau, one could also use the substr() function and get a similar result or could also use the answer by #Rietty
string phone_nb = "173";
string just_one_char = phone_nb.substr(0, 1);
int i_just_one_char = stoi(just_one_char);
The code compiles, and runs as expected using Visual Studio. I understand that never guarantees it will compile/run elsewhere, but I don't understand why in this instance. Perhaps someone can help clarify? The g++ compiler gives me errors at line 45 where the vector of vectors of type RGB are declared:
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
using namespace std;
/* The following color method uses the provided formula to determine
the float value of each (i,j) coordinate passed as parameters. */
float color (int i, int j)
{
float col = float (((i & 0x08) == 0) ^ ((j & 0x08) == 0));
return col;
}
int main()
{
// The provided RGB object that stores each rgb value:
struct RGB
{
float r;
float g;
float b;
};
int w;
int h;
string filename;
float c; // to store the result from the color method.
cin >> w >> h >> filename;
// A vector of vectors to represent the 2D array:
vector< vector<RGB> > rgb(h, vector<RGB>(w));
for (int i = 0; i < h; i++)
for (int j = 0; j < w; j++)
{
c = color(i, j);
rgb[i][j].r = c;
rgb[i][j].g = c;
rgb[i][j].b = c;
}
ofstream ppmfile;
ppmfile.open (filename);
ppmfile << "P3\n" << w << " " << h << endl;
ppmfile << "255\n";
for (int i = 0; i < h; i++)
{
// The following loop uses integer multiplication to output to the ppm
// file the rgb values converted to integers on the 0-255 scale.
for (int j = 0; j < w; j++)
{
ppmfile << rgb[i][j].r * 255 << " ";
ppmfile << rgb[i][j].g * 255 << " ";
ppmfile << rgb[i][j].b * 255;
if (j != (w-1))
ppmfile << " ";
}
ppmfile << endl;
}
return 0;
}
Here's the full list of errors that pop up in g++:
hw1.cxx: In function 'int main()':
hw1.cxx:45: error: template argument for 'template<class _Alloc> class std::allocator' uses local type 'main()::RGB'
hw1.cxx:45: error: trying to instantiate 'template<class _Alloc> class std::allocator'
hw1.cxx:45: error: template argument 2 is invalid
hw1.cxx:45: error: template argument 1 is invalid
hw1.cxx:45: error: template argument 2 is invalid
hw1.cxx:45: error: invalid type in declaration before '(' token
hw1.cxx:45: error: template argument for 'template<class _Alloc> class std::allocator' uses local type 'main()::RGB'
hw1.cxx:45: error: trying to instantiate 'template<class _Alloc> class std::allocator'
hw1.cxx:45: error: template argument 2 is invalid
hw1.cxx:45: error: initializer expression list treated as compound expression
hw1.cxx:51: error: invalid types 'int[int]' for array subscript
hw1.cxx:52: error: invalid types 'int[int]' for array subscript
hw1.cxx:53: error: invalid types 'int[int]' for array subscript
hw1.cxx:57: error: no matching function for call to 'std::basic_ofstream<char, std::char_traits<char> >::open(std::string&)'
/usr/local/gcc443/lib/gcc/i386-pc-solaris2.10/4.4.3/../../../../include/c++/4.4.3/fstream:696: note: candidates are: void std::basic_ofstream<_CharT, _Traits>::open(const char*, std::_Ios_Openmode) [with _CharT = char, _Traits = std::char_traits<char>]
hw1.cxx:67: error: invalid types 'int[int]' for array subscript
hw1.cxx:68: error: invalid types 'int[int]' for array subscript
hw1.cxx:69: error: invalid types 'int[int]' for array subscript
As I remember C++03 forbids using types with internal linkage in templates.
You should pull the RGB class from the main() function
In C++03 (which is almost certainly what you're getting with g++ 4.4.3) the problem is that local types and types with internal linkage can't be used as template parameters. In this case your RGB class is defined within main and isn't eligible to be used as a parameter to vector.
The restrictions were loosened in C++11 but I can't recall if (function) local types are still forbidden. Visual studio may be using C++11 rules while g++ is not.
I see two errors:
vector< vector<RGB> > rgb(h, vector<RGB>(w));
C++03 does not allow this for a type that is "local" to your function so move the definition out of main().
Also the open function does not take std::string as an argument but const char *. So change
ppmfile.open (filename);
to
ppmfile.open( filename.c_str() );
I'm trying to use both sort and qsort to sort a c-style string and them see which of them is better, so I've written this code, but it is not working , so can you please tell me what is wrong with it.
thanks in advance.
#include <iostream>
#include<vector>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<chrono>
#include<string>
#include<sstream>
using namespace std;
using namespace std::chrono;
void bvect(vector<double> &vec, int num)
{
auto gen = bind(normal_distribution<double>(15,4.0),default_random_engine());
for(int i=0; i<num; ++i)
vec.push_back(gen());
}
char* converttostring(int number)
{
stringstream ss;
ss << number;
return (ss.c_str());
}
int cst_cmp(const void *one, const void *two)
{
char a = *((char*)one);
char b = *((char*)two);
return strcmp(a, b);
}
//Generated random strings
void textvect(vector<string> &vec, int num)
{
srand(time(NULL));
for(int i=0; i<num; ++i)
vec.push_back(converttostring(rand()%num +1));
}
void displayvector(vector<char*>vect)
{
for (int i=0; i<vect.size(); ++i){
for (int j=0; j<strlen(vect[i]); ++j)
cout<<vect[i][j];
cout<<endl;
}
}
int main(){
int sz=100000;
vector<char*>text1, text2;
textvect(text1, sz);
text2.resize(text1.size());
copy(text1.begin(),text1.end(),text2.begin());
// qsort() string
auto t1 = system_clock::now();
qsort(&text1[0], text1.size(), sizeof(char*), cst_cmp);
auto t2 = system_clock::now();
auto dms = duration_cast<milliseconds>(t2-t1);
cout << "string qsort() took " << dms.count() << " milliseconds\n";
// sort() string
auto t3 = system_clock::now();
std::sort(text2.begin(), text2.end());
auto t4 = system_clock::now();
auto dms1 = duration_cast<milliseconds>(t4-t3);
cout << "string sort() took " << dms1.count() << " milliseconds\n";
return 0;
}
For std::sort, you are just using the default comparator, which will just compare pointer values. You need to pass a comparator that does a proper comparison (using strcmp, for example):
std::sort(text2.begin(), text2.end(),
[](const char* lhs, const char* rhs) { return strcmp(lhs,rhs) < 0; });
That's one problem, there may be others.
One problem is in your compare function for qsort:
int cst_cmp(const void *one, const void *two)
{
char a = *((char*)one);
char b = *((char*)two);
return strcmp(a, b);
}
You are not comparing strings here, because a and b are just chars. You might as well avoid them:
int cst_cmp(const void *one, const void *two)
{
return (strcmp(*(char **)one, *(char **)two));
}
These are the errors I obtain trying to compile your code:
> g++ main.cc -std=c++0x
main.cc: In function ‘char* converttostring(int)’:
main.cc:24:15: error: ‘std::stringstream’ has no member named ‘c_str’
main.cc: In function ‘int cst_cmp(const void*, const void*)’:
main.cc:31:23: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
/usr/include/string.h:143:12: error: initializing argument 1 of ‘int strcmp(const char*, const char*)’ [-fpermissive]
main.cc:31:23: error: invalid conversion from ‘char’ to ‘const char*’ [-fpermissive]
/usr/include/string.h:143:12: error: initializing argument 2 of ‘int strcmp(const char*, const char*)’ [-fpermissive]
main.cc: In function ‘int main()’:
main.cc:55:23: error: invalid initialization of reference of type ‘std::vector<std::basic_string<char> >&’ from expression of type ‘std::vector<char*>’
main.cc:35:6: error: in passing argument 1 of ‘void textvect(std::vector<std::basic_string<char> >&, int)’
24:15 c_str() is a member function of string not of stringstream. See here.
31:23 strcmp() wants two const char * not two char. See here.
55:23 and 35:6 char* is not the same type as string.
This function isn't working
char* converttostring(int number)
{
stringstream ss;
ss << number;
return (ss.c_str());
}
and if it was sort of fixed (ss.str().c_str()), it would return a pointer to a temporary.
If you have a compiler with some C++11 support, you can use std::to_string from the standard library. Otherwise, change the return type to std::string (no pointer!).
Ask Stroustrup ;) just allocate space for the C string array and enter characters ino it.. remember to deallocate it..
I'm a new code monkey in training, and I'm currently having issues working with arrays and structs.
Currently I have a main file where I have a an Array of Records declared. I pass that array to an external function, where a quick sort is performed on the with of the fields in the record. Mainly the first name. I'm having an issues where I copy elements in the array of records, to a temporary array for the sorting algorith. I know that c++ does have a qsort function built in, but for what I'm working on right now, I need to have the algoritm written out the way it is. I was able to get this to work using only any array.
I'm getting the following error when trying to compile with the make file.
make
g++ -c -o main2.o main2.cpp
g++ -c externArray2.cpp -o externArray2.o
externArray2.cpp: In function ‘void copytemp(EmployeeRecord*, EmployeeRecord*, int, int)’:
externArray2.cpp:52: error: cannot convert ‘float’ to ‘void*’ for argument ‘1’ to ‘void* memcpy(void*, const void*, size_t)’
externArray2.cpp:53: error: cannot convert ‘float’ to ‘void*’ for argument ‘1’ to ‘void* memcpy(void*, const void*, size_t)’
externArray2.cpp:54: error: cannot convert ‘float’ to ‘void*’ for argument ‘1’ to ‘void* memcpy(void*, const void*, size_t)’
externArray2.cpp:55: error: cannot convert ‘float’ to ‘void*’ for argument ‘1’ to ‘void* memcpy(void*, const void*, size_t)’
externArray2.cpp:56: error: cannot convert ‘float’ to ‘void*’ for argument ‘1’ to ‘void* memcpy(void*, const void*, size_t)’
externArray2.cpp:57: error: cannot convert ‘float’ to ‘void*’ for argument ‘1’ to ‘void* memcpy(void*, const void*, size_t)’
externArray2.cpp:58: error: cannot convert ‘float’ to ‘void*’ for argument ‘1’ to ‘void* memcpy(void*, const void*, size_t)’
externArray2.cpp:59: error: cannot convert ‘float’ to ‘void*’ for argument ‘1’ to ‘void* memcpy(void*, const void*, size_t)’
externArray2.cpp:60: error: cannot convert ‘float’ to ‘void*’ for argument ‘1’ to ‘void* memcpy(void*, const void*, size_t)’
make: *** [externArray2.o] Error 1
Make File
test1: main.o ExternArray.o
g++ main.o ExternArray.o -o test1
externArray.o: ExternArray.cpp
g++ -c ExternArray.cpp -o ExternArray.o
main.o: main.cpp
g++ -c main.cpp -o main.o
Header.h
#ifndef _INCL_GUARD
#define _INCL_GUARD
const int maxEmployee =10;
const int NAMES = 5;
const int LENGTH = 15;
typedef struct EmployeeRecord
{
char first[10];
char last[10];
float reghours;
float ovrhours;
float pay;
float gross;
float defer;
float state;
float fed;
float ssi;
float net;
} EmployeeRecord;
#endif
main.cpp
#include <iostream>
#include <cstring>
using namespace std;
#include "./Header2.h"
void showArray(EmployeeRecord employees[], int, const char*); //Function Prototype 3.1
extern void qsortArray(EmployeeRecord employees[], int, int); //Funvtion Prototype 3.2
int main(void)
{
EmployeeRecord myEmployee[maxEmployee];
strcpy(myEmployee[0].first,"John");
strcpy(myEmployee[0].last,"Doe");
strcpy(myEmployee[1].first,"Ed");
strcpy(myEmployee[1].last, "Whittle");
strcpy(myEmployee[2].first, "Louise");
strcpy(myEmployee[2].last, "Marion");
strcpy(myEmployee[3].first,"Paula");
strcpy(myEmployee[3].last, "Prentiss");
strcpy(myEmployee[4].first, "Carl");
strcpy(myEmployee[4].last, "Davidson");
showArray(myEmployee, NAMES, "Before Sort");
qsortArray(myEmployee, 0, 4 );
showArray(myEmployee, NAMES, "After Sort");
return 0;
}
void showArray(EmployeeRecord employees[], int emp, const char *message)
{
cout << message << endl;
for (int test = 0; test < emp; test++)
{
cout << "First Name: " << employees[test].first << endl;
cout << "Last Name: " << employees[test].last << endl;
}
}
ExternArray.cpp
#include <cstring>
#include <iostream>
#include <iomanip>
#include <stdio.h>
using namespace std;
#include "./Header2.h"
void qsortArray(EmployeeRecord employees[], int, int); //Funvtion Prototype 3.2
void copytemp(EmployeeRecord tmpEmp[], EmployeeRecord emp[], int, int);
void qsortArray(EmployeeRecord employees[], int start, int finish)
{
int left=start,
right=finish;
char pivot[15];
strcpy(pivot, employees[(start+finish)/2].first);
while (left < right) {
cout << pivot << " pivot " << endl;
cout << "outer loop" << endl;
// find left candidate
while (strcmp(employees[left].first,pivot) <0) left++;
// find right candidate
cout << "First Inner Loop" << endl;
while (strcmp(employees[right].first,pivot) > 0 )right--;
cout << "Inner Loop" << endl;
if (left <= right)
{
EmployeeRecord tmpEmployee[1];
cout << "Create new struct" << endl;
copytemp(tmpEmployee, employees, 0, left);
cout << "copy to temp" << endl;
copytemp(tmpEmployee, employees, 1, right);
copytemp(employees, tmpEmployee, left, 1);
copytemp(employees, tmpEmployee, right, 0);
left++;
right--;
cout << "All copy done" <<endl;
}
} // while left < right
cout << "Back out of outer Loop" << endl;
if (start < right) qsortArray(employees,start,right);
if (left < finish) qsortArray(employees,left,finish);
}
void copytemp(EmployeeRecord tmpEmp[], EmployeeRecord emp[], int first, int secound)
{
memcpy(tmpEmp[first].first, emp[secound].first, sizeof(emp[secound].first));
memcpy(tmpEmp[first].last, emp[secound].last, sizeof(emp[secound].last));
memcpy(tmpEmp[first].reghours, emp[secound].reghours, sizeof(emp[secound].reghours));
memcpy(tmpEmp[first].ovrhours, emp[secound].ovrhours, sizeof(emp[secound].ovrhours));
memcpy(tmpEmp[first].pay, emp[secound].pay, sizeof(emp[secound].pay));
memcpy(tmpEmp[first].gross, emp[secound].gross, sizeof(emp[secound].gross));
memcpy(tmpEmp[first].defer, emp[secound].defer, sizeof(emp[secound].defer));
memcpy(tmpEmp[first].state, emp[secound].state, sizeof(emp[secound].state));
memcpy(tmpEmp[first].fed, emp[secound].fed, sizeof(emp[secound].fed));
memcpy(tmpEmp[first].ssi, emp[secound].ssi, sizeof(emp[secound].ssi));
memcpy(tmpEmp[first].net, emp[secound].net, sizeof(emp[secound].net));
}
In C you can copy an entire struct with a plain assignment
tmpElm[first] = emp[secound];
This is only problematic if the struct contains members which are pointers, which is not your case.
Try:
memcpy(&(tmpElm[first].first, &(emp[second].first), sizeof(emp[second].first));
The difference is that you need to pass an address of a float rather than a float value.
You may find that with C++ you need to cast the float pointer that the address of operator (&) gives you to a void, since C++ has stronger typing rules than C.
memcpy((void *)&(tmpElm[first].first, (void *)&(emp[second].first), sizeof(emp[second].first));
There are a few other ways to get the address of something when arrays are involved, but this is the simplest for a new programmer.