Take input in arrays of pointers - c++

Can someone please let me know why one can't take an input in arrays of pointer to strings using input stream as in the following code:
char *names[5];
for(int i=0; i<5; i++)
{
cout<<"enter name "<<i+1;
cin>>names[i];
}

The variable "names" is an undefined array of char pointers. That's your first problem. The pointers are undefined and have no memory allocated for them.
In your original code example there are five char pointers with undefined values. This is why the program would crash, because it's trying to access memory of the invalid address in the pointers.
Another problem is that there is no memory allocated to hold the array of chars coming in from stdin.
You could do something like this to get your original example working without crash:
#include <iostream>
#include <string.h>
using namespace std;
int main(int argc, char** argv)
{
char names[5][128];
memset(names, 0, sizeof(names));
for (int i = 0 ; i < 5 ; i++ )
{
cout << "enter name " << i+1 << ": ";
cin >> names[i];
}
for (int i = 0 ; i < 5 ; i++ )
{
cout << names[i] << "\n";
}
}
This allocates an array of 5 128 character strings. It also clears the arrays with the memset() as well.
Since this is C++ it would seem to make more sense to do it C++ style.
#include <iostream>
#include <string>
#include <vector>
using namespace std;
const int NUM_NAMES = 5;
int main(int argc, char** argv)
{
vector<string> names;
names.resize(NUM_NAMES);
for (int i = 0 ; i < NUM_NAMES ; i++ )
{
cout << "enter name " << i+1 << ": ";
cin >> names[i];
}
for (int i = 0 ; i < NUM_NAMES ; i++ )
{
cout << names[i] << "\n";
}
}

Disclaimer:
using char* for reading from std::cin is generally a bad idea and I suggest you learn how to use std::string in future.
Also this question would have been better suited for codereview.SE but I'll ignore that for now.
Here is an example of doing what you want to do, but I strongly insist you avoid doing it in any real code.
char * names[5];
// Allocate names
for (int i = 0; i < 5; i++)
{
// Use 256 characters as a buffer
// any names longer than that might cause errors
names[i] = new char[256];
}
// Do IO
for (int i = 0; i<5; i++)
{
// Append std::endl
std::cout << "enter name " << i + 1 << std::endl;
// This isn't very robust since the user can give anything as a name,
// and they can't use spaces because of how cin works in this example.
std::cin >> names[i];
}
// Use names
for (int i = 0; i < 5; i++)
{
// Printing names is just an example
// you could write the names to somewhere more important
// you could copy them to a smaller location to use less memory
std::cout << names[i] << std::endl;
}
// Dispose of names when done
for (int i = 0; i < 5; i++)
{
// Check pointer isn't null
if (names[i] != nullptr)
{
// Never forget to delete
delete names[i];
}
}

Related

Why is my program to read a vector of strings into an array of character pointers not displaying any output?

I'm on exercise 4.34 of the book C++ Primer, 4th edition, which states "Write a program to read strings into a vector. Now, copy that vector into an array of character pointers. For each element in the vector, allocate a new character array and copy the data from the vector element into that character array. Then insert a pointer to the character array into the array of character pointers." I'm also trying to print the vector and character pointer array, and delete the character pointer array afterwards.
Here's what I've come up with so far:
#include <iostream>
#include <string>
#include <vector>
using std::cin;
using std::cout;
using std::endl;
using std::string;
using std::vector;
int main()
{
cout << "Enter some strings:" << endl;
vector<string> svec;
string input;
while (cin >> input) {
svec.push_back(input);
}
size_t sarr_sz = svec.size();
char **sarr = new char*[sarr_sz];
size_t carr_sz, carr_num;
char *carr = NULL;
for (vector<string>::size_type i = 0; i < svec.size(); ++i) {
carr_num = i;
carr_sz = svec[i].size();
carr = new char[carr_sz + 1];
size_t cval;
for (string::size_type j = 0; j < svec[i].size(); ++j) {
cval = j;
carr[cval] = svec[i][j];
}
cval = svec[i].size();
carr[cval] = '\0';
sarr[carr_num] = carr;
}
cout << "Vector contents:" << endl;
for (vector<string>::size_type i = 0; i < svec.size(); ++i) {
cout << svec[i] << " ";
}
cout << endl;
cout << "Character pointer array contents:" << endl;
for (size_t i = 0; i < sarr_sz; ++i) {
cout << sarr[i] << " ";
}
cout << endl;
for (size_t i = 0; i < sarr_sz; ++i) {
delete [] sarr[i];
}
delete [] sarr;
return 0;
}
When I compile and run this program, it freezes at the point after entering the string input and displays no output. When I exit the program manually using Ctrl-C, it displays either Vector Output: <first string inputted> or just Vector Output:. I've gone over the program multiple times and can't figure out where I've made an error.
Please keep in mind that I'm a beginner, and I'm just following the conventions of the book. As such, my program is probably neither efficient nor follows correct style. Any help would be greatly appreciated. Thank you.

I'm having trouble in C++ geting input from a user in a function, adding to an array, and printing that array

I'm learning c++ and I'm trying to ask the user to input 4 numbers in a function, and then simply print the array.
int getFourNums();
int main(int argc, char** argv){
int getNums;
getNums = getFourNums();
cout << "The array is: " getNums << endl;
}
int getFourNums(){
int i;
int myArray[4];
cout << "Enter 4 nums: ";
for(i = 0; i < 4; i++){
cin >> myArray[i];
}
return myArray[i];
As of now, it's letting me get the four numbers, but the result that's printing is "The array is: 0." I'm not quite sure why the array is seemingly not populating.
Your fundamental problem is that int getFourNums() can only return a single integer, not an array of them. The next problem is that functions cannot return raw arrays for historical reasons. Your choices are to return a std::array, a struct containing the array, pass the array by reference into the function, or return a std::vector. My preference for this application is a std::vector - it is flexible, and although not quite as efficient as std::array, you should probably default to std::vector unless you have a good reason otherwise. Your getNums code would then look like:
std::vector<int> getFourNums() {
std::vector<int> result;
cout << "Enter 4 nums: ";
for(int i = 0; i < 4; i++){
int v;
cin >> v;
result.push_back(v);
}
return result;
}
To print the vector, see this question. My personal preference would be a range-based for loop over the vector; your tastes may vary.
One issue in your code is that a loop like
for(i = 0; i < 4; i++){
cin >> myArray[i];
}
will end up with i==4. Hence, return myArray[i] will exceed array bounds and/or access an uninitialised value then and yield undefined behaviour.
The main issue, however, is that in C++ you'll follow a very different approach and use collection types like std::vector instead of plain arrays. See the following code illustrating this. Hope it helps.
#include <vector>
#include <iostream>
std::vector<int> getFourNums(){
int val;
std::vector<int> result;
cout << "Enter 4 nums: ";
for(int i = 0; i < 4; i++){
cin >> val;
result.push_back(val);
}
return result;
}
int main(int argc, char** argv){
std::vector<int> fourNums = getFourNums();
for (auto i : fourNums) {
cout << i << endl;
}
}
int getFourNums() will only let you return one int, not the whole array and return myArray[i]; is out of bounds since i == 4. You can only use the range [0,3] as indices for your array. Here's a reworked version with comments in the code.
#include <iostream>
#include <vector>
// don't do "using namespace std;" since it includes
// a lot of stuff you don't need.
// Here's a function that will return a vector of int's
// It'll behave much like a C style array
// but can have variable length and you can use
// a lot of standard functions on it.
std::vector<int> getNums(size_t count) {
// The "array" we'll return with "count" number of
// default constructed int:s (they will all be 0):
std::vector<int> myArray(count);
std::cout << "Enter " << count << " nums: ";
// A range based for loop that will go through
// all int:s in "myArray". "num" will be
// a reference to each int in the vector which
// means that if you change the value of "num",
// you'll actually change the value in the vector.
for(int& num : myArray) {
// read values into the int currently
// referenced by num
std::cin >> num;
}
// return the vector by value
return myArray;
}
// Put main() last so you don't have to forward declare the functions
// it uses
int main() {
// call getNums with the value 4 to read 4 int:s
std::vector<int> Nums = getNums(4);
std::cout << "The array is:";
// print each int in the vector. There's no need to use
// a reference to the int:s here since we won't be changing
// the value in the vector and copying an int is cheap.
for(int num : Nums) {
std::cout << " " << num;
}
// std::endl is rarely good when you only want to output a newline.
// It'll flush the buffer with is costly.
// Make a habit of using "\n" in most cases.
std::cout << "\n";
}
I see that you want to return entire array but just look at your return type:
int getFourNums()
You're returning an integer right? In this situation the returned integer is always myArray[4]. Be aware that it's an integer value, you're returning something that doesn't belong to you actually!
So what to do? I suggest you to pass your array to function like this:
void getFourNums(int myArray[]){
int i;
cout << "Enter 4 nums: ";
for(i = 0; i < SIZE; i++){
cin >> myArray[i];
}
}
Now you filled your array. How to print your array then? We can't simply give our array name and tell cout to print it like you did (you couldn't actually!). Nothing magical here. We're going to print your array's element one by one:
void printFourNumbers(int array[])
{
for(int i = 0 ; i < SIZE ; ++i)
{
cout << array[i] << endl;
}
}
Finally whole code looks like this:
#include <iostream>
using namespace std;
const int SIZE = 4;
void getFourNums(int myArray[]);
void printFourNumbers(int array[]);
int main(int argc, char** argv){
int myArray[SIZE];
getFourNums(myArray);
printFourNumbers(myArray);
}
void getFourNums(int myArray[]){
int i;
cout << "Enter 4 nums: ";
for(i = 0; i < SIZE; i++){
cin >> myArray[i];
}
}
void printFourNumbers(int array[])
{
for(int i = 0 ; i < SIZE ; ++i)
{
cout << array[i] << endl;
}
}

I want to declare a pointer array to character without using string

Here is the code::
#include <iostream>
using namespace std;
const int MAX = 4;
int main ()
{
char key[20];
char *names[MAX];
for (int i=0; i<MAX; i++)
{
cout << " entr keys\n";
cin >> key;
names[i]=key;
cout<< names[i];
}
for(int i=0; i<MAX;i++)
{
cout << names[i];
}
return 0;
}
When I enter the keys and print them in the 1st for loop they show the right value, but when I print names[i] in the 2nd for loop it keeps showing the last key entered again and again.
Please tell me: where am I going wrong?
When you run names[i]=key; you don't really copy key's string value to names[i].
It just makes name[i] point to where key is (since both name[i] & key are pointers).
so all in all you're overwriting key several times, and making all of names pointers point to key.
You need to copy those strings either by working with std::string instead of char* or by using strcpy. I'd recommend on working with std::string.
Using std::string your code should look like this:
#include <iostream>
#include <string>
using namespace std;
const int MAX = 4;
int main ()
{
string names[4];
for (int i = 0; i < MAX; i++)
{
cout << "entr keys" << endl;
cin >> names[i];
cout << names[i];
}
for(int i=0; i<4;i++)
{
cout << names[i];
}
return 0;
}
Every time you execute the lines
cout << " entr keys\n";
cin >> key;
you're inserting a null-terminated string into key, e.g. "hello\0".
Afterwards you copy key's address and store it into a cell of the names pointers array:
names[i]=key; // Now I point to 'key'
cout<< names[i];
then the cycle starts again. Anyway from the second time on you're inserting null-terminated strings into key and thus overwriting the previous contents. The second time if you had entered "hi\0" the contents of the key array would become
['h', 'i', '\0', 'l', 'l', 'o', '\0']
anyway you're going to only print the first string since the null terminator will prevent the other content from being displayed.
When the program ends you're going to have four pointers to the same key array and that array will only contain the last element inserted which overwrote the previous ones.
In order to solve you can make your array a bidimensional one (or use a string array):
const int MAX = 4;
int main ()
{
char key[4][20]; // <- Now this has two indices
char *names[4];
for (int i = 0; i < MAX; i++)
{
cout << " entr keys\n";
cin >> key[i];
names[i]=key[i];
cout<< names[i];
}
for(int i=0; i<4;i++)
{
cout << names[i];
}
return 0;
}
Live Example
Corrected program:
#include <iostream>
using namespace std;
#include <cstring>
const int MAX = 4;
int main ()
{
char key[20];
char *names[MAX];
for (int i = 0; i < MAX; i++)
{
cout << " entr keys\n";
cin >> key;
names[i] = new char[strlen(key) + 1];//names[i]=key;
strcpy(names[i], key);
cout<< names[i];
}
for(int i=0; i<MAX;i++)
{
cout << names[i];
}
for(int i=0; i<MAX;i++)
{
delete [] names[i];
}
return 0;
}
You need to allocate space for each names[i] and when done, deallocate
also, changed the hardcoded 4 to MAX

Return array from function in C++

I tried the code below to return an array with all string ids, but it didn't work.
The output just returns a number. How can I return an array with ids?
#include <iostream>
#include <string>
using namespace std;
string* getArray()
{
int nanim;
cout << "Enter the number of animals: ";
cin >> nanim;
string *id = new string[nanim];
for ( size_t i=0; i < nanim; i++ )
{
cout<< "\nEnter id anim "<< i+1 << ": ";
cin >> id[i];
}
for ( size_t i = 0; i < nanim; i++ )
{
cout << id[i] << endl;
}
return id;
}
int main()
{
int n;
cin>>n;
string* anim[n]=getArray();
cout<<anim;
return 0;
}
You are returning a pointer to the first element in the array.
To access array elements just having called string* arr = getArray(); you can use arr[0], arr[1], arr[2] etc. to access the strings.
Don't forget to delete the memory you allocated in the function though; at the moment you have a big memory leak.
Generally this is not good programming though since the function caller doesn't know how many elements there are in the returned array. It would be better to get the number of animals in the caller and pass that into your function.
Better still, rebuild your code to use std::vector as I see you're already using stl. Then you don't need to worry (explicitly) about memory allocation and deallocation.
You do not need to read the number of elements twice, and the type of the anim should be string*, not string* []. Unfortunately, this wouldn't tell you the number of items in the array, so you need to get it from the getArray, for example, like this:
string* getArray(int& nanim) {
// Remove the declaration of nanim, and keep the rest of the code unchanged
...
}
int main()
{
int n;
string* anim = getArray(n);
for (int i=0; i != n; i++) {
cout << anim[i] << endl;
}
delete[] anim;
return 0;
}
This is not an optimal C++ solution, though: you would be much better off using std::vector instead of an array, because the vector grows dynamically, and its size is returned along with the container itself. There would be no need to delete[] the result either, which would significantly simplify your code:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<string> getVector()
{
int nanim;
cout << "Enter the number of animals: ";
cin >> nanim;
vector<string> res;
for ( size_t i=0; i < nanim; i++ )
{
cout<< "\nEnter id anim "<< i+1 << ": ";
string tmp;
cin >> tmp;
res.push_back(tmp);
}
return res;
}
int main()
{
vector<string> anim = getVector();
for ( size_t i = 0; i < anim.size(); i++ )
{
cout << anim[i] << endl;
}
return 0;
}

How to bubble sort array of pointers to the another array of chars

I have one array containing chars from the input and the other array containing pointers to the corresponding chars in the first array. This part went good.
But then I would like to bubble sort the char** array (array of pointers) so the original array stays untouched but something goes wrong(the text is not sorted).
EDIT: Please discuss only the sorting algorithm
char tab[200];//array of chars
char** t = new char*[tabLength];
//SOMETHING
....
....
int n = tabLength;//length of tab(length of the word it contains)
//TILL HERE EVERYTHING IS FINE -----------------------------------
//bubble sorting below
do{
for(int i = 0; i < n -1; i++){
if(*t[i] > *t[i+1]){
char* x = t[i];
t[i] = t[i+1];
t[i+1] = x;
}
n--;
}
}while(n>1);
cout<<"sorted input";
for(int i = 0; i < tabLength; i++)
cout<<t[i];
cout<<endl;
cout<<"original"<<tab<<endl;
Make sure you print out the values that the pointers point at:
for(int i = 0; i < tabLength; i++)
cout << *t[i];
I would simply use the functionality already at my disposal in the standard library:
#include <iostream>
#include <string>
#include <algorithm>
int main()
{
std::string original;
std::getline(std::cin, original);
std::cout << '|' << original << "|\n";
std::string sorted = original;
std::sort(std::begin(sorted), std::end(sorted));
std::cout << "Sorted : " << sorted << '\n';
std::cout << "Original: " << original << '\n';
}
Test run:
|Hello world, how are you doing today?|
Sorted : ,?Haadddeeghilllnoooooorrtuwwyy
Original: Hello world, how are you doing today?