I have a school project and I have to use the AM in the Student.h as a char*.The AM have to have numbers in it. I can't understand why what I am doing is not working.
Student.cpp
#include <iostream>
#include <string>
#include "Student.h"
using namespace std;
int main()
{
Student dlg;
dlg.AM[10]={2,1,3,9,0,2,6,6};
}
Student.h
#pragma once
#include <string>
using namespace std;
class Student
{
public:
char *AM[20];
string Name;
unsigned int Semester = 1;
};
If you really need your student number to be a char string, then you need to convert your ints to char* before assigning them to the array.
int main()
{
Student dlg;
int j = 0;
for (auto i : {2,1,3,9,0,2,6,6})
{
auto strInt { std::to_string(i) }; // create a C++ string containing a int
// next copy the internal memory of the C++ string to a read-writable memory buffer
// and assign a pointer to that buffer casted to a char* to the appropriate slot in the array
dlg.AM[j++] = static_cast<char*> (std::memcpy (new char[16], strInt.c_str(), strInt.size()));
}
// test
for (int i = 0; i < 8; i++)
{
cout << dlg.AM[i] << ' ';
}
}
Are you sure the student number should be a char* ?
I want to transfer a function to calculate the row of a text file.
The compile can pass but the function can not be transferred. I want to know what happens.
#include<iostream>
#include<fstream>
#include<string>
using namespace std;
int getLine( const char *filename)
{
ifstream infile(filename,ios::in);
if(!infile){
cout<<"can not open"<<filename<<'\n';
return 0;
}
int count=0;
infile.unsetf(ios::skipws);
char buff[300];
while(infile.getline(buff,300))
count++;
cout<<"the total line:"<<count<<endl;
infile.close();
return 0;
}
int getLineNoEmpty(const char* filename)
{
ifstream infile(filename,ios::in);
if(!infile){
cout<<"can not open"<<filename<<'\n';
return 0;
}
int count=0;
char buff[300];
while(infile.getline(buff,300))
{
if(sizeof(buff)==0)
continue;
else
count++;
}
cout<<"the total line without null string:"<<count<<endl;
return 0;
}
int main()
{
char filename[256];
cout<<"input filename:";
cin>>filename;
int getLine(const char &filename);
int getLineNoEmpty(const char &filename);
return 0;
}
The compile can pass but the function can not be transferred. I want to know what happens about it. It can output the result I want. And I don't know how to
realize the goal of calculating the total line without null string.
Firstly, You are just declaring 2 functions in main() without using them. Change
int main()
{
char filename[256];
cout<<"input filename:";
cin>>filename;
int getLine(const char &filename);
int getLineNoEmpty(const char &filename);
return 0;
}
to
int main()
{
char filename[256];
cout<<"input filename:";
cin>>filename;
getLine(filename);
getLineNoEmpty(filename);
return 0;
}
I run some tests to validate my preconceived idea about constructors speed but the results were very different from what I expected. Am I doing something wrong? What is that I'm missing?
I'm using MVS 2015 with no optimizations (but it doesn't matter the results are always equivalent).
class Person
{ using ushort = unsigned short;
string name_;
ushort age_;
public:
explicit Person(const string &name, ushort age) //1
{ name_ = name;
age_ = age;
}
explicit Person(const string &name,ushort age) : name_{name},age_{age} //2
{
}
explicit Person(string name, ushort age) : name_{ std::move(name) }, age_{ age } //3
{
}
};
//1 - Is always faster than the other ctors.
//2 - Is slightly slower than 1 (negligible!!).???
//3 - Takes 50% more time than 1. ???
I run the tests using small strings(8 bytes), 1K, 2K string sizes..
I was expecting //2 ctor to be the fastest, and not expecting that //3 took so much time.
A last question is it legal what I'm doing in //3 ctor?
UPDATE
Here's the code I wrote
class Person
{
using ushort = unsigned short;
private:
std::string name_;
ushort age_;
public:
static constexpr size_t nr_ctors = 3;
static const char * const ctor_signature[nr_ctors];
enum class CTOR_1
{ CTOR = 0
};
enum class CTOR_2
{ CTOR = 1
};
enum class CTOR_3
{ CTOR = 2
};
explicit Person(const std::string &name, ushort age,CTOR_1)
{ name_ = name;
age_ = age;
}
explicit Person(const std::string &name, ushort age, CTOR_2) : name_{name},age_{age}
{}
explicit Person(std::string name,ushort age,CTOR_3) : name_{std::move(name)},age_{age}
{}
};
const char * const Person::ctor_signature[Person::nr_ctors] = {"\nexplicit Person(const std::string &name, ushort age,CTOR_1)",
"\nexplicit Person(const std::string &name, ushort age, CTOR_2) : name_{name},age_{age}",
"\nexplicit Person(std::string name,ushort age,CTOR_3) : name_{std::move(name)},age_{age}"};
using mclock = std::chrono::high_resolution_clock;
using time_p_t = std::chrono::time_point<mclock>;
using precision_t = std::chrono::nanoseconds;
#define NR_ITERATIONS (128 * 1024)
template <typename Ty_>
precision_t time_no_heap(const std::string &name)
{
time_p_t t_0;
time_p_t t_1;
t_0 = mclock::now();
Person p = Person{name,66,Ty_::CTOR};
t_1 = mclock::now();
return t_1 - t_0;
}
template <typename Ty_>
precision_t time_with_heap(const std::string &name)
{
time_p_t t_0;
time_p_t t_1;
Person *p_person;
t_0 = mclock::now();
p_person = new Person{ name,66,Ty_::CTOR };
t_1 = mclock::now();
delete p_person;
return t_1 - t_0;
}
void print_statistics(int iterations, size_t str_size, const precision_t(&stats)[2][Person::nr_ctors])
{
std::cout << "\nTotal iterations : "
<< iterations
<< "\nString ize : "
<< str_size
<< std::endl;
for (int i = 0; i < Person::nr_ctors; ++i)
{ std::cout << Person::ctor_signature[i]
<< "\n\t Stack (ms) : "
<< std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(stats[0][i]).count()
<< "\n\t Heap (ms) : "
<< std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(stats[1][i]).count()
<< std::endl;
}
}
int main(int argc, const char *argv[])
{
int iterations;
std::string *p_name;
if (argc != 3 && argc != 1)
{ std::cout << "USAGE [<iterations>K <string size>]" << std::endl;
return -1;
}
else if (argc == 3)
{ iterations = std::atoi(argv[1]) * 1024;
p_name = new std::string(std::atoi(argv[2]), 'x');
}
else
{ iterations = NR_ITERATIONS;
p_name = new std::string{ "Benchmark" };
}
precision_t benchmark [2][Person::nr_ctors]{};
std::cout << "\nUsing string : " << *p_name << ".\nIterating : " << iterations << " times." << std::endl;
for (auto i = iterations; --i >= 0; )
{ //Stack allocation
benchmark[0][(int)Person::CTOR_1::CTOR] += time_no_heap<Person::CTOR_1>(*p_name);
benchmark[0][(int)Person::CTOR_2::CTOR] += time_no_heap<Person::CTOR_2>(*p_name);
benchmark[0][(int)Person::CTOR_3::CTOR] += time_no_heap<Person::CTOR_3>(*p_name);
//Heap allocation
benchmark[1][(int)Person::CTOR_1::CTOR] += time_with_heap<Person::CTOR_1>(*p_name);
benchmark[1][(int)Person::CTOR_2::CTOR] += time_with_heap<Person::CTOR_2>(*p_name);
benchmark[1][(int)Person::CTOR_3::CTOR] += time_with_heap<Person::CTOR_3>(*p_name);
}
print_statistics(iterations,p_name->size(),benchmark);
delete p_name;
return 0;
}
I was being mistaken by the debug version of MVS which presents results completely different and opposite to release version even with the same project settings! My mistake..
Benchmarking with no optimizations is meaningless.
What string are you passing as name? A very important factor is the length of the string, and whether or not it will trigger SBO (small buffer optimization).
If the string is short enough, moves won't be any faster than copies.
Also, what does your benchmark look like? It might be that your benchmarking code is flawed.
I would also expect //2 to be the fastest, lets have a look at what the difference constructors do.
//1: name_ is default constructed and then copy assigned.
//2: name_ is copy constructed.
//3: name is copy constructed and then name_ is move constructed.
The difference between //1 and //2 will grow as default construction becomes more expensive.
//3 is valid since the argument name only lives inside the constructor so we can steal the innards by move constructing name_.
Nicolai Josuttis have a great talk from CppCon 2017 on this.
I got some different results when I tried to benchmark your code.
The benchmark runs on a pool of AWS Machines, compiled with Clang 5.0 C++17 -O3.
#include <string>
class Person1
{ using ushort = unsigned short;
std::string name_;
ushort age_;
public:
explicit Person1(const std::string &name, ushort age) //1
{ name_ = name;
age_ = age;
}
};
class Person2
{ using ushort = unsigned short;
std::string name_;
ushort age_;
public:
explicit Person2(const std::string &name,ushort age) : name_{name},age_{age} //2
{
}
};
class Person3
{ using ushort = unsigned short;
std::string name_;
ushort age_;
public:
explicit Person3(std::string name, ushort age) : name_{ std::move(name) }, age_{ age } //3
{
}
};
static void CreatePerson1(benchmark::State& state)
{
for (auto _ : state) {
Person1 person("Hello World!!!!!!!!!!!!", 10);
}
}
BENCHMARK(CreatePerson1);
static void CreatePerson2(benchmark::State& state)
{
for (auto _ : state) {
Person2 person("Hello World!!!!!!!!!!!!", 10);
}
}
BENCHMARK(CreatePerson2);
static void CreatePerson3(benchmark::State& state)
{
for (auto _ : state) {
Person3 person("Hello World!!!!!!!!!!!!", 10);
}
}
BENCHMARK(CreatePerson3);
With a small string (8 bytes) the second constructor was the fastest followed by the third. See result here Quick C++ Benchmarks
With a larger string (20 bytes) the third constructor was the fastest followed by the second. See result here Quick C++ Benchmarks
You make a copy in the third case. Instead this, try something like this:
class Person
{ using ushort = unsigned short;
string name_;
ushort age_;
public:
explicit Person(string&& name, ushort age) : name_{ std::move(name) }, age_{ age } //3
{
}
explicit Person(const string &name, ushort age) //1
{
name_ = name;
age_ = age;
}
explicit Person(const string &name,ushort age) : name_{name},age_{age} //2
{
}
};
R-value usage has to improve the performance.
Or you can create one constructor for aboce r-value and l-value like this:
class Person
{ using ushort = unsigned short;
string name_;
ushort age_;
public:
template<typename T>
explicit Person(T&& name, ushort age) : name_{ std::forward<T>(name) }, age_{ age } //3
{
}
};
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <stdlib.h>
using namespace std;
struct trienode
{
map<char, struct trienode*> m;
bool endofword;
};
struct trienode* create_node()
{
struct trienode* new_node = (struct trienode*)malloc(sizeof(struct trienode));
new_node->endofword = false;
return new_node;
};
void word_insert(struct trienode* root, string word)
{
struct trienode* curr = root;
for (unsigned int i =0; i < word.size(); i++) {
if (curr->m.find(word[i]) == curr->m.end()) {
struct trienode* new_node = create_node();
***curr->m.insert(pair<char, struct trienode*>(word[i], new_node) );***
}
curr = curr->m.find(word[i])->second;
}
curr->endofword = true;
}
int main()
{
struct trienode* root = NULL;
root = create_node();
vector<string> v = {"aspirin", "aspetol", "astray", "atran", "chronic"};
for (unsigned int i =0; i < v.size(); i++) {
word_insert(root, v[i]);
}
}
I am trying to build a trie data structure to hold a set of strings. I have written a word_insert() function to insert a word into the trie. For inserting a word into the trie, I start at the root node, see if the map in the root node contains the char and if yes, I proceed to the next charachter. If the char is not present in the map of the node, I create another trienode and insert an entry into the map. However, when I am doing this, I see a problem with my code. My code hangs at the point where I try to insert the (char, struct trienode*) pair into the map.
Could someone tell me what is wrong with that? Thank you.
Here is what I am supposed to do.
Here is what I did.(on codeblocks IDE with minGW compiler)
#include <iostream>
using namespace std;
class person
{
private:
string name;
int age;
double height;
double weight;
public:
void set_private_members(string n, int a, double h, double w)
{
name = n;
age = a;
weight = h;
height = w;
}
void print_private_members()
{
cout <<"The name of person is:- "<<name<<"\n The age of person is:- " <<age<<"\n The weight of person is:- "<<weight;
cout <<"\n The height of person is:- "<<height<<endl;
}
};
void modify_person(person);
int main()
{
person p;
p.set_private_members("Ayush",19,165.7,47.2);
cout <<"We are in main function right now \n";
p.print_private_members();
modify_person(p);
cout <<"We are now back in main function \n The values of object passed to modify_person function are as \n";
p.print_private_members();
return 0;
}
void modify_person(person z)
{
cout <<"We are in modify_person function \n Modifying person details... \n";
z.set_private_members("Priyanshi",15,159.1,50.6);
cout <<"The details are now as:- \n";
z.print_private_members();
}
Here is the output to this code
however the expected output is to have priyanshi details in the class object when print_private_members function is called in main() for the last time.
Who is wrong? Me or they? I think if I call modify_person by reference then the expected should come.