C++ storing an element of a string array into a variable - c++

I am currently coding in C++ and am fairly new to it. I am running into issues with converting an element of an array of strings into a variable. The cout statement dcity[selection-1] works as intended. However, I am unable to store dcity[selection-1] into a variable named departureLocation. Visual Studios gives me the error that there is no suitable conversion function from a string to a char. Does anyone have advice on how to properly store this? Thanks!
int main()
{
int selection = 0;
char departureLocation;
std::string dcity[] = { "Seattle Detroit Seattle Chicago Houston Seattle" };
std::cout << "Please choose a number from the list";
std::cin >> selection;
std::cout << dcity[selection-1];
departureLocation=dcity[selection-1]
};

Since C++ is a strongly-typed language, it doesn't like type mismatches.
You've declare your variable in the following way:
char departureLocation;
This means departureLocation is a variable of type char, or a single character. So 'C' can go into departureLocation but "Chicago" cannot, as it is more that one character.
You've also declared your array like so:
std::string dcity[] =
Here, you have defined the type of the array as std::string. So elements of the array are strings, not chars.
The short answer is that you need to change the type of departureLocation to a string when you declare it, instead of a char. Something like:
std::string departureLocation;
I also didn't see any include statements in your code above. For C++ to recognize the string class, you'll need to make sure the following is at the top of your code somewhere:
#include <string>

dcity is an array of std::strings. departureLocation is a char which can only hold one character. To store (copy) an element of the array dcity, departureLocation must be of type std::string (or any other type that can be constructed fron a std::string):
std::string dcity[] = { "Seattle Detroit Seattle Chicago Houston Seattle" };
std::string departureLocation = dcity[0];
Be aware thet dcity is an array consisting of only one element. Maybe you want an array where each city is a seperate array element:
std::string dcity[] = { "Seattle", "Detroit", "Seattle",
"Chicago", "Houston", "Seattle" };
std::string departureLocation = dcity[2];
std::cin >> selection;
std::cout << dcity[selection-1];
Also you should do some error checking before using user input as an array index:
if (!(std::cin >> selection) || selection < 1 || selection > sizeof(dcity) / sizeof(*dcity)) {
std::cerr << "Input error!\n";
return EXIT_FAILURE;
}
std::string departureLocation = dcity[selection - 1];
If you don't need independent copies of your array elements you could also use a reference to std::string:
std::string &departureLocation = dcity[selection - 1];
Be aware that changes to the string using departureLocation will now reflect on the array element departureLocation references. If you don't want to allow changes, use a const reference:
std::string const &departureLocation = dcity[selection - 1];

First of all the compiler thinks that there is only one element in the array because arrays in c++ should have commas between each element and each string must be enclosed inside double quotes.The second error is that you are trying to save data of type string into a variable having data type char.
Code
#include<string>
#include<iostream>
using namespace std;
int main()
{
int selection=0;
string depaturelocation;
string dcity[]={"Seattle","Detroit","Seattle","Chicago","Houstan","Seattle"};
int size=sizeof(dcity)/sizeof(dcity[0]);
for(int i=0;i<size;i++)
{
cout<<i+1<<" : "<<dcity[i]<<endl;
}
cout<<"please enter the destination no:";
cin>>selection;
for(int i=0;i<size;i++)
{
if(selection-1==i)
{
depaturelocation=dcity[i];
}
}
cout<<"destination:"<<depaturelocation;
return 0;
}

Your code needs little modification.
1. An array is initialized by giving its component values separated by a comma. Note each individual element should be of the same type as that of the declared array.
2. The C++ is very strict with the type matching. We can assign objects only of the same type. In the above code, a string object is being assigned to a character variable which is against the rule. A C string is an array of characters terminated by null character (\0). In C++, string is more advanced and it is an object which has very useful member function. For e.g. to get length of the string, just say obj.length(). We need to have character array since in string there can be more than one char element. We need to have c-string of the string object to get into an array of characters. Please see below the modified code.
#include <iostream>
#include <cstring>
#include <string>
using namespace std; //std:: is not required in front of cout
int main()
{
int selection = 0;
string dcity[] = { "Seattle", "Detroit" ,"Seattle", "Chicago", "Houston","Seattle" };
cout << "Please choose a number from the list";
cin >> selection;
cout << dcity[selection-1] << endl;
char departureLocation[dcity[selection-1].length()+1];
strcpy(departureLocation,dcity[selection-1].c_str());
cout << departureLocation;
// cout << *c;
return 0;
}

You could to store the selection in a std::string, because char can only store a single character. Be also careful of where you access your array to not go out of bounds (what happens if somebody enters 1000 etc.) and that non-programmer users index lists starting with 1. You can try this code:
#include <iostream>
#include <string>
int main()
{
const auto Cities = { "Seattle", "Detroit", "Seattle", "Chicago", "Houston", "Seattle" };
std::cout << "Please choose a number from the list (1-" << Cities.size() << "): ";
int selection = 0;
std::cin >> selection;
if (selection < 1 || selection > Cities.size()) {
std::cout << "\ninvalid selection!\n";
return -1;
}
const std::string departureLocation = *(Cities.begin() + selection - 1);
std::cout << "\nyou selected: " << departureLocation;
return 0;
};

Related

Console couts a memory address instead of string

As I understand that strings can be treated like arrays, so I tried to insert each character of a string by iterating with a while loop. However the final cout pointed to a memory address, not the string I hoped it would print.
int main()
{
int i = 0;
int n = 2;
char input;
string str1[n];
while(i<=n){
cout<<"enter letter: ";
cin>>input;
str1[i] = input;
i++;
}
cout<<"Your word is: "<<str1;
return 0;
}
The output was:
enter letter: a
enter letter: b
enter letter: c
Your word is: 0x7ffd505af1f0
How can I print my string at the end, instead of a pointer to a mem address?
More interestingly, when I adjusted the final line to cout str1[n] instead of str1, the console prints the next character in the alphabet from the last input!
cout<<"Your word is: "<<str1[n];
and the output is
enter letter: a
enter letter: b
enter letter: c
Your word is: d
How is this happening?
When people say that strings are like arrays, they mean specifically "c-strings", which are just char arrays (char*, or char []). std::string is a separate C++ class, and is not like an array. See this question for a definition of C-strings.
In your example, str1 is actually an array of std::strings, and when you print it, you're printing the pointer address.
Below is an example using both C++ std::string, and a C-string, to illustrate the difference. In general, when writing C++, you should prefer std::string.
const int n = 2;
std::string str1; //A c++ std::string, which is not like an array
char cstr1[n+1]; // a c-string, which is array-like
for(int i = 0; i < n; ++i) {
char input = '\0';
cout<<"enter letter: ";
cin>>input;
str1.push_back(input); //Append to c++ string
cstr1[i] = input; //Add to array-like c-string
}
cstr1[n] = '\0'; //Ensure C-string is null-terminated
cout << "As C++: " << str1 << std::endl;
cout << "AS C: " << cstr1 << std::endl;
cout << "C++ can convert to C-string: " << str1.c_str() << std::endl;
Added const to n, to make it valid C++, since you shouldn't create arrays from non-const variables
Most likely you meant either string str1; or char str1[n]; (I suggest the first one, as the latter is a variable-length array supported only by compiler extensions, not a part of C++). string str1[n]; is an array of strings, which in generally decays to a pointer when passed around, so it happened in your case.
Should you decide to go with the std::string I suggest getting rid of i and n and rewriting it to sth like that:
while(str1.size() < 2){
cout<<"enter letter: ";
cin>>input;
str1.push_back(input);
}
Should you decide to stick to C-style char array (char str1[n];) I suggest making n a compile time constant, i.e. by defining it the following way: constexpr int n = 5; (provided you're on C++11 or newer).

Using pointers to find positions of characters between unbalances parentheses

I am given a C++ programming problem: In a string I need to find wether or not there are balanced parentheses. If not, using pointers I should find position of the characters between unclosed parentheses (between second opening and nearest closing).
The problem statement is a bit confusing, I know. I think it should work somehow like that:
Input #1:
((aba)aaab)
Output:
OK.
Input #2:
(aa(a)ab
Output:
Parentheses not balanced: between characters 1 and 6.
Code below solves part of problem with the closed parentheses check and also there is a structure to keep the address of the opening parenteses. I am not sure how exactly to use pointers for that purposes, some attempts did not give any result, so I need some help here.
#include<iostream>
#include<string>
#include<stack>
using namespace std;
struct br_data{
char br_t;
char *cptr; //store the address of the opening parenthesis
};
int main (){
string input;
int addr;
br_data br;
getline(cin, input);
stack<br_data> braces;
char *a = input[0];
auto init_char = static_cast<void*>(&a); //store the address of the first character in the input string
cout << static_cast<void*>(&a) << endl; //gives the address in memory
for(auto c: input) {
if (c == '(') {
br.br_t = c;
br.cptr = &c; //storing the address of the first parenhesis
braces.push(br);
} else if (c == ')' ) {
if (braces.empty())
cout << "This line does not contain unclosed parentheses\n";
if (!braces.empty())
braces.pop();
}
}
if (!braces.empty()){
//int addr = br.cptr;
cout << "This line does not contain unclosed parentheses\n";
//int pos = (&br.cptr) - (&a); //how to calculate the position??
cout << "Position of the second opening parenthis is " << () << endl;
//cout << "Position of the nearest closing parenthis is " << -how?? (static_cast<void*>(&br.cptr)) << endl;
}
if (braces.empty()){
cout << "Parentheses are balanced in this line\n";
}
return 0;
}
When you write
br.cptr = &c; //storing the address of the first parenhesis
you're actually storing the address of a local object of char type declared earlier:
auto c: input
By the moment you exit the loop it is officially dangling.
One simplest solution would be to actually consider string's characters, not their local copies:
for(auto &c: input) {
(and, even better, change auto into char for better clarity keeping source length the same). Then you can go on and see how your solution needs to be fixed further.
(A few extra free advice: input[0] is a rvalue reference of type char so it makes no sense to assign it to a variable of type char *, and what you try to do in that line is actually written as char *a = input.c_str(); or input.data() or even &input[0], pick the best option; and br.cptr is of type pointer-to-char already, so the character's position in a string would be calculated as br.cptr - a, you need to subtract the pointers themselves, not their addresses.)
#include <iostream>
using namespace std;
int main(){
char str[]="Hello Programming";
char *ptr;
char ch;
char s;
s='n';
ptr=str;
cout<<"To be found Character"<<endl;
cin>>ch;
while(*ptr++ != '\0')
if(*ptr==ch)
s='y';
if (s=='y')
cout<<"FOUND";
else
cout<<"not found";``
return 0;
}

passing array as parameter to a function

this script is supposed to output array values that were inputted by the user into array "store." I am trying to store all the char array values into string temp. I get the error on line 12: "[Error] invalid conversion from 'char*' to 'char' [-fpermissive]." Would appreciate any help!
Edit: so I fixed the declaration and now at least it compiles, but the answer I get on my cmd is all jumbled up. Why is this so? The cmd only correctly couts the first string but after the space, it messes up.
#include <iostream>
#include <cstdlib>
using namespace std;
void coutArray(char[], int);
int main()
{
char store[50];
cout << "enter text: " << endl;
cin >> store;
coutArray(store, 50);
system("pause");
return 0;
}
void coutArray(char store[], int max)
{
string temp = "";
int i = 0;
while (i < max)
{
temp += store[i];
i++;
}
cout << temp << endl;
}
Using input from all answerers I finally got the fixed code:
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
void coutArray(char[], int);
int main()
{
char store[50] = {0};
cout << "enter text: " << endl;
cin.getline(store, 50);
coutArray(store, 50);
system("pause");
return 0;
}
void coutArray(char store[], int max)
{
string temp = "";
int i = 0;
while (i < max && store[i]!=0)
{
temp += store[i];
i++;
}
cout << temp << endl;
}
Thanks everyone. i learned a lot!!!
When you get an input using "cin" your input automatically ends with 0 (NULL).
You just need to add one little piece of code to your while statement.
instead of this :
while (i < max)
use this :
while (i < max && store[i]!=0)
Now it will stop when the input string is finished and won't print any garbage existed in the array beforehand.
To show that cin does add terminating zero, i initialized the array to 46, and put a breakpoint after the cin
so I fixed the declaration and now at least it compiles, but the answer I get on my cmd is all jumbled up. Why is this so?
Not sure what you mean by jumbled up. But since you did not tell us what you typed its hard to know it looks like it worked to me:
> ./a.out
enter text:
Plop
Plop�ȏU�
Notice that since my input is only 4 characters long. This means that a lot of the characters in the array still have undefined (ie random values). This is why I am seeing junk. To get past this initialize the array to have all 0 values.
char store[50] = {0};
Even bettern use a C++ object than handles longer strings.
std::string store;
std::getline(std::cin, store);
Note: passing arrays to functions by value is not a good idea. On the other end they have decayed to pointers and thus do not act like arrays anymore (they act like pointers whose semantics are similar but not identical).
If you must pass an array pass it by reference. But I would use a C++ container and pass that by reference (it is much safer than using C constructs). Have a look at std::string
The declaration of the function is wrong. Should be void coutArray(char *, int);
Look at the Implicit Conversion rules to understand what the compiler can do and what it cannot to do for you.
The issue with your program was that you were probably entering in less characters than the maximum size of the buffer. Then when you passed the maximum size as the parameter to coutArray, you assigned unfilled slots in the char array to temp. These unfilled slots could contain anything, as you have not filled them up to that point.
Your program is still correct, but what would be better would be to use read so that the number of bytes you specify is the minimum number of bytes that can be entered:
std::cin.read(store, 50);
Even better solution would be to use std::string:
std::string store;
std::cin >> store;
// or for the entire line
std::getline(std::cin, store);
It also follows that your coutArray should be changed to:
void coutArray(std::string);
// ...
void coutArray(std::string str)
{
std::cout << str << std::endl;
}
Look at this way
template<typename T, size_t N>
void MyMethod(T (&myArray)[N])
{
//N is number of elements, myArray is the array
std::cout<<"array elements number = "<<N<<endl;
//put your code
string temp;
temp.resize(N+1);//this is for performance not to copy it each time you use += operator
int i = 0;
while (i < max)
{
temp += store[i];
i++;
}
cout << temp << endl;
}
//call it like this
char arr[] = "hello world";
MyMethod(arr);

`const char*' to `char'

I am new to programming and attempted to improve on my basic countdown timer. I don't know why I'm getting this error and other questions are in different situations and therefore don't suit my program.
//countdown timer using while loops, if else, strings and sleep
#include <iostream>
#include <windows.h>
#include <string>
using namespace std;
int main ()
{
char progend[5];
float a; /* a will be floating point */
cout << "Enter start the the number you want to count down from" << ".\n";
while (a>-1) { /* the main program is located here */
cin >> progend[5];
if (progend[5] = "end") /* if the user inputs end the program ends */
{
a = -1;
}
else if (progend [5] = "start")
{
cin >> a;
while (a>0) { /* the actual countdown timer*/
Sleep(100);
a = a - 0.1;
cout << a;
}
cout << "Finished!" << ".\n" << "Enter start then enter another number to count down from or enter end to close the program" << ".\n";
}
else
{
cout << "Enter yes or end";
}
}
return 0;
}
Any help would be appreciated.
char progend[5];
...
if (progend [5] = "start")
tries to assign string literal "start" to 6th character of progend array (which doesn't even exist). Note that even if this code tried to assign a character, writing into the array after its end would cause undefined behavior.
You could either use C-style strcmp:
if (strcmp(progend, "start") == 0)
or yet even better: since this is C++, use std::string objects instead:
std::string progend;
...
if (progend == "start") ... // <-- this will use std::string::operator==
You're trying to assign a char* to char, I'm assuming you want to compare .
So use strstr
if (strstr(progend,"end" )){
//...
}
Similarly all other places
But why not use std::string , when using C++
std::string progend;
if(progend.find("end") != std::string::npos)
{
}
You are assigning a const char * to a char variable in
if (progend[5] = "end")
progend[5] is an element of a char array that holds a char value. "end" cannot be assigned to it.
You can use std::string. Then compare it like
std::string progend;
...
if(progend == "end")
{
//your code
You made a number of different errors.
cin >> progend[5];
Here, you ask for a character input, instead of a string. What is more, index 5 is out of the bounds of the array (we start counting from 0).
progend[5] = "start"
Here, there are two errors. To compare for equality, you sholud use == instead of =. What you actually did is try to assign a value. What is more, "start" is a C-type String, or better a pointer to the first character of the String.
Why don't you simply use a String from the C++ STL?
#include <string>
using namespace std;
// etc.
String progend;
Also, replace all instances of progend[5] with progend, you are not refering to a specific position. Equality check must also be ==.
I hope this helps!!! :D

adding string objects to an array via loop

What i'm trying to do is create a template array class that will store values of a data type into an array. I have it working fine with int values, however working with string objects things start to break down.
I've taken out the block of code and tried it on it's own and I do get the same error. I'm sure I've learnt this, and I'm almost positive that the answer is something simple, trying to wrap my head around the pace in which we're learning c++ is a little crazy at times!
My best guess right now, is that I would need to tokenize the string and look for spaces. I tend to over think things though which lead to more confusion - thus me seeking out a answer here!
The code:
// Test String: Hello World this is a String Object
int stringSize = 7;
int count = 0;
string s[stringSize];
cout << "\nEnter " << stringSize << " one-word string values:\n";
while (count < stringSize) {
string tmpVal;
cin >> tmpVal;
s[count] = tmpVal;
count ++;
}
string s[stringSize]; is illegal because stringSize is not a constant. You must either use dynamic memory (i.e. string* s = new string [stringSize];), include stringsize as a template argument (don't do this, it doesn't actually solve the problem), use a fixed size value, or use an existing structure (I'd suggest vector, as in Bill's answer). The code below works fine on my compiler:
int main(int argc, char *argv[]) {
int stringSize = 7;
int count = 0;
string* s = new string [stringSize];
cout << "\nEnter " << stringSize << " one-word string values:\n";
while (count < stringSize) {
string tmpVal;
cin >> tmpVal;
s[count] = tmpVal;
count ++;
}
delete[] s;
}
I am a little confused as to exactly what you're looking for, but I suggest looking into the standard library.
Perhaps something like:
list<string> s;
and then, in the loop use push_back.
I am also confused what is your actual question, because your code works. However, FWIW, I would suggest the following. The changes are: (1) use of const (already suggested by others), (2) use of size_t, (3) change of variable name stringSize to numStrings (because of this I was confused at first glance), and (4) avoiding string copy.
#include <iostream>
#include <string>
using namespace std;
int main()
{
const size_t numStrings = 7;
size_t count = 0;
string s[ numStrings ];
cout << "\nEnter " << numStrings << " one-word string values:\n";
while (count < numStrings) {
cin >> s[ count ];
count++;
}
return 0;
}
Why not read in the entire line, then find all spaces and using the substr method, split the string?
You will need the following methods:
getline()
find_first_of()
substr()
Also, searching around this site for splitting strings in c++ will give you a lot of tips.
First of all, the size of your array should be constant:
const int stringSize = 7;
Secondly, as dbrien said, you should use std::vector unless you're doing this for the learning experience:
std::string tmpVal;
std::vector<std::string> s;
cout << "\nEnter " << stringSize << " one-word string values:\n";
while (cin >> tmpVal)
{
s.push_back(tmpVal);
}
First, the array dimension must be constant, so it should be const int stringsize = 7; Also, I would suggest using std::vector rather than std::list, additionally What was the error?
Not sure what error you're getting, but this is wrong because you need to use a constant integral value to allocate arrays on the stack.. Change:
int stringSize = 7;
int count = 0;
string s[stringSize];
... to:
const int stringSize = 7;
int count = 0;
string s[stringSize];
You can and probably should also use a vector instead of using C-style arrays, or trying to hand roll your own templated array class:
vector<string> s;
const int stringSize = 7;
cout << "\nEnter " << stringSize << " one-word string values:\n";
while (s.size() < stringSize) {
string tmpVal;
cin >> tmpVal;
s.push_back(tmpVal);
}
So it turns out it was the compiler. I was using xCode and getting:
cin_cout(7307) malloc: *** error for object 0x1000072c0: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Running the same block in Visual c++ seemed to be ok... Sorry for my stupidity and thanks kindly for all the quick feedback!