#include <iostream>
using namespace std;
const int MAX = 4;
int main () {
const char *names[MAX] = { "Zara Ali", "Hina Ali", "Nuha Ali", "Sara Ali" };
for (int i = 0; i < MAX; i++) {
cout << "Value of names[" << i << "] = ";
cout << (names + i) << endl;
}
return 0;
}
what is (names + i) printing in the above code
what is char *names
names is an array of const char * pointers, which are being initialized to point at string literals in memory (which is irrelevant to the code being shown).
When an array is referred to by its name alone, it decays into a pointer to the first element. The loop is then using pointer arithmetic to increment that pointer to access each subsequent element. Thus, the expression names + i is effectively the same as &names[i], and so the loop is printing out the memory address of each element in the array, eg:
Value of names[0] = 0x7ffedc2f1850
Value of names[1] = 0x7ffedc2f1858
Value of names[2] = 0x7ffedc2f1860
Value of names[3] = 0x7ffedc2f1868
Online Demo
Had the code used *(names + i) instead, then it would be dereferencing those addresses, thus printing out each const char* pointer in the array. operator<< is overloaded to handle const char* as a null-terminated string, thus the contents of the string literals would be printed instead of their addresses, eg:
Value of names[0] = Zara Ali
Value of names[1] = Hina Ali
Value of names[2] = Nuha Ali
Value of names[3] = Sara Ali
Online Demo
Related
I have a very simple structure for adding size field to dynamic arrays:
template <typename T>
struct sized_array {
int size;
T* array;
};
I cannot use std::vector or std::array. The function to fill the array initializes the sized_array.array field and fills it with random integers:
void array_fill(sized_array<int> &array, int size = ARRAY_SIZE) {
array.array = new int[size];
array.size = size;
for (int i = 0; i < size; i++) {
array.array[i] = random_in_range(RANDOM_MIN, RANDOM_MAX);
}
}
The other functions, array_join and array_print print the contents of an array:
string array_join(sized_array<int> &array, string delimiter) {
string text = "";
for (int i = 0; i < array.size; i++) {
text += array.array[i];
if (i < array.size) text += delimiter;
}
return text;
}
void array_print(sized_array<int> &array) {
cout << "array(" << array.size << ") = [";
cout << array_join(array, ", ") << "]" << endl;
}
The array variable is declared like so, and the program runs this code:
sized_array<int> number_array;
int main() {
srand(time(NULL));
array_fill(number_array);
array_print(number_array);
system("pause");
return 0;
}
When debugging, the array shows this value when first initialized, then appears to take the first returned value of random_in_range and never change, staying at one element -- the first returned value.
When printed, the array appears to be filled with random ASCII characters, and the first element is never the one it was (even though the debugger displayed it had one element).
What is the cause of this and how to avoid this problem?
When printed, the array appears to be filled with random ASCII characters
This is because you have an error in your array_join function:
text += array.array[i];
This would append an int re-interpreted as char, not a decimal representation of the number.
Use std::to_string to fix the problem:
text += std::to_string(array.array[i]);
If you are restricted to a C++ version prior to C++11, use std::stringstream instead.
I have this code:
#include <iostream>
#include <string.h>
using namespace std;
void copyString(char *input, int offset, int length, bool invert, char *output, int output_offset)
{
char *cp = new char[length+1];
for (int i = 0; i < length + 1; i++)
{
cp[i] = input[offset + i];
}
if (invert)
{
for (int i = 0; i < length/2; i++)
{
swap(cp[i], cp[length - i - 1]);
}
}
int count = 0;
while (output[count])
count++;
int cutlength = count - output_offset;
char *temp = new char[count + 1];
for (int i = 0; i < count + 1; i++)
temp[i] = output[i];
for (int i = 0; i < cutlength; i++)
{
temp[output_offset + i] = cp[i];
}
output = temp;
}
void main()
{
char *st = "Hello world";
cout << "st= " << st << endl;
char *st2 = "My name is C++";
cout << "st2= " << st2 << endl;
copyString(st, 6, 5, true, st2, 11);
cout << "st2 output= " << st2 << endl;
system("Pause");
}
The idea is that the function will copy a length of an input string and replace a part of an output with that copied string.
All i want to do is make the st2 value change after copyString function, but i can't seem to change it through temp var. But if i try to change the st2 value in the function, i got the Access Violation Error. Any idea how to fix this?
st and st2 are pointers to a constant string, and as such you shouldn't try to change there contents (although you can make them point at an entirely different string).
To make st2 a character array (string) that is editable, you should declare st2 as follows
char st2[] = "My name is C++";
In your copyString function, the output pointer originally points at the same place as st2, and then at the end of the function make output point at a different string. However this wont change st2 or its contents in any way.
You need either need to make st2 a character array and edit this array in the copyString function, or have the copyString function create and return a new string that st2 can point at (although likely to end up with memory leaks if your not careful).
The following should do what you are after. It can could be improved a little by removing cp altogether and directly writing from the input buffer to output buffer.
void copyString(char *input, int offset, int length, bool invert, char *output, int output_offset)
{
char *cp = new char[length+1];
for (int i = 0; i < length + 1; i++)
{
cp[i] = input[offset + i];
}
if (invert)
{
for (int i = 0; i < length/2; i++)
{
swap(cp[i], cp[length - i - 1]);
}
}
int count = strlen(output);
int cutlength = count - output_offset;
for (int i = 0; i < cutlength; i++)
{
output[output_offset + i] = cp[i];
}
delete[] cp;
}
void main()
{
char st[] = "Hello world";
cout << "st= " << st << endl;
char st2[] = "My name is C++";
cout << "st2= " << st2 << endl;
copyString(st, 6, 5, true, st2, 11);
cout << "st2 output= " << st2 << endl;
system("Pause");
}
Your copyString function is generally similar to the C strcpy function (if not to take the inversion option into the account). It needs the output to be an already allocated buffer (a char array) of a sufficient size to write the string content into (say, you may allocate a buffer using new char[strlen(str) + 1] ) . However, you are trying to write into the memory where the string constants "Hello world" and "My name is C++" are located. This is obviously a memory access violation (otherwise you would modify those constants).
No need to say that this way of dealing with strings is extremely error prone and far not C++ish.
1) You count the output length (undefined behavior!), not the input one.
2) output pointer goes to nowhere - do you want to use a reference function argument for it?
Memory access violation is due to your are trying to modify a string, which size can't accommodate extra length (i.e. st2 in your case)
Note: Temp method worked without error as your updated the base address of st2 <-- temp.
Also boundary checking against offset & input params lengths are also recommended.
In general use of strcpy_s is preferred over strcpy.
I am writing a C++ function that is supposed to duplicate an array of chars by copying each element character-by-character into a new array. Ideally, if I make the statements
char* a = "test";
char* b = copyString(a);
then both a and b should contain the string "test." However, when I print the copied array b, I get "test" plus a series of nonsense characters that seem to be the pointer. I don't want those, but I can't figure out where I'm going wrong.
My current function is as follows:
char* copyString(char* s)
{
//Find the length of the array.
int n = stringLength(s);
//The stringLength function simply calculates the length of
//the char* array parameter.
//For each character that is not '\0', copy it into a new array.
char* duplicate = new char[n];
for (int j = 0; j < n; j++)
{
duplicate[j] = s[j];
//Optional print statement for debugging.
cout << duplicate[j] << endl;
}
//Return the new array.
return duplicate;
}
For the purposes of understanding certain aspects of C++, I cannot use string libraries, which is where other answers I have found have fallen short in this case. Any help with this problem is greatly appreciated.
EDIT: I though my stringLength function was fine - perhaps I was wrong.
int stringLength(char* s)
{
int n;
//Loop through each character in the array until the '\0' symbol is found. Calculate the length of the array.
for (int i = 0; s[i] != '\0'; i++)
{
n = i + 1;
}
//Optional print statement for debugging.
// cout << "The length of string " << s << " is " << n << " characters." << endl;
return n;
}
You need to copy the 0 too. That's what a C-style string is, a null-terminated character array.
Really, all you need to do is add one to the length:
int n = stringLength(s) + 1; // include the '\0'
And then everything else will account for itself - you'll allocate an array of sufficient size, and copy the '\0' in your loop too.
Ok, I know that this is invalid
char char_A = 'A';
const char * myPtr = &char_A;
*myPtr = 'J'; // error - can't change value of *myP
[Because we declared a pointer to a constant character]
Why is this valid?
const char *linuxDistro[6]={ "Debian", "Ubuntu", "OpenSuse", "Fedora", "Linux Mint", "Mandriva"};
for ( int i=0; i < 6; i++)
cout << *(linuxDistro+i)<< endl;
*linuxDistro="WhyCanIchangeThis";// should result in an error but doesnt ?
for ( int i=0; i < 6; i++)
cout << *(linuxDistro+i)<< endl;
Thanks for looking!
You write
*linuxDistro = "WhyCanIchangeThis";
which is perfectly valid, because the declaration of linuxDistro was
const char *linuxDistro[6];
i. e. it's an array of 6 pointers to const char. That is, you can change the pointers themselves, just not the characters pointed to by those pointers. I. e., you can not compile
*linuxDistro[0] = 'B';
to obtain the string "Bebian", becuse the strings contain constant characters...
What you probably want is an array of constant pointers to constant characters:
const char *const linuxDistro[6];
*linuxDistro is still a pointer, it is linuxDistro[0], *linuxDistro="WhyCanIchangeThis" it just change the pointer to point to a new address, not to modify the content in the old address, so it is OK.
If you write **linuxDistro='a', it should error.
because the pointer is a variable that stores a memory address, if a pointer is const the pointer keeps storing the same memory address, so the value of the pointer itself can't change, but you are saying nothing about the value pointed by the pointer, according to what you have, chaging the pointed value it's an allowed operation.
because char is not char[], so when you access to * of char[] you access the first element of it (Debian).
when you shift pointer (e.g. +1 it) you access next element of array
here is good example for better understanding
#include <iostream>
using namespace std;
int main ()
{
int numbers[5];
int * p;
p = numbers; *p = 10;
p++; *p = 20;
p = &numbers[2]; *p = 30;
p = numbers + 3; *p = 40;
p = numbers; *(p+4) = 50;
for (int n=0; n<5; n++)
cout << numbers[n] << ", ";
return 0;
}
this will output:
10, 20, 30, 40, 50,
I tried making this small program that takes input and checks for vowels. If there are vowels then it appends them to a string and returns the size of the string.
My only problem is I can't get it to work using strings. What is the major difference over using character arrays? I can get the program to work using something like:
char entered[128];
//and then
char exceptions[11] = "aeiouAEIOU";
**Quick question about the above array. When I assign the buffer to 'exceptions' it has to be 11 or the compiler will error. Must I manually account for the NULL termination portion?
If I do something like:
if(cPtrI[i] == 'a'){
I get an error stating unknown operator '==' ??
I thought '==' was a check operator, and '=' was an assignment operator?
no match for 'operator==' in '*((+(((unsigned int)i) * 4u)) + cPtrI) == 'a''|
AND, if I do something like: (which I thought was correct, at first)
if(*cPtrI[i] == *cPtrJ[j]){
I get the same error as above, but referencing unknown operator *:
no match for 'operator*' in '**((+(((unsigned int)i) * 4u)) + cPtrI)'|
no match for 'operator*' in '**((+(((unsigned int)j) * 4u)) + cPtrJ)'|
I thought the * operator said, in effect, 'what is at' the address of where the pointer is pointing.
So, something like the above would read:
If(What is at index I of string 'a' EQUALS What is at index J of string 'exceptions'){
then ..
Any help with this one? I learned C a bit before C++, so perhaps this is where my confusing is coming from. It was my understanding the the above code would compare addresses of characters/variables they are pointing to. * indicates 'what is at' while just placing the pointer name would indicate the value the pointer is holding(which is an address of the variable being pointed to). Using &ptrName would be the address of the pointer itself, correct? Where have I gone wrong here?
#include <iostream>
#include <string>
int vowelCheck(std::string a);
int main()
{using namespace std;
string eString;
cout << "Enter a string: ";
cin >> eString;
cout << "There were " << vowelCheck(eString) << " vowels in that string.";
return 0;
}
int vowelCheck(std::string a)
{using namespace std;
string exceptions = "aeiouAEIOU";
string vowels;
string *cPtrI = &a;
string *cPtrJ = &exceptions;
for(int i = 0; i < a.size(); i++){
cout << i <<"i\n";
for(int j = 0; j < 10; j++){
cout << j << "j\n";
// cout << cPtrJ[j];
if(cPtrI[i] == cPtrJ[j]){ //if index of A equal index of J then
cout << "Added: " << cPtrJ[j];
vowels.append(cPtrJ[j]); // append that vowel to the string 'vowels'
break;
}
}
}
return vowels.size();
}
Using my debug tools listed above, the program will only increment through j = 8 then stops. Also, if I even enter an initial string something like AEIOU, it will string go through j = 8. So, it is not seeing the equivalent characters.
What am I doing wrong using strings?
Forget about pointers.
string *cPtrI = &a;
string *cPtrJ = &exceptions;
// ...
if(cPtrI[i] == cPtrJ[j]){ //if index of A equal index of J then
cPtrI[i] is the same as *(cPtrI + i), which would be indexing into an array of string.
That's why cPtrI[i] == 'a' doesn't compile. cPtrI[i] has type std::string& (remember, it's indexing into a non-existing array of std::string), and 'a' is a char. You can't compare the two.
std::string has an indexing operator of its own. Just don't use pointless pointers and it just works.
if(a[i] == exceptions[j]){
You appear to be counting the number of vowels in a string. Instead of writing out the for loops manually and building up a string, let's use count_if to do that. The plan is to create a function object that can detect if a character is a vowel and then use count_if to count the number of vowel characters in the string:
struct VowelFinder
{
bool operator()(char c)
{
std::string vowels = "aeiouAEIOU";
return vowels.find(c) != std::string::npos;
}
};
int vowelCheck(const std::string& a)
{
return std::count_if(a.begin(), a.end(), VowelFinder());
}
I've answered your C-related questions in comments.
As for your usage of std::string, you're actually trying to use std::string* for some reason. Don't do that. Just use the std::string; operator [] is overloaded for it to work as-is. At the moment you're treating cPtrI as a element of an array of strings.