The following program in C++ prints more output than I expected. Can anyone explain why this has happened? The program attempts to use pointers to loop through the integer array, printing each value along the way.
#include <cstdio>
using namespace std;
int main(int argc, char **argv) {
puts("hi");
int ia[5] = {1,2,3,4,5};
for (int *p = ia; *p; ++p) {
printf("Char is: %d\n", *p);
}
return 0;
}
/*
hi
Char is: 1
Char is: 2
Char is: 3
Char is: 4
Char is: 5
Char is: 32767
Char is: -811990796
Char is: -133728064
Char is: 1606416320
Char is: 32767
Char is: -1052593579
Char is: 32767
Program ended with exit code: 0
*/
You will need to have a 0/NULL value to stop at, currently you do not.
Your loop condition will allow iteration until you get a value that evaluates to false (i.e 0) and your array does not contain that, so your iteration will continue on past the bounds of the array and will at some point exit when it access some memory its not supposed to.
There are several ways to fix it. You can add a 0 to the end of the array.
#include <cstdio>
using namespace std;
int main(int argc, char **argv) {
puts("hi");
int ia[] = {1,2,3,4,5, 0};
for (int *p = ia; *p; ++p) {
printf("Char is: %d\n", *p);
}
return 0;
}
Issue with this is that you now cant use 0 in your array, or it will terminate early.
A better way would be to pre calculate the address at which to stop, given the array length. This address is one off the end of the array.
#include <cstdio>
using namespace std;
int main(int argc, char **argv) {
puts("hi");
int ia[] = {1,2,3,4,5};
int* end = ia + 5;
for (int *p = ia; p != end; ++p) {
printf("Char is: %d\n", *p);
}
return 0;
}
Now we are getting towards the method used by standard library iterators. Now templates can deduce the size of the array.
i.e.
#include <iterator>
...
for (auto it = std::begin(ia); it != std::end(ia); ++it) {
printf("Char is: %d\n", *it);
}
...
and finally, range based for also supports arrays.
for (auto i: ia)
{
/* do something */
}
Can anyone explain why this has happened?
You are accessing the array out of bounds. Your program has undefined behavior.
The line
int ia[5] = {1,2,3,4,5};
creates an array with exactly 5 elements. Accessing *p after you have accessed the last element of the array is not good.
You can use:
for (int *p = ia; p != std::end(ia); ++p) {
to make sure that you don't access the array out of bounds.
You will need to add:
#include <iterator>
to use std::end.
Alternatively use sizeof() operator to determine the number of elements:
for (int *p = ia; p < ia + sizeof(ia)/sizeof(*ia); ++p) {
printf("Char is: %d\n", *p);
}
in fact the condition:
for( ; *p; )//...
will check whether the value in the address is equal to 0 or not so it stops only if the value is zero and of course this is not what you wanted; you wanted to increment the address until the last element but your code checks the value inside the address not the address itself morever the address after the lat element is not NULL.
to solve your problem you can count how many elements in the array and then inside the loop increment the pointer accordingly:
#include <cstdio>
using namespace std;
int main(int argc, char **argv) {
puts("hi");
int ia[5] = {1,2,3,4,5};
int* end = &ia[0] + 4;
for (int *p = ia; p <= end; ++p) {
printf("Char is: %d\n", *p);
}
return 0;
}
Related
I am trying to reverse a char which has been provided in input from an user. I am having issues with the reverse function, particularly the loop. I can't get it to work- can I get advice?
#include <iostream>
using namespace std;
#include <cstring>
char* reverse(char* input) {
int len = strlen(input);
char temp[len];
for(int i=len; i>len; --i) {
temp[i]+=input[i];
}
return temp;
}
int main()
{
char input[100];
while(cin>>input) {
cout << reverse(input);
}
return 0;
}
Your Program has few issues
You're trying to return local variable address i.e. temp array address. The Function will return the address to main function. Since memory might get cleaned so it will print garbage value present at the address.
As Rohan Bari mentioned variable length array might cause undefined behavior. There for you can create a constant length array i.e.
char temp[100];
or you can dynamically allocate array on heap. Memory allocated on heap do not get cleared after termination of block but we have to manually delete it.
char* temp = new char[len];
As array start from 0 it goes till len-1 so loop condition should start from len-1 and has to go till 0 to reverse.
+ operator do not work's with array or char even if you are trying to add just char it preforms normal integer addition of their ASCII value.
Here is improved version of your code
#include<iostream>
using namespace std;
#include <cstring>
char* reverse(char* input) {
int len = strlen(input);
char* temp = new char [len]; // or you can use char temp[100];
int j = 0; //temp variable to enter values from 0th index if we use same as loop it just enter in the same order as original char array.
for(int i=len-1; i>=0; --i) {
temp[j++] = input[i];
}
temp[j] = '\0';
return temp;
}
You have got several errors in the program.
The variable-length arrays are used here:
char temp[len];
This should not be applied in C++ since this invokes undefined-behavior. Note that this is a valid statement in the C99 standard.
There is a better alternative to this. That is to take the std::string built-in type in use.
In the following line:
temp[i] += input[i];
You are not sequentially adding one character after another, but the values of them in a single integer. This could be not a problem if temp was of the type std::string.
The reverse function should look like this:
const char *reverse(char *input) {
int len = strlen(input);
std::string temp;
while (len--)
temp += input[len];
return temp.c_str();
}
len should actually be (len-1) and i should be >= 0 not len, so from (len-1) to 0 your loop should run.
for(int i = len-1; i >= 0; i--){}
You have to allocate the new array with the new keyword if you don't want to use a string. The following code does what you need:
char* reverse(char* input)
{
int len = strlen(input);
char* temp = new char[len + 1];
for (int i = len; i >= 0; --i)
{
temp[len-i-1] = input[i];
}
temp[len] = '\0';
return temp;
}
You could use a std::stack to reverse your input:
std::stack<char> s;
char c;
while (std::cin >> c)
{
s.push(c);
}
while (!s.empty())
{
std::cout << s.top();
s.pop();
}
It's 2021. Use the STL. If your instructor isn't aware of it or doesn't allow you to use it, your instructor is not keeping up-to-date and you should fire your instructor.
#include <algorithm>
#include <iostream>
#include <string>
int main() {
std::string input{};
while(std::getline(std::cin, input)) {
std::reverse(std::begin(input), std::end(input));
std::cout << input << '\n';
}
return 0;
}
There's quite many things wrong with the code as many people have already mentioned! Since you want to implement this without using STL it can be done this way,
#include <iostream>
using namespace std;
#include <cstring>
void reverse(char* input,int len) { //added len as argument
char temp[len];
for(int i=len-1; i>=0; --i) {
temp[len-i-1]=input[i];
cout<<temp[len-i-1]; //printing while reversing
}
cout<<endl;
}
int main()
{
char input[100];
int len=0;
//using do while since it has to run atleast once
do{
cin.getline(input,100);
len=strlen(input);
input[len]='\0';
if(len!=0)
reverse(input,len);
}while(len!=0) ;
return 0;
}
So basically I'm trying to write a method that returns two times the length of an array, but I cannot figure out how to make the length into an int so that it can be used. I have been trying to figure out the correct method to use since sizeof() returns the number of bytes, not the length of the array. What method should I be using and how can I fix this? Here is my code:
int main(int argc, const char * argv[]) {
int arr[] = {1,2,3,4,5};
cout << getLen(arr);
return 0;
}
int getLen( int *arr ){
int len = sizeof(arr);
return 2 * len;
}
I think this could be an XY problem. Ultimately if you want this kind of behaviour in C++ you should use an std::vector object. For example:
#include <iostream>
#include <vector> // Remember to include this
int getLen(std::vector<int> &vec) // Pass vec by reference rather than as a pointer
{
return static_cast<int>(vec.size()) * 2; // Use .size() to get the number of elements in vec
// ^^^ .size() returns a value of type size_t which is converted to an int using static_cast<int>
}
int main()
{
std::vector<int> vec = {1,2,3,4,5};
std::cout << getLen(vec);
return 0;
}
#include <iostream>
template<typename T,std::size_t n>
std::size_t get_new_len(T (&a)[n]) {
return n*2;
}
int main() {
int a[10] = {0};
std::cout << get_new_len(a) << "\n";
}
you can do it in this way, using template argument deduction.
output is 20
The result of sizeof(arr) is not the same in the main as in the function, i don't understand why , but it works like this :
int getLen(int *arr, int arrSize)
{
int len = arrSize / sizeof(int);
return len;
}
int main(int argc, const char * argv[])
{
int arr[] = { 1, 2, 3, 4, 5 };
cout << getLen(arr,sizeof(arr));
return 0;
}
For example, I have an array:
int Arr[10]={1,2,3,4,5,6,7,8,9,10};
How to change its order of elements using a pointer to receive the following array:
Arr={10,9,8,7,6,5,4,3,2,1}
to change the order odd and even using a pointer I've found this:
But I need only to reverse an array (without replacing odd and even)
#include <iostream>
using namespace std;
int main (const int& Argc, const char* Argv[]){
const int Nelem=10;
int Arr[]={1,2,3,4,5,6,7,8,9,10};
int *begAr=&Arr[0];
int *endAr=&Arr[Nelem];
int *itrAr=begAr;
int *tmpValAr=new int(0);
cout<<"Before\t1 2 3 4 5 6 7 8 9 10"<<endl;
while(itrAr<endAr){
*tmpValAr=*itrAr;
*itrAr=*(itrAr+1);
*(itrAr+1)=*tmpValAr;
itrAr+=2;
}
cout<<"After\t";
for(int i=0; i<Nelem; ++i)cout<<Arr[i]<<" ";
cout<<endl;
system("pause");
return 0;
}
Ok, a C-style approach using pointers to reverse an array? That shouldn't be too hard to figure out. Here's one approach:
int main ( void )
{
int i,//temp var
arr[10]= {1,2,3,4,5,6,7,8,9,10};//the array
int *start = &arr[0],//pointer to the start of the array
*end = &arr[9];//pointer to the last elem in array
//print out current arr values
for (i=0;i<10;++i)
printf("arr[%d] = %d\n", i, arr[i]);
do
{//simple loop
i = *start;//assign whatever start points to to i
*start = *end;//assign value of *end to *start
*end = i;//assign initial value of *start (stored in i) to *end
} while ( ++start < --end);//make sure start is < end, increment start and decrement end
//check output:
for (i=0;i<10;++i)
printf("arr[%d] = %d\n", i, arr[i]);
return 0;
}
As you can see here, this reverses the array just fine.
Use reverse found in <algorithm>:
std::reverse(Arr, Arr+10);
It will reverse a set of data like you are requesting.
This is the approximate implementation of the function, which you could adapt if necessary to your needs if you would like to write the loop yourself:
template <class BidirectionalIterator>
void reverse (BidirectionalIterator first, BidirectionalIterator last)
{
while ((first!=last)&&(first!=--last)) {
std::iter_swap (first,last);
++first;
}
}
If you are in C or would like a less general solution, do something like this:
int i = 0; j = 9;
for(;i<j;++i;--j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = arr[i];
}
Take two pointers begAr pointing at arr[0] and endAr pointing at arr[9]. Traverse the array from both sides and swap *begAr with *endAr until begAr > endAr.
int tempValAr;
while(endAr >= begAr )
{
tempValAr = *begAr;
*begAr++ = *endAr;
*endAr-- = tempValAr;
}
See the test program.
Here is my code:
#include <cstdlib>
#include <stdio.h>
#define NUM_READINGS 3
int* readingsTotal;
int* readingsAverage;
int readingsIndex;
using namespace std;
void avgOf(int* toFindAvgOf, int size) {
int i;
for (i = 0; i < size; i++) {
// Add reading to total for each component.
readingsTotal[i] += toFindAvgOf[i];
// Once method has been iterated through n (NUM_READINGS) times:
if (readingsIndex == NUM_READINGS - 1) {
// Set the arithmetic mean.
readingsAverage[i] = readingsTotal[i] / NUM_READINGS;
// Reset the total.
readingsTotal[i] = 0;
}
}
readingsIndex++;
}
int iterate(int findAvgOf) {
int toFindAvgOf[] = {findAvgOf, 20, 30};
avgOf(toFindAvgOf, sizeof (toFindAvgOf));
return readingsAverage[0];
}
int main(int argc, char** argv) {
readingsTotal = (int []){0, 0, 0};
readingsAverage = (int []){0, 0, 0};
int i;
for (i = 0; i < 3; i++) {
int smthd = iterate(12 + i * 2);
printf("%d\n", smthd);
}
return 0;
}
When I run this in netbeans c/c++, it builds with now errors but when it executes it fails and prints:
RUN FAILED (exit value 1, total time: 86ms)
When I go into debug mode it also fails immediately and gives the SIGSEGV error. From reading online I'm guessing there is some issue with the way I am dereferencing a pointer. But I have no clue where exactly it is failing at. I am pretty new to c++ so any help would be great!
In C, the sizeof function returns the size of the object in bytes.
So when you say:
sizeof (toFindAvgOf)
That will return 12 (assuming an int on your system is 4-bytes) thus causing an index out of bounds condition in the avgOf function.
To get the length of the array:
sizeof(toFindAvgOf) / sizeof(int)
I'm trying to create a function that would dynamically allocate an array, sets the values of the elements, and returns the size of the array. The array variable is a pointer that is declared outside the function and passed as a parameter. Here is the code:
#include <cstdlib>
#include <iostream>
using namespace std;
int doArray(int *arr) {
int sz = 10;
arr = (int*) malloc(sizeof(int) * sz);
for (int i=0; i<sz; i++) {
arr[i] = i * 5;
}
return sz;
}
int main(int argc, char *argv[]) {
int *arr = NULL;
int size = doArray(arr);
for (int i=0; i<size; i++) {
cout << arr[i] << endl;
}
return 0;
}
For some reason, the program terminates on the first iteration of the for loop in main()! Am I doing something wrong?
If you want to allocate memory that way you have to use:
int doArray(int*& arr)
else the pointer will only be changed inside the function scope.
You're passing in the array pointer by value; this means that when your doArray function returns, the value in arr in main is still NULL - the assignment inside doArray doesn't change it.
If you want to change the value of arr (which is an int *), you need to pass in either a pointer or a reference to it; hence, your function signature will contain either (int *&arr) or (int **arr). If you pass it in as a ** you'll also have to change the syntax inside the function from using arr to *arr (pointer-dereferencing), and you'll call it like so: doArray(&arr).
Also, in C++ you should really be using new int[sz] instead of malloc.
You need to add an extra level of indirection to doArray. As written it allocates the array properly but it doesn't communicate the pointer value back to the caller correctly. The pointer from malloc is lost once you return.
If you wrote a function to take a float and change the value, passing the changed value back to the caller, it would need to take a pointer: foo(float *f). Similarly, here you want to pass back an int* value to the caller so your function must be declared as doArray(int **arr) with a second asterisk.
int doArray(int **arr) {
int sz = 10;
*arr = (int*) malloc(sizeof(int) * sz);
for (int i=0; i<sz; i++) {
(*arr)[i] = i * 5;
}
return sz;
}
int main(int argc, char *argv[]) {
int *arr = NULL;
int size = doArray(&arr);
for (int i=0; i<size; i++) {
cout << arr[i] << endl;
}
return 0;
}
Notice how it now dereferences *arr inside of doArray, and how the call is now written as doArray(&arr).
The arr variable in your function is a local copy of the arr pointer in the main function, and the original is not updated. You need to pass a pointer-to-pointer or pointer reference (the former will also work in plain c, the later only in c++).
int doArray(int **arr)
or
int doArray(int*& arr)
Change signature to (specific for c++):
int doArray(int *&arr)
so pointer would be changed at exit from doArray.
You need a pointer to a pointer in your doArray() parameter. If you've never done any programming with pointers before, this can be confusing. I find that it can be easier to see the right types if you annotate your code abundantly with typedefs.
You have the right idea that (int*) can be used to represent an array. But if you want to change the value of your variable arr in main(), you need a pointer to that, and so you will end up with (untested code) something like the following
typedef int *IntArray;
int doArray(IntArray *arr) {
int sz = 10;
*arr = (IntArray) malloc(sizeof(int) * sz);
IntArray theArray = *arr;
for (int i=0; i<sz; i++) {
theArray[i] = i * 5;
}
return sz;
}
when calling doArray, you will need to pass the address of your variable (so doArray knows where to write to):
int main(int argc, char *argv[]) {
int *arr = NULL;
int size = doArray(&arr);
for (int i=0; i<size; i++) {
cout << arr[i] << endl;
}
return 0;
}
This should work.
As others have pointed out, you're passing your array (the int *) by value, so when you say arr=... you're not actually changing the array you passed in.
You're also got a memory leak, as you've written it. It's not a big deal when you only call doArray once in the body of your program, but if it gets called repeatedly and the array is never freed (or deleted, if you made it with new) then it can cause problems. Typically the best way to deal with this is by using the STL. You'd then write
#include <vector>
#include <iostream>
int doArray(std::vector<int> &arr) {
int sz = 10;
arr.resize(sz);
for (int i=0; i<sz; i++) {
arr[i] = i * 5;
}
return sz;
}
int main(int argc, char *argv[]) {
std::vector<int> arr;
int size = doArray(arr);
for (int i=0; i<size; i++) {
std::cout << arr[i] << std::endl;
}
return 0;
}
However, with the STL there are more idomatic ways than returning the size, since you can just ask for arr.size(), and if you get really fancy, can use functions like for_each or the ostream_iterator to print all your elements.