C++ Constructor from char* to int[]/int* - c++

I have a constructor with parameter char* (only numbers) and I would like make a simple mathematical operations. I thought to add new parameter to constructor int[]/int* to make it easier.
header:
class BigNum {
char *value;
int* arr;
public:
BigNum(char*, int * = 0) {};
BigNum();
};
cpp:
BigNum::BigNum(char* value, int *tab){
int length = sizeof(value) / sizeof(char*);
for (int i = 0; i < length; i++) {
arr[i] = value[i];
}
}
Can I do something like this? It does not even compile.
What I could to do to on this sample change char* to int.

its not even compile
It doesn't compile because you have defined BigNum(char*, int *) twice. Once in the header, and then in the source file.
Solution: Only define the constructor once. Extra hint: When a program doesn't compile, the compiler will tell you why in the diagnostic message.
This doesn't do what you think it does:
int length = sizeof(value) / sizeof(char*);
length will always be 1, because the type of value is char*. I suspect that your intention is that value points to an array and you want to calculate the length of that array. Well, calculating the length of an array from a pointer to an element of that array is not possible.
Solution: You have to a) pass the length of the array as an argument or b) specify that the array must be a terminated string, in which case you can calculate the length by iterating the string until the termination character is found.
You access arr[i] without initializing arr:
arr[i] = value[i];
The behaviour is undefined.
Solution: You have to allocate an array.
what i could to do to on this sample change char* to int.
It depends on how you want to change it. If you want to convert a pointed character digit to int, you can use the fact that digits are required to be sequential in all native character encodings (that are supported by C++). From that fact, we know that subtracting the value of digit character from the value of 0 character, we get the numeric value that the digit character represents:
char* c = address_of_some_digit;
int value_of_digit = '0' - *c;

Related

Integers and/or array of integers into a single int array using variadic function

I'm trying to write a function, with a variable number of integer/int array parameters, that concatenates all the elements into a single 1-dimensional array. I'm struggling with one of the two scenarios where current_item turns out to be an array instead of just an integer. How can I access the individual elements of this array and assign them to pOutList?
typedef unsigned short WORD;
int PinListJoin(WORD * pOutList, ...) {
int index=0;
boolean isArray = false;
va_list next_item;
va_start(next_item, pOutList);
WORD current_item = va_arg(next_item, WORD);
int current_item_size = sizeof(current_item) / sizeof(WORD);
if (current_item_size > 1) {
isArray = true;
for (int pinidx = 0; pinidx < current_item_size; pinidx++) {
pOutList[index] = current_item;
index++;
}
}
else {
isArray = false;
pOutList[index] = current_item;
index++;
}
va_end(next_item);
return(current_item_size);
}
boolean isArray = false;
There is no boolean datatype in C++.
Also, the value of neither isArray nor index variable is ever used in the function.
typedef unsigned short WORD;
WORD current_item = va_arg(next_item, WORD);
This isn't going to work. Variadic arguments are promoted. unsigned short promotes to int (typically; on some exotic system, it might be unsigned int). Using the non-promoted type with va_arg will cause undefined behaviour. You could use a trick like this to get the correct type for any system:
using promoted_word = decltype(+WORD(0));
WORD current_item = WORD(va_arg(next_item, promoted_word));
WORD current_item = va_arg(next_item, WORD);
int current_item_size = sizeof(current_item) / sizeof(WORD);
The size of WORD divided by the size of WORD is always 1. There's no point in doing this.
I'm struggling with one of the two scenarios where current_item turns out to be an array instead of just an integer. How can I access the individual elements of this array and assign them to pOutList?
Function argument cannot be an array. But it can be a pointer to an element of an array, which I assume is what you mean. If that is the case, then you can get the pointer out of varargs like this:
WORD* current_item = va_arg(next_item, WORD*);
You can then copy the elements from array to array just like you would using any pointer to an element.
There's still two problems though: 1. There is no way of finding out the size of the array based on that pointer and 2. There is no way of finding out what type of arguments were passed (i.e. whether it was a( pointer to a)n array or an integer). You can take a look at the interface of printf for an idea of how that problem may be solved. It is solved there using a format string where those types are specified. The length of the array is solved by using a sentinel value (the null terminator character). Another approach is to pass the length as a separate argument.
More generally though: I recommend that you not use C style varargs at all in C++. It's just too easy to shoot yourself in the foot. Variadic templates are much safer and more powerful way to achieve similar things.
That said, I don't quite understand what you're attempting to do, so I cannot confirm whether it makes sense to use any form of variadics.

When passing char arrays as arguments, why isn't the null terminator included in the index?

When you pass char arrays as arguments and try to find the length of the array, it returns the length without the null operator?
For example, if I passed charArray[4] = "aaa" and found the length of this using strlen, the returned value would be 3. Why is this so?
More detailed example below:
#include <iostream>
using namespace std;
int main() {
void function(char[]);
char charArray[4] = "aaa";
function(charArray);
cin.get();
return 0;
}
void function (char *array)
{
size_t index = 0;
index = strlen(array);
std::cout << index; // prints value: 3
}
You are confusing char arrays with the behavior of string literals, c-style strings respectively.
strlen() operates on NUL terminated character arrays and doesn't count the terminating \0 character by definition:
Returns the length of the given null-terminated byte string, that is, the number of characters in a character array whose first element is pointed to by str up to and not including the first null character.
The behavior is undefined if str is not a pointer to a null-terminated byte string.
To get the size of an array use sizeof() like so:
char arr[4] = "abc";
cout << sizeof(arr) << endl;
You should note that the above sample will not give you correct results, as soon the array is decayed to a pointer that is passed to a function:
char arr[4] = "abc";
void func(char* arr)
{
cout << sizeof(arr) << endl; // Prints the size of the pointer variable itself
}
Such functions need to get the array size from an extra parameter:
void func(char* arr, size_t arrsize)
{
// ...
}
If you think of the null as more of an implementation detail, that might help.
If you know std::string at all, you want length() to return the actual length. Every other major language has a string of some sort, and they all have a function to get the length.
Also, you really want strlen(a+b) == strlen(a) + strlen(b), otherwise a lot of operations get a bit more complicated. You only want to count a null once. When you strcat.
strlen does not return the length with the null character because the null character determines where the C string ends in memory.
(ie it is not part of the string, it tells the runtime where the string ends).
See:
https://en.wikipedia.org/wiki/String_%28computer_science%29#Null-terminated
https://en.wikipedia.org/wiki/Null-terminated_string

Finding the length of a character array in c++ [duplicate]

This question already has answers here:
How do I use arrays in C++?
(5 answers)
Closed 8 years ago.
I have an character array of the form
char x[]='asdasdadsadasdas';
int p = sizeof(x)/sizeof(*x)
gives me correct result but when I pass this as an argument in another function like
void X(char* a)
int i = sizeof(a)/sizeof(*a)
and I call it
X(x)
p and i are not equal.How is it possible ?
When the char array gets passed to a function accepting a char*, the array is said to 'decay' to a pointer. This conversion is automatic, and the length information which was previously statically available to the compiler is lost.
Possible solutions are:
Pass the size of the array as an additional parameter.
Make the char-Array 0-terminated (i.e., a string literal) and use strlen. This is the common ways of operating on strings in C and C++. However, this introduces runtime cost which is not strictly necessary. However it provides some convenience (same API for statically and dynamically sized strings) and error resilience (the length is always correct).
Use templates to capture the length of the array. This is explained here..
void X(char* a)
int i = sizeof(a)/sizeof(*a)
Here, a is a pointer and *a is a char. So sizeof(a) won't return the size of the array, but the size of the pointer to the first element in the array.
In order to find the length of the string (which isn't the same as "the size of the array"), you have a few options.
One, don't use a char* at all, but a std::string (may create a temporary):
void X (const std::string& s)
{
size_t i = s.length();
}
Two, scan the string for the null-terminator (linear complexity):
void X (const char* p)
{
size_t i = strlen (p);
}
Three, use a template (needlessly complex code):
template <size_t N> void X (const char (&arr)[N])
{
size_t i = N;
}
Each of the above has it's own set of cons. But this is all best avoided if you take a broader look at your program and see where you can make improvements. Here's one that stands out to me:
char x[]='asdasdadsadasdas';
C-style arrays present their own problems and are best avoided altogether. Instead of using a C-style array, use a tool from the StdLib designed for just this problem:
std::string x = "asdasdadsadasdas";
sizeof(char *)
Gives you the size of a pointer. Eight bytes on my system.
char x[] = "fred";
sizeof(x);
Returns 5. The size of the string with the null termination.
void x(char * c) {
sizeof (*c);
}
Returns the size of a a char.
This is true no matter what the length or original type of the array is passed to void x(). Note that sizeof() is evaluated at compile time. At compile time the compiler cannot normally know what length of array it's been passed. For a run-time evaluation of string length, as said above, use strlen if you actually want the strings length in characters. (Or a template - but that's probably a more unusual solution).

Parsing a string to a pointer array of chars: char[0] contains the full string and [1] onward contains nothing

I'm trying to parse a simple string to an array of *char and for some reason when I use string.c_str() it puts the entire string into *char[0] and the rest of the array is left blank (I originally thought that chars could only hold one ASCII character but I guess that they act differently as pointers), could anyone have a scan through my function and tell me if there are any obvious mistakes?
static void SetGame()
{
// Variable Initiation
int myRandom = rand() % (numOfWords - 1);
lengthOfString = wordArray[myRandom].length();
// Reinitiate Pointer Arrays
stringArray = new string[lengthOfString];
isDiscoveredArray = new bool[lengthOfString];
// Parse string to the array of characters
*stringArray = wordArray[myRandom].c_str();
// Set each boolean array value to false
for (int i = 0; i < sizeof(isDiscoveredArray); i++)
{
isDiscoveredArray[i] = false;
}
}
Here are my decelerations of the pointers
// Global Variable and pointer Declerations
string *wordArray;
int numOfWords;
string *stringArray;
int lengthOfString;
bool *isDiscoveredArray;
Any ideas? Thanks.
You are mixing types here. First you build an array of strings and store it in a pointer, then you assign to the first element a const char* coming from c_str. The code you currently have would be if your were creating a string for every character in your selected word.
Make your "stringArray" a const char* to fit with the code you already have, but remove the memory allocation.
You've got an array of std::string and when you deference it (i.e. *stringArray) its the same as stringArray[0], so that is why it always going into the first element of your array.
Since you are setting your array have the same number of elements as the string your are copying has characters, you may just want to use a string rather than a string array to copy it into.
If it supposed to be char* (character array) then you will need to explicitly copy the source, which is the result of wordArray[myRandom].c_str(), into your character array rather than using simple assignment.

Beginner C++ Question

I have followed the code example here
toupper c++ example
And implemented it in my own code as follows
void CharString::MakeUpper()
{
char* str[strlen(m_pString)];
int i=0;
str[strlen(m_pString)]=m_pString;
char* c;
while (str[i])
{
c=str[i];
putchar (toupper(c));
i++;
}
}
But this gives me the following compiler error
CharString.cpp: In member function 'void CharString::MakeUpper()':
CharString.cpp:276: error: invalid conversion from 'char*' to 'int'
CharString.cpp:276: error: initializing argument 1of 'int toupper(int)'
CharString.cpp: In member function 'void CharString::MakeLower()':
This is line 276
putchar (toupper(c));
I understand that toupper is looking for int as a parameter and returns an int also, is that the problem? If so how does the example work?
Also,
char* str[strlen(m_pString)];
int i=0;
str[strlen(m_pString)]=m_pString;
is not valid C++ - arrays must be dimensioned using compile time constants - this is a C99 feature. And I really don't think the code would do what you want it to, even if it were legal, as you seem to be accessing one past the end of the array. It would be handy if you posted the complete class definition.
I don't think your code does what you want it to do and in fact if it compiled it would explode.
char* str[strlen(m_pString)]; // you've made an array of X C strings where
// X is the length of your original string.
int i=0;
str[strlen(m_pString)]=m_pString; // You've attempted to assign the C string in your array
// at location X to point at you m_pString. X is the
// same X as before and so is 1 past the end of the array
// This is a buffer overrun.
I think what you actually wanted to do was to copy the content of m_pString into str. You'd do that like so:
char * str = new char[strlen(m_pString)];
memcpy(str, m_pString); // I may have the operands reversed, see the docs.
The easier way to do this though is to stop using C strings and to use C++ strings:
std::string str = m_pString;
There are more issues, but this should get you steer you more toward the right direction.
You need to feed toupper() an int (or a char) instead of a char *, which is how you've declared c.
try:
char c;
Also,
char* str[strlen(m_pString)];
is an an array of pointers to characters, not just a single string.
This line:
str[strlen(m_pString)]=m_pString;
is an assignment to a bad pointer then, since there was no allocation.
I'm going to go with the assumption that m_pString is a C style string (char *). You're doing way more fiddling than you need to be doing.
void CharString::MakeUpper()
{
char* str = m_pString; // Since you're not modifying the string, there's no need to make a local copy, just get a pointer to the existing string.
while (*str) // You can use the string pointer as an iterator over the individual chars
{
putchar (toupper(*str)); // Dereference the pointer to get each char.
str++; // Move to the next char (you can merge this into the previous line if so desired, but there's no need.
}
}
In the example you cite, the reason it works is because of how the variables are declared.
int main ()
{
int i=0;
char str[]="Test String.\n"; // This is a compile time string literal, so it's ok to initialize the array with it. Also, it's an array of `char`s not `char*`s.
char c; // Note that this is also a `char`, not a `char *`
while (str[i])
{
c=str[i];
putchar (toupper(c));
i++;
}
return 0;
}
Because of the error-prone ways of using C strings, your best bet is std::string:
void CharString::MakeUpper()
{
string str(m_pString);
transform(str.begin(), str.end(), ostream_iterator<char>(cout), &toupper);
}
There is not a built-in conversion from char * to int, which is why the error occurs. Since you're trying to capitalize a character, you need to dereference the pointer.
putchar(toupper(*c));