it looks like when I cout *cp, it only outputs the first letter of the string and after I put them in vector, my output is blank. what am I doing wrong?
//write a program to assign the elements from a list of char* pointers to c-style character strings to a vector of strings
#include <iostream>
#include <cstring>
#include <vector>
#include <list>
#include <string>
using namespace std;
int main ()
{
list<const char*> clist;
cout<<"please enter a string"<<endl;
for(string s; getline(cin,s); )
{
const char* cp=s.c_str();
clist.push_back(cp);
cout<<*cp;
}
cout<<*clist.begin();
vector<string> svec;
svec.assign(clist.begin(),clist.end());
for(vector<string>::iterator iter=svec.begin(); iter!=svec.end(); ++iter)
cout<<*iter<<endl;
return 0;
}
This will print the whole string:
cout << cp; // You're providing cout a const char *
This will only print one character:
cout << *cp; // You're providing cout a char
As to what's wrong with your vector, you're only storing pointers to strings, not strings themselves. The memory for the string has gone out of scope. As others have said, use std::string instead of raw const char *.
cout *cp, it only outputs the first letter of the string
Well, *cp is a character (the one found at the location to which the pointer cp pointers). So, yea, it will.
after I put them in vector, my output is blank
It's unfortunate that your program did not crash outright, as the pointers in your list become dangling pointers almost as soon as you store them.
Store std::strings from the very start.
cout<<*cp;
will output a single character because it points to a const char *
You need to do:
cout<<cp;
This will output the entire string pointed by cp.
You have a couple big problems here. First of all,
const char* cp=s.c_str();
returns a pointer to an internal member string within std::string. When you change the string, the value referenced by the returned pointer to c_str may be changed (may even be in a new location). So, the values in your list are not valid. Make sure you don't use c_str and try to make use of the result after the original string has been changed (unless you copy the c_str result into a new char array.
Also,
cout<<*cp;
only prints our your first element. Get rid of the * to print the whole c-string at that list element.
it looks like when I cout *cp, it only outputs the first letter of the string
*cp is the first letter of the string. cout << cp will print the whole string.
after I put them in vector, my output is blank.
Your list contains pointers to the contents of s, which is only valid within the body of the loop. Once the string goes out of scope, the pointer is "dangling" - pointing to deallocated memory. Trying to use the pointer will give undefined behaviour.
You'll need to keep hold of a copy of the string itself, either by making clist a list<string>, or by keeping the strings in another container, and storing pointers to the data in that container in clist.
Alternatively, you could use string literals rather than reading strings from cin. String literals live as long as the program, so there are no issues with dangling pointers.
(That's assuming that the comment in the first line of your code is a specification that you can't change. Otherwise, I'd get rid of clist completely, and push each string onto the back of svec as I read it. It's rarely a good idea to use pointers for anything.)
Related
So I wrote a code that inputs a word, takes it's first letter and puts it at the end of the word( eg. "egg" will be "gge", and if we do the same process again it will be "geg" and then finally back to "egg")
I want to do this process only 1 time. And I want to use a pointer to memorize the initial value of the word, that is egg, and then the string has to memorize "gge".
This is the code:
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char s[100],aux,*P;
int p=1,i,n,k,j;
cin.get(s,100);
i=0;
while(i>=0)
{
P=s; //this is the pointer that SHOULD memorize "egg"
aux=s[0];
for(j=1; j<=n; j++) s[j-1]=s[j];
s[n]=aux;//until here it does the letter thing
break;
}
cout<<P<<endl<<s;//now here the pointer P should be "egg" and the string s should be "gge"
//but the program prints out "gge" and "gge".
return 0;
}
What am I doing wrong and how am I supposed to do what I want?
What am I doing wrong and how am I supposed to do what I want?
You seem to have misunderstood what a pointer is.
A pointer is a variable that points to something else. In this case
char s[100];
char *P = s;
P points to the first character element of s. This is the same pointer that s decays to in many contexts.
You still only have one array to store 100 characters. You just have two identifiers for that array, because you can reach it via either s or P.
If you mutate that array in place from "egg" to "gge" or whatever, P still just points to the same array it did originally. It didn't save a copy of anything but the location (address) and that isn't what changed.
If I can take two roads to get to your blue house, and you repaint the house green, one of the roads doesn't still lead to the original blue house. That isn't how roads work, or how houses work, or how pointers work.
You want somewhere to store the original 3 or 4 characters, which means you want another char array, or better a std::string. This will make a copy of the characters you care about before you change them.
The minimal working change is probably
// P = s <-- just stores the location
P = strdup(s); // <- copies the contents
but do note you should free(P) at some point after you're done with it. Switching to std::string is really much easier.
Simple example of using std::string value semantics to do the copying:
#include <string>
#include <algorithm>
#include <iostream>
// source is a copy of the string passed
std::string rotate_left(std::string source, size_t offset = 1)
{
std::rotate(source.begin(), source.begin()+offset, source.end());
return source;
}
int main()
{
std::string original{"eggsoup"};
// for interactive use: getline(std::cin, original);
std::string rotated = rotate_left(original);
std::cout << original << '\n' << rotated << '\n';
}
This is called rotating the string.
It's not clear why you have decided to use a pointer for this. A pointer is not a string. A pointer doesn't "contain" its own information*. A pointer points to some piece of information. Here you're making a pointer that points to the original string, and then you alter that string … but your pointer is still just pointing to that same, altered string. The pointer has no knowledge of what form the string used to take, only where it is.
If you want to store a copy of the original string, you have to literally do that, either by copying its elements into a second char array, or by switching to std::string because it's 2018. 😀
* Well, obviously it does; it contains the address of the thing it points to, which in itself is "information". But it's not the information you wanted.
If you really want to use a pointer, you can actually get the expected outcome using them, but not in the way that you're expecting (i.e. not by storing a copy of the string). Since you know you have rotated the string n times, and you know where it starts (that's P!) and you know how long it is (that's n, although you currently aren't setting that, which is a bug), you can do some mathematics to output the original form of the string just by navigating its current form in a different order.
const char* startOfString = &s[0];
const size_t lengthOfString = strlen(s);
const size_t numberOfRotations = 1;
// ... do your rotation here
// Now we can still print the original form, char by char, using MATHS!
for (size_t index = 0; index < lengthOfString; index++)
{
const size_t adjustedIndex = (index + lengthOfString - numberOfRotations) % lengthOfString;
std::cout << startOfString[adjustedIndex];
}
(live demo)
But, then, you may as well have "performed" (or pretended to perform) the actual rotation in this manner in the first place, too.
Or just print the string when you get it, before you rotate it.
I am learning pointers and i tried this following program
#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;
char* getword()
{
char*temp=(char*)malloc(sizeof(char)*10);
cin>>temp;
return temp;
}
int main()
{
char *a;
a=getword();
cout<<a;
return 0;
}
To my level of understanding, a is a pointer to a character, and in the function getword() I returned temp which I think the base &temp[0]. I thought that the output would be the first character of the string I enter, but I got the entire string in stdout. How does this work?
In the tradition of C, a char* represents a string. Indeed, any string literal in your program (e.g. "hello") will have a type of const char *.
Thus, cout::operator<<( const char * ) is implemented as a string-output. It will output characters beginning at the address it is given, until it encounters the string terminator (otherwise known as null-terminator, or '\0').
If you want to output a single character, you need to dereference the pointer into a char type. You can choose one of the following syntaxes:
cout << *a; // Dereference the pointer
cout << a[0]; // Use array index of zero to return the value at that address
It should be noted that the code you provided isn't very C++ish. For starters, we generally don't use malloc in C++. You then leak the memory by not calling free later. The memory is uninitialised and relies on cin succeeding (which might not be the case). Also, you can only handle input strings of up to 9 characters before you will get undefined behaviour.
Perhaps you should learn about the <string> library and start using it.
It's true that char* "points to a character". But, by convention, and because with pointers there is no other way to do so, we also use it to "point to more than one character".
Since use of char* almost always means you're using a pointer to a C-style string, the C++ streams library makes this assumption for you, printing the char that your pointer points to … and the next … and the next … and the next until NULL is found. That's just the way it's been designed to work.
You can print just that character if you like by dereferencing the pointer to obtain an actual char.
std::cout is an overloaded operator and when it receives a char * as an operand then it treats it as a pointer to c style string and it will print the entire string.
If you want to print the first character of the string then use
cout << *a;
or
cout << a[0];
In your code, std::cout is an ostream and providing a char* variable as input to operator<< invokes a particular operator function overload to write characters to the ostream.
std::ostream also has a operator overload for writing a single character to itself.
I'm assuming you now know how to dereference a char* variable, but you should be using std::string instead of an unsafe char* type.
Here is the correct code
#include <stdio.h>
#include <stdlib.h>
char* getword()
{
char*temp=(char*)malloc(sizeof(char)*10);
scanf("%s",temp);
return temp;
}
int main()
{
char *a;
a = getword();
int currChar = 1;
printf("%c",*(a + currChar)); //increment currChar to get next character
return 0;
}
#include <iostream>
#include <string>
using namespace std;
int main() {
string s = "hello";
cout << s[5] << endl;
return 0;
}
In the above code, if I print s[5], it correctly prints a NULL character. But if I change the code to this:
#include <iostream>
#include <string>
using namespace std;
int main() {
char[] s = {'a','b','c','d','e'};
cout << s[5] << endl;
return 0;
}
It doesn't print a NULL character but something random. If I store the string as a string or as a char*, then the behavior is in tune with what I expect.
But if I explicitly declare the character array, how does the compiler know when the array ends? Does the size of the array gets stored at compile time?
String literals and std::strings store null terminated strings.
But an array of 5 char declared like:
char s[] = {'a','b','c','d','e'};
contains only 5 char, no null terminator.
But the compiler does know the size of s. It is part of the type of s. It has no convenient .size() function like std::string, std::vector or std::array does but you can get it by doing:
sizeof(s) / sizeof(s[0])
Or more safely in C++11:
std::extent<decltype(s)>::value
Or in C++17:
std::size(s)
(demo)
Arrays have a habit of decaying to pointers though and then there is no way of getting the size, you have to keep track of it yourself. Which is why std::string, std::vector or std::array is preferred in C++.
Strings are null-terminated, and const char* are treated the same way as Strings are. When you declare a array with a size it's put on the stack and the compiler doesn't know the size. Array out-of-bounds exceptions aren't determined during compile time.
the string class in c++ has the constructor which by itself adds the null character to the string passed to it if not explicitly added. But while using char it only stores the content passed to it (i.e) if you want to have a null character you have to explicitly add in the declaration or the definition of that char.
When you do char[] s = {'a','b','c','d','e'};, it will store characters mentioned and nothing else.
if I explicitly declare the character array, how does the compiler know when the array ends?
size is determined by number of characters provided by you.
Does the size of the array gets stored at compile time?
no, the size of array is determined by memory blocks allocated to it. (It is not stored separately in memory, if that's what you meant)
And when you use this string s = "hello";, strings are always null terminated.
Your code is char s[] = {'a','b','c','d','e'};, so it will not put the \0 at the end of your char array. It will put the \0 with three methods below:
1. char s[] = {'a','b','c','d','e', '\0'};
2. char s[] = "abcde";
3. string s = "abcde";
So if you use any of the three above, you will get a NULL character.
"how does the compiler know when the array ends ?": the compiler knows how many elements the array has, from its declaration, and this information is available through the sizeof operator.
Anyway C-style arrays have virtually no size, as they are implicitly turned to pointers when passed as arguments, and their length is dropped (IMO a major flaw in the design of the C language). Overflow avoidance is your responsibility.
For this reason, you mustn't use a cout << statement if your string isn't null-terminated.
Just trying to assign chars to the char array and it says string in not null terminated?
I want to be able to change the teams around in the array like a scoreboard.
#include <string.h>
#include <iostream>
int main(int argc, char* argv[])
{
char Team1[7] = "Grubs";
char Team2[7] = "Giants";
char Team3[7] = "Bulls";
char Team4[7] = "Snakes";
char Team5[7] = "Echos";
char TeamList[5][7];
strcpy_s(TeamList[0], Team1);
strcat_s(TeamList[1], Team2);
strcat_s(TeamList[2], Team3);
strcat_s(TeamList[3], Team4);
strcat_s(TeamList[4], Team5);
TeamList[5][7]= '\0';
system("pause");
return 0;
}
strcat() (which is a "less-safe" version of strcat_s()) requires both strings to be null-terminated. That's because strcat() appends its second parameter (source) where first parameter (dest) ends. It replaces null-terminator of dest with first character of source, appends rest of source and then
a null-character is included at the end of the new string formed by
the concatenation of both
I would simply change
strcpy_s(TeamList[0], Team1);
strcat_s(TeamList[1], Team2);
strcat_s(TeamList[2], Team3);
strcat_s(TeamList[3], Team4);
strcat_s(TeamList[4], Team5);
to
strcpy_s(TeamList[0], Team1);
strcpy_s(TeamList[1], Team2);
strcpy_s(TeamList[2], Team3);
strcpy_s(TeamList[3], Team4);
strcpy_s(TeamList[4], Team5);
strcpy_s() does not have any requirements regarding contents of destination - only its capacity matters.
If you want to stick with strcat_s(), do this:
char TeamList[5][7];
memset(TeamList, 0, sizeof(char) * 5 * 7);
Then, this line:
TeamList[5][7]= '\0';
is not required, It is incorrect anyway, because for N-element array valid indexes are [0; N-1].
EDIT
Since in your case swapping comes into play, I would suggest you totally different approach.
First of all:
#include <string>
Then, initialize teams this way:
std::string TeamList[] =
{
"Grubs",
"Giants",
"Bulls",
"Snakes",
"Echos"
};
Now, TeamList is an array containing 5 elements and each of these elements is an object of type std::string, containing name of a particular team.
Now, if you want to swap, let's say, teams 1 and 3:
std::swap(TeamList[1], TeamList[3]);
std::swap() is a standard C++ function extensively used in standard library implementation. It is overloaded for many standard types, including std::string. This solution has one, critical benefit: if string's content is held on the heap, swapping two strings is as simple as swapping pointers (and some length/capacity variables).
Oh, and one more thing: if you are not familiar with std::string and you would need to get pointer to a buffer containing string's data, you can do it this way:
const char* team_1_raw_name = TeamList[0].c_str();
See this page for more info about std::string
strcat requires that there already be a null-terminated string in the destination to concatenate the source string onto; you're calling it with uninitialised values in the destination.
It looks like you want strcpy in every case, not just the first.
Also, remove the bogus TeamList[5][7]= '\0';. Even if you fix it to write inside the array bounds, each string has already been terminated by strcpy so there's no need to try to do that yourself.
Then stop messing around with low-level arrays and pointers. std::vector<std::string> would be much friendlier.
Learning C++. I just want to grab the first character in a string, then make a new string based on such character, and then print it out:
#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
string name = "Jerry";
char firstCharacter = name.at(0);
string stringOfFirstCharacter = string(&firstCharacter);
cout << stringOfFirstCharacter;
return 0;
}
The output is:
J
Jerry
I don't really know why is it also printing Jerry. Why is that?
Your code has undefined behavior. The signature of the constructor that takes a pointer to char requires that it is a pointer to a null terminated string, which it is not in your case since it is a single character.
My guess is that the implementation you have uses the small object optimization, and that "Jerry" is small enough that it is stored inside the std::string object rather than dynamically allocated. The layout of the two objects in the stack happens to be first firstCharacter, then name. When you call std::string(&firstCharacter) it reads until it hits the first null character (inside the std::string buffer) and stops there.
You are constructing an std::string object from a char* (because you are taking the address of firstCharacter). A pointer to a character is not interpreted as a character itself by the constructor of std::string, but rather as a null-terminated string.
In this case, your program has Undefined Behavior, because the address of firstCharacter is not the address of the first character of a null-terminated string.
What you should be doing is:
string stringOfFirstCharacter(1, firstCharacter);
cout << stringOfFirstCharacter;
If you really want to create a one-character string. However, notice that in order to print the character to the standard output, you could have simply written:
cout << firstCharacter;
Or even:
cout << name.at(0);
With string(&firstCharacter), you are using the std::string constructor of the form
std::string( const char* s, const Allocator& alloc = Allocator() );
That form expects a pointer to a null-terminated array of characters. It is incorrect to pass a pointer to character(s) that are not null-terminated.
With your intention of initializing the string with 1 char, you should use the form:
string( 1, firstCharacter )
The string constructor you're using (the one that takes a char * argument), is intended to convert a C-style string into a C++ string object - not a single character. By passing it a single character you cause undefined behaviour.
In your specific case, there appears to not be a zero byte in memory after firstCharacter, so the constructor runs through and includes all of name along with it!