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).
Related
I tried to write a function similar to strcat() in c++.
Here is the code of this function:
char *mystrcat(char *str1, char *str2){
int i = 0;
char *buffer = str1;
while(*str1){
str1++; i++;
}
i++;
while(*str2){
str1[i] = *str2;
str2++; i++;
}
str1[++i] = '\0';
str1 = buffer;
return str1;
}
The input values for this function are given by this code:
char string1[100], string2[100];
cout << "Enter string 1 ";
cin >> string1;
cout << "Enter string 2 ";
cin >> string2;
mystrcat(string1, string2);
cout << string1 << endl;
When I ran the code and tried to input two strings, it has given me this output:
Enter string 1 qwerty
Enter string 2 asdf
qwerty
Why the first string is displayed only?
For a start, since you're incrementing both str1 and i in the first loop, you're going to move twice as fast through that array as you think. Thats because you're increasing both:
the base of the array; and
the offset from that base.
You're actually lucky to have chosen an even number of characters, otherwise you'd probably keep going beyond the end of str1 (by missing the \0), resulting in all sorts of fun and hilarity :-)
You should increment one or the other, such as with:
char *mystrcat(char *str1, char *str2) {
int i = 0;
while(str1[i] != '\0')
i++;
while(*str2 != '\0')
str1[i++] = *str2++;
str1[i] = '\0';
return str1;
}
The reason why you only get the first string after the concatenation, is the i++ after the first loop (which I've removed from the above code).
When you exit that loop, i is the index of the str1 terminator character so, an i++ at that point will jump over it. That means that you'll append str2 after that terminator:
qwerty<nul>asdf<nul>
Hence the string will only be qwerty because C strings always stop at the first terminator.
I often find it's useful to be able to start with a memory map and variable register (on paper), then run the code in your head, changing variables along the way. It helps to understand how your program will work. You can start with something like:
1 2
Index: 012345678901234567890
str1: qwerty_
str2: asdf_
i: 0
Then, each line of code in your head will result in i changing, or the string memory blocks changing (the _ at the end indicates the string terminator).
Don't increment the string pointers. Do just
while (str1[i]) {
++i;
}
And start with iterating str2 with another variable, from 0.
What you are doing currently is basically: str1[12] = str[6]
When you want: str1[6] = str2[0]
I'm trying to keep the alphabet in a char array. But 4 letters show absurd charachters.
I run the program step by step using F11 button. Wrote the alphabet and after 'Q', until 'V' whatever I write, it shows ...PQÿÿÿÿVWXYZ this character: 'ÿ'
int main()
{
cout << "ALPHABET:";
char alf[] = "";
cin >> alf;
system("PAUSE");
}
I expect: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Actual result: ABCDEFGHIJKLMNOPQÿÿÿÿVWXYZ
Problem is with this line:
char alf[] = "";
you declare char array with size 1 which can only hold empty strings (null terminator). Note that std::istream::operator>> with char * does not validate size of array (it cannot) so you are getting Undefined Behavior writing into array with out of bounds. Solution is to use std::string instead which will grow as needed.
int main()
{
std::cout << "ALPHABET:";
std::string alf;
std::cin >> alf;
std::cout << alf << std::endl;
}
I am trying to learn c++ and one of the assignments is to ask the user for a letter - then ask for a string of text and count how many times the 1st letter is repeated in the string of text.
I have written some code that successfully gets to the point of asking for the letter & the string of text - I can display both
I can traverse the string of text counting how many letters there are in the string. When I try to add an if check to compare the current letter in the string inside the loop with the letter 1st asked for - I get this compile error:
error: ISO C++ forbids comparison between pointer and integer [-fpermissive]
if (textToCount[i] == letterToCount)
this is the full code I have written
char getLetterToCount(char letterToCount[]);
char getTextToCount(char textToCount[]);
int countLetters(char letterToCount[], char textToCount[]);
int main()
{
char letterToCount[1];
getLetterToCount(letterToCount);
char textToCount[256];
cin.ignore();
getTextToCount(textToCount);
countLetters(letterToCount, textToCount);
return 0;
}
char getLetterToCount(char letterToCount[])
{
cout << "Enter a letter: ";
cin >> letterToCount;
}
char getTextToCount(char textToCount[])
{
cout << "Enter text: ";
cin.getline(textToCount, 256);
}
int countLetters(char letterToCount[], char textToCount[])
{
int numChrsInString = 0;
int numTimesChrtoCountrepeated = 0;
for (int i = 0; textToCount[i] != '\0'; i++)
{
if (textToCount[i] == letterToCount)
{
numTimesChrtoCountrepeated++;
}
}
cout << "num chrs in string: "
<< numChrsInString
<< "num times chr counted: "
<< numTimesChrtoCountrepeated
<< endl;
}
I did a fair bit of output to try and figure out what was wrong with these - I pulled the code for that out because it made it a bit more confusing.
BUT the compile error explains what is wrong, I just don't understand why it is wrong because the things I am trying to compare are BOTH text letters...
It would be great if someone who knows c++ can explain what I am doing wrong
You are comparing a char with a pointer to char
Use:
if (textToCount[i] == letterToCount[0])
~~~
Note: There are few obvious nitpicking but above is the main compiler error cause
In C++, arrays are pointers. C++ considers lettertocount to be a pointer because you're passing it as an array. You don't want to pass that; you want to pass just a character:
int countLetters(char letterToCount, char textToCount[])
A bigger question to my mind is, why do you think you have to pass lettertocount as an array? Apparently it's just one letter. When you invoke this function do you eventually want to count multiple letters?
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!
First off, this is a "homework" question so vector libraries and string libraries are off limits. I'm trying to get to the basics of c++.
My intention with this code is to make and use an array of string arrays. A list of words in other words.
When I run this code I get a bunch of nonsense.
If there is a better way to make a list of words in c++, I would love to hear about it.
const int cart_length = 50;
const int word_length = 50;
int main()
{
char cart_of_names[cart_length][word_length];
float cart_of_costs[cart_length];
char name[word_length];
cout << "enter the name of the first item: ";
cin >> name;
for(int i=0; i<word_length; i++)
{
cart_of_names[0][i] = name[i];
}
cout << endl;
cout << "that is: ";
for(int x=0; x<word_length; x++)
{
cout << cart_of_names[0][x];
}
cout << endl;
return 0;
}
If the string entered is not 50 characters long (cart_length), then less than 50 characters will be valid in the name. You should have an if(cart_of_names[0][x]==0) break; in your second loop.
I don't exactly understand what you are looking for. Following code will help you to read and print a list of 50 words. Hope this would help you.
const int cart_length = 50;
const int word_length = 50;
int main()
{
char cart_of_names[cart_length][word_length];
float cart_of_costs[cart_length];
for(int i=0; i<cart_length; i++)
{
cout << "enter the name of the " << i + 1 << "th item: ";
cin >> cart_of_names[i];
}
cout << "that is: ";
for(int x=0; x < cart_length; x++)
{
cout << cart_of_names[x] << endl;
}
return 0;
}
Check out STLSoft's fixed_array_2d (and it's higher order siblings). There's a detailed discussion of how they're implemented for maximum performance in Matthew Wilson's Imperfect C++.
If you can't use std::string, at least look at the functions like strncpy() from C for your name copying. Also, you're forgetting that c-style strings are null terminated.
Unless you're forbidden to use STL (which would be just mean), just use std::list<std::string>. www.cplusplus.com has detailed descriptions and examples for those classes.
Otherwise, you're stuck with an array of char arrays: in that case, be prepared for a lot of buffer overflow errors. Look around on the above site for the char[] management functions (strncpy() and the like), they'll make your life a bit easier (but not a lot).
In C, the best way I found to conceptualize what you are trying to do is using an array of char*. Same effect, but if you start to work with it I believe you may find it is easier on the brain.
It looks pretty close to me. Strings in C are null-terminated, which means that the end of the string is indicated by a null character. In a sense, a string in C is really just an array of bytes.
When you do:
cout << "enter the name of the first item: ";
cin >> name;
If I enter the string "Book", in memory it'll look like something like:
|0|1|2|3|4|5..49|
|B|o|o|k|0|*HERE BE DRAGONS*
Well, really it will contain the ASCII values corresponding to those letters, but for our purposes, it contains those letters. There here be dragons is memory that that you didn't initialize, so it contains whatever garbage your platform sets it to.
So when you copy your string, you need to instead look for that 0 byte at the end of the string.
for(int i=0; name[i]!=0; i++)
{
cart_of_names[0][i] = name[i];
}
Then when you output it, you don't actually need to do it a character at a time. You can just do cout<<cart_of_names[0]. cout knows where the string ends because of that terminating null character.
If you use strcpy() instead of
cart_of_names[0][i] = name[i];
it may work better but I cringe just looking at all that code.
"If there is a better way to make a list of words in c++, I would love to hear about it."
Include #include <string> and use std::string. The std::string type is part of the C++ specification, I think.
#include <iostream>
#include <string>
int main(void) {
std::string list[7];
list[0] = "In C++";
list[1] = "you can use";
list[2] = "the `std::string` type.";
list[3] = "It removes";
list[4] = "many of the problems";
list[5] = "introduced by";
list[6] = "C-style strings.";
for (int k=0; k<7; k++) std::cout << list[k] << ' ';
std::cout << '\n';
return 0;
}