... operator in function - c++11

Sorry for the noob question. I've been immersed in Java for the past while and the book for this course doesn't cover C++.
I have to fill in a function to add keywords (of string type) to an Item object. the prototype of the function is as follows.
void addKeywordsForItem(const Item* const item, int nKeywords, ...);
In Java ... returns the remainder of arguments as a String object and I'm guessing C++ does something similar but I don't know the name of ... so searching for it is rather difficult.
What is ... called and what does it do?

What is ... called and what does it do?
There are multiple places where ... is used in C++. The context in which you are using it, it is called variadic arguments.
The standard header cstdarg provides a type and macros to help you extract specific arguments from variadic arguments.
Example code from http://en.cppreference.com/w/cpp/utility/variadic/va_start:
#include <iostream>
#include <cstdarg>
int add_nums(int count, ...)
{
int result = 0;
va_list args;
va_start(args, count);
for (int i = 0; i < count; ++i) {
result += va_arg(args, int);
}
va_end(args);
return result;
}
int main()
{
std::cout << add_nums(4, 25, 25, 50, 50) << '\n';
}

Related

Accepting and printing a string

Can we accept and print a string like this in c++?
This code is not working properly.
#include<iostream>
#include<string>
using namespace std;
main()
{
string a;char ch;
for(int i=0;i<5;i++)
{cin>>ch;
a[i]=ch;
}
a[5]='\0';
cout<<a;
}
I am able to print individual elements like a[1],a[2],etc but unable to print the entire string.Why?
If you want to take a string, you could do the following.
#include <iostream>
int main() {
std::string str;
std::getline(std::cin, str);
std::cout << str;
}
Also, C++ automatically null terminates any string literal you use.
Well it's not really anywhere near best-practices but to fix your immediate issue you need to actually resize the string.
#include<iostream>
#include<string>
main()
{
std::string a;char ch;
a.resize(5); // <--- reserves memory
for(int i=0;i<5;i++)
{
std::cin>>ch;
a[i]=ch;
}
a[5]='\0'; //<-- unnecessary
st::cout<<a;
}
alternatively you can append the characters
#include<iostream>
#include<string>
main()
{
std::string a;char ch;
for(int i=0;i<5;i++)
{
std::cin>>ch;
a+=ch;
}
std::cout<<a;
}
The real problem here is not that you can't read or can't print the string, is that you are writing to unallocated memory. operator[], which is what you are using when you do something like a[i]=ch, does not do any kind of boundary checking and thus you are causing undefined behavior. In my machine, nothing is printed, for instance.
In short, you need to make sure that you have space to write your characters. If you are certain that you are going to read 5 characters (and adding a \0 at the end, making it 6 in length), you could do something like this:
std::string a(6, '\0')
If you are uncertain of how many characters you are going to read, std::string is ready to allocate space as need, but you need to use std::push_back to give it a chance to do so. Your loop contents would be something like:
cin >> ch;
a.push_back(ch);
If you are uncertain where the std::string object is coming from (as in, this is library code that accepts a std::string as an argument, you could use at(i) (e.g, a.at(i) = ch instead of a[i] = ch), which throws an exception if it is out of range.
You can print the string like this
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a;char ch;
for(int i=0;i<5;i++)
{
cin>>ch;
a.push_back(ch);
}
a.push_back('\0');
cout << a;
return 0;
}

C++ sequential container initialization using iterator

I'm trying to create sub containers of a container through container<\T>(InputIt First, InputIt Last). For example, I have a string s1="AreYouOK".
The expected outputs are
A
Ar
Are
AreY
AreYo
AreYou
AreYouO
Here is my code:
#include <vector>
#include <string>
#include <iostream>
using std::vector;
using std::string;
using std::cout;
using std::cin;
using std::endl;
int main()
{
string s1 = "AreYouOK";
vector<string> v;
for (string::const_iterator iter = s1.begin();
iter != s1.end()-1; ++iter)
{
string s(s1.begin(),iter); // no matching container
s += *iter;
v.push_back(s);
}
for (vector<string>::const_iterator iter = v.begin();
iter != v.end(); ++iter)
{
cout << *iter <<endl;
}
return 0;
}
I expect the commented line
string s(s1.begin(),iter);
to create a substring s of string s1 in range [s1.begin(), iter), since iter is an iterator of s1. However, I was told that there is no matching constructor for initialization.
error: no matching constructor for initialization of 'string'
(aka 'basic_string<char, char_traits<char>, allocator<char> >')
string s(s1.begin(),iter);
^ ~~~~~~~~~~~~~~~
While
string s(s1.begin(),s1.begin+3);
did manage to create a substring.
Why
string s(s1.begin(),iter);
did not work?
Many thanks!
If you look here, for example, you can see that a full error message contains
prog.cpp:19:33: error: no matching function for call to 'std::basic_string<char>::basic_string(std::basic_string<char>::iterator, std::basic_string<char>::const_iterator&)'
which says that it thinks your calling a constructor that takes an iterator and (reference to) const_iterator. There is no such constructor. Since s1 is a non-const object, s1.begin() returns a regular iterator.
There are many ways around this. One of them is to change your loop to
string::const_iterator b = s1.begin();
for (string::const_iterator iter = b;
iter != s1.end()-1; ++iter)
{
string s(b,iter);
...
Here you indeed use two const iterators (see here your expected output).
Edit
Two excellent (and superior) alternatives are:
Use cbegin if you're C++11 enabled (#rici)
Use accumulate, once you get to that algorithm (#PaulMcKenzie)

std::string::assign vs std::string::operator=

I coded in Borland C++ ages ago, and now I'm trying to understand the "new"(to me) C+11 (I know, we're in 2015, there's a c+14 ... but I'm working on an C++11 project)
Now I have several ways to assign a value to a string.
#include <iostream>
#include <string>
int main ()
{
std::string test1;
std::string test2;
test1 = "Hello World";
test2.assign("Hello again");
std::cout << test1 << std::endl << test2;
return 0;
}
They both work. I learned from http://www.cplusplus.com/reference/string/string/assign/ that there are another ways to use assign . But for simple string assignment, which one is better? I have to fill 100+ structs with 8 std:string each, and I'm looking for the fastest mechanism (I don't care about memory, unless there's a big difference)
Both are equally fast, but = "..." is clearer.
If you really want fast though, use assign and specify the size:
test2.assign("Hello again", sizeof("Hello again") - 1); // don't copy the null terminator!
// or
test2.assign("Hello again", 11);
That way, only one allocation is needed. (You could also .reserve() enough memory beforehand to get the same effect.)
I tried benchmarking both the ways.
static void string_assign_method(benchmark::State& state) {
std::string str;
std::string base="123456789";
// Code inside this loop is measured repeatedly
for (auto _ : state) {
str.assign(base, 9);
}
}
// Register the function as a benchmark
BENCHMARK(string_assign_method);
static void string_assign_operator(benchmark::State& state) {
std::string str;
std::string base="123456789";
// Code before the loop is not measured
for (auto _ : state) {
str = base;
}
}
BENCHMARK(string_assign_operator);
Here is the graphical comparitive solution. It seems like both the methods are equally faster. The assignment operator has better results.
Use string::assign only if a specific position from the base string has to be assigned.

Enum to string in C++11

I realize this has been asked before more than once on SO but I couldn't find a question explicitly looking for a current solution to this issue with C++11, so here we go again..
Can we conveniently get the string value of an enum with C++11?
I.e. is there (now) any built-in functionality in C++11 that allows us to get a string representation of enum types as in
typedef enum {Linux, Apple, Windows} OS_type;
OS_type myOS = Linux;
cout << myOS
that would print Linux on the console?
The longstanding and unnecessary lack of a generic enum-to-string feature in C++ (and C) is a painful one. C++11 didn't address this, and as far as I know neither will C++14.
Personally I'd solve this problem using code generation. The C preprocessor is one way--you can see some other answers linked in the comments here for that. But really I prefer to just write my own code generation specifically for enums. It can then easily generate to_string (char*), from_string, ostream operator<<, istream operator<<, is_valid, and more methods as needed. This approach can be very flexible and powerful, yet it enforces absolute consistency across many enums in a project, and it incurs no runtime cost.
Do it using Python's excellent "mako" package, or in Lua if you're into lightweight, or the CPP if you're against dependencies, or CMake's own facilities for generating code. Lots of ways, but it all comes down to the same thing: you need to generate the code yourself--C++ won't do this for you (unfortunately).
In my opinion, the most maintainable approach is to write a helper function:
const char* get_name(OS_type os) {
switch (os) {
case Linux: return "Linux";
case Apple: return "Apple";
case Windows: return "Windows";
}
}
It is a good idea not to implement the "default" case, since doing so will ensure that you get a compiler warning if you forget to implement a case (with the right compiler and compiler settings).
I like a hack using the C preprocessor, which I first saw here:
http://blogs.msdn.com/b/vcblog/archive/2008/04/30/enums-macros-unicode-and-token-pasting.aspx .
It uses the token-pasting operator # .
// This code defines the enumerated values:
#define MY_ENUM(x) x,
enum Fruit_Type {
MY_ENUM(Banana)
MY_ENUM(Apple)
MY_ENUM(Orange)
};
#undef MY_ENUM
// and this code defines an array of string literals for them:
#define MY_ENUM(x) #x,
const char* const fruit_name[] = {
MY_ENUM(Banana)
MY_ENUM(Apple)
MY_ENUM(Orange)
};
#undef MY_ENUM
// Finally, here is some client code:
std::cout << fruit_name[Banana] << " is enum #" << Banana << "\n";
// In practice, those three "MY_ENUM" macro calls will be inside an #include file.
Frankly, it's ugly and. but you end up typing your enums exactly ONCE in an include file, which is more maintainable.
BTW, on that MSDN blog link (see above) a user made a comment with a trick that makes the whole thing much prettier, and avoids #includes:
#define Fruits(FOO) \
FOO(Apple) \
FOO(Banana) \
FOO(Orange)
#define DO_DESCRIPTION(e) #e,
#define DO_ENUM(e) e,
char* FruitDescription[] = {
Fruits(DO_DESCRIPTION)
};
enum Fruit_Type {
Fruits(DO_ENUM)
};
// Client code:
std::cout << FruitDescription[Banana] << " is enum #" << Banana << "\n";
(I just noticed that 0x17de's answer also uses the token-pasting operator)
Here is a simple example using namespaces and structs.
A class is created for each enum item. In this example i chose int as the type for the id.
#include <iostream>
using namespace std;
#define ENUMITEM(Id, Name) \
struct Name {\
static constexpr const int id = Id;\
static constexpr const char* name = #Name;\
};
namespace Food {
ENUMITEM(1, Banana)
ENUMITEM(2, Apple)
ENUMITEM(3, Orange)
}
int main() {
cout << Food::Orange::id << ":" << Food::Orange::name << endl;
return 0;
}
Output:
3:Orange
== Update ==
Using:
#define STARTENUM() constexpr const int enumStart = __LINE__;
#define ENUMITEM(Name) \
struct Name {\
static constexpr const int id = __LINE__ - enumStart - 1;\
static constexpr const char* name = #Name;\
};
and using it once before the first usage of ENUMITEM the ids would not be needed anymore.
namespace Food {
STARTENUM()
ENUMITEM(Banana)
ENUMITEM(Apple)
ENUMITEM(Orange)
}
The variable enumStart is only accessible through the namespace - so still multiple enums can be used.
You can use macro to solve this problem:
#define MAKE_ENUM(name, ...) enum class name { __VA_ARGS__}; \
static std::vector<std::string> Enum_##name##_init(){\
const std::string content = #__VA_ARGS__; \
std::vector<std::string> str;\
size_t len = content.length();\
std::ostringstream temp;\
for(size_t i = 0; i < len; i ++) {\
if(isspace(content[i])) continue;\
else if(content[i] == ',') {\
str.push_back(temp.str());\
temp.str(std::string());}\
else temp<< content[i];}\
str.push_back(temp.str());\
return str;}\
static const std::vector<std::string> Enum_##name##_str_vec = Enum_##name##_init();\
static std::string to_string(name val){\
return Enum_##name##_str_vec[static_cast<size_t>(val)];\
}\
static std::string print_all_##name##_enum(){\
int count = 0;\
std::string ans;\
for(auto& item:Enum_##name##_str_vec)\
ans += std::to_string(count++) + ':' + item + '\n';\
return ans;\
}
As the static variable can only be initialized once, so the Enum_##name##_str_vec will use the Enum_##name##_init() function to initialize itself at first.
The sample code is as below:
MAKE_ENUM(Analysis_Time_Type,
UNKNOWN,
REAL_TIME,
CLOSSING_TIME
);
Then you can use below sentence to print an enum value:
to_string(Analysis_Time_Type::UNKNOWN)
And use below sentence to print all enum as string:
print_all_Analysis_Time_Type_enum()
As mentioned, there is no standard way to do this. But with a little preprocessor magic (similar to AlejoHausner's second contribution) and some template magic, it can be fairly elegant.
Include this code once:
#include <string>
#include <algorithm>
#define ENUM_VALS( name ) name,
#define ENUM_STRINGS( name ) # name,
/** Template function to return the enum value for a given string
* Note: assumes enums are all upper or all lowercase,
* that they are contiguous/default-ordered,
* and that the first value is the default
* #tparam ENUM type of the enum to retrieve
* #tparam ENUMSIZE number of elements in the enum (implicit; need not be passed in)
* #param valStr string version of enum value to convert; may be any capitalization (capitalization may be modified)
* #param enumStrs array of strings corresponding to enum values, assumed to all be in lower/upper case depending upon
* enumsUpper
* #param enumsUpper true if the enum values are in all uppercase, false if in all lowercase (mixed case not supported)
* #return enum value corresponding to valStr, or the first enum value if not found
*/
template <typename ENUM, size_t ENUMSIZE>
static inline ENUM fromString(std::string &valStr, const char *(&enumStrs)[ENUMSIZE], bool enumsUpper = true) {
ENUM e = static_cast< ENUM >(0); // by default, first value
// convert valStr to lower/upper-case
std::transform(valStr.begin(), valStr.end(), valStr.begin(), enumsUpper ? ::toupper : ::tolower);
for (size_t i = 0; i< ENUMSIZE; i++) {
if (valStr == std::string(enumStrs[i])) {
e = static_cast< ENUM >(i);
break;
}
}
return e;
}
Then define each enum like so:
//! Define ColorType enum with array for converting to/from strings
#define ColorTypes(ENUM) \
ENUM(BLACK) \
ENUM(RED) \
ENUM(GREEN) \
ENUM(BLUE)
enum ColorType {
ColorTypes(ENUM_VALS)
};
static const char* colorTypeNames[] = {
ColorTypes(ENUM_STRINGS)
};
You only have to enumerate the enum values once and the code to define it is fairly compact and intuitive.
Values will necessarily be numbered in the default way (ie, 0,1,2,...). The code of fromString() assumes that enum values are in either all uppercase or all lowercase (for converting from strings) that the default value is first, but you can of course change how these things are handled.
Here is how you get the string value:
ColorType c = ColorType::BLUE;
std::cout << colorTypeNames[c]; // BLUE
Here is how you set the enum from a string value:
ColorType c2 = fromString<ColorType>("Green", colorTypeNames); // == ColorType::GREEN

Main C Program does not find header and methods

Wasn't really sure how to explain this any better in the title. Basically I am learning how to separate my code in C. I have a main, the equivalent of an ArrayList class from java (but converted to c and is very basic) and a header file which declares my struct and all the functions in use. I am using all sample code out of the text and I am using the latest version of dev c++ for windows 8.
Every time I try to compile main I get:
In function main undefined reference to "newList"
[Error] Id returned 1 exit status
Here is my code:
main.c
#include <stdio.h>
#include "ArrayList.h"
int main(int numParms, char *parms[]){
list myList;
myList = newList(myList);
printf("End");
return 0;
}
ArrayList.c
#include <stdio.h>
#include "ArrayList.h"
list newList(list myList){
myList.size = 0;
return myList;
}
list add(list myList, int value){
myList.values[myList.size] = value;
myList.size++;
return myList;
}
int get(list myList, int position){
int entry;
entry = myList.values[position];
return entry;
}
int size(list myList){
return myList.size;
}
list delete(list myList, int position){
int count;
for(count =0; count<(myList.size-1); count++){
myList.values[count] = myList.values[count+1];
}
myList.size --;
return myList;
}
void print(list myList){
int count;
printf("Current list contents:\n");
if (myList.size > 0){
for (count=0; count<myList.size; count++){
printf("Element %d is %d\n", count, get(myList, count));
}
printf("\n");
}
else{
printf("The list is empty\n\n");
}
}
ArrayList.h
#define MAX_SIZE 100
typedef struct{
int size;
int values[MAX_SIZE];
}list;
list newList(list);
list add(list, int);
int get(list, int);
int size(list);
list delete(list, int);
void print(list);
That is actually a linker problem. The compilation is OK, but when the linker tries to assemble the pieces it can't find newList anywhere. My guess would be that you did not compile the file ArrayList.c and link the result to your project.

Resources