Using char and char[] in C++ [closed] - c++

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I'm having trouble using type char. When I initialize my ID and Name in my struct by a constructor, why am I getting this error message? "expression must be a modifiable lvalue".
struct Staff
{
char ID[8];
char Name[30];
Staff()
{
ID = "";
Name = "";
}
};

Since this question is tagged C++ and the code make uses of C++ only features (such as constructors), I'm going assume you have mistakenly confused C with C++ in your title.
Don't use char arrays when you really mean strings. Use std::string instead:
struct Staff {
std::string ID;
std::string Name;
};
In this way the default constructor will behave as expected and you won't even need to specify it. The only additional line you'll need is the one that includes the necessary header:
#include <string>
on the very top of the file.

char in C and C++ is just another numeric type, like int, but smaller (generally one byte). An array of chars is not special -- it's basically a raw hunk of memory. A string literal is internally an array of chars as well, but C++ has no built-in support for copying arrays with operator= -- you have to copy the bytes yourself, for example via the (deprecated) strcpy C function (include cstring).
In C++, the usual way to deal with strings is to use std::string (include string), which is a class that wraps the string's bytes for you, and implements string copying, comparison, etc. in a clean, intuitive fashion.
You're also missing a semicolon at the end of the Staff structure, which will cause some interesting compile errors :-)

You cannot change the value of ID or Name since it is an array, not a pointer.
Either declare it as char pointer (in this case it's better to declare it as const char*):
const char *ID;
const char *Name;
Or use memset:
memset(ID, '\0', sizeof(ID));
memset(Name, '\0', sizeof(Name));
This will "initialize" your char arrays.
You can do the same to assign a string to the array using strncpy
strncpy(Name, "John Doe", sizeof(Name)-1);
The -1 accounts for the null terminating character.

What you need to do is
struct Staff
{
char ID[8];
char Name[30];
Staff() :
ID{0}, // Null terminate the array same as, ID[0] = 0;
Name{0} // Null terminate the array same as, Name[0] = 0;
{
}
};

Related

Assigning string* to char* c++ [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I need to read a file in c++ and save every line(in a vector) as i will be processing them later.
I also need to save a vector of char* that will point to the first position of each string*.
The problem is that I don't know how to assign the string* to char*.
FYI, i can not use const char*, it has to be char*.
Code:
void ClassA::readFile() {
std::ifstream file("test.txt");
std::string* str = new string();
while (std::getline(file, *str))
{
_aVector.push_back(*str);
char *c = &str[0]; <-- This works if string is not declared as string*
char *c = .... <--What is the equivalent for string*
str = new string();
someFunction(c); <-- This function saves the *c in a vector.
}
}
Though the std::string protocol gives you access to the underlying memory, e.g. by calling member c_str(), these pointers are all const. If you cast it to a non-const pointer, you risk undefined behaviour if a function beyond your control then modifies the content through such a pointer.
Since C++17, the data-method gives you access to a non-const pointer to the underlying data.
Anyway, note that a string-object will - again beyond your control - replace the underlying memory if necessary, and your pointers might become invalid then. So I'd say that it's generally not a good idea to store pointers to the contents of string objects.
The only way to get a char*-pointer to the contents of an std::string I see is to copy the contents of the string, e.g. by using strdup. Thereby you avoid undefined behaviour from unintended modifying access, and you decouple the char* from the memory managed by the string object.
See the following code illustrating this:
int main() {
std::vector<std::string> aVector;
std::ifstream file("test.txt");
std::string str;
while (std::getline(file, str))
{
aVector.push_back(str);
char *c = strdup(str.c_str());
someFunction(c); // <-- This function saves the *c in a vector.
}
}

How is a const char* not a just a character? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I'm really confused about this because personally, I come from a java background, and recently began c++. So, I learnt all the basic stuff, like, printing stuff out to the screen and whatnot, and now, I learnt POINTERS. So, the person on youtube (The Cherno's C++ Pointer tutorial This was not the video where he declared the const char*, just the pointer tutorial that I followed.) I've been following was using this following statement to declare what I know as a 'string'.
const char* str = "random text here";
But, how is a char* converted into a string, and its even using the double quotation marks like a string! Also, what does a constant have to do with any of this? If I remove the const from my code it gives me an error. But, I understand what a pointer is. It is a variable that holds the memory address of another variable, so if one was to access that variable directly, they would just have to do *ptrVarName and dereferenced it. But how can a string "like this one" be a memory address?
Wouldn't I have to do something like this?
char[] str = "string here";
and THEN do:
char* stringPointer = *str;
(WARNING: untested code!)
Thanks in advance.
(oh and sorry if this is a really NOOBY question or the question is poorly constructed, I've just started out with c++ and stackoverflow)
EDIT: Ok, so I understand what the char* str means. It means that when you reference *str, it means that you're accessing the first character in memory. Ok, I get it now. But, what does const mean?
const char* str = "random text here";
On the right hand side, the "random text here" defines a string literal which actually is an array of type const char[17] (including the null terminator character). When you assign that array to const char* str it decays to a pointer that points to the first character. You cannot modify the string literal through the pointer because string literals are stored in read-only memory, so the following would be illegal: str[0] = 'x';
char[] str = "string here";
This one is different. It defines the char array str which has the same size as the string literal on the right hand side (const char[12]). The string literal will be copied into the array str, so you will be able to modify str. In this case, it would be legal to write str[0] = 'x';.
If you declare const char* sth ="mystring"
It will place mystring inthe memory and sth pointing to that its work like array but with direct access to memory
These are plain C-strings. A C string is always null terminated. In other words- it has '\0' at the end. So you need only the place in memory where the string starts and you can find when it ends.
For pointer arithmetic these [] brackets are only syntax sugar. str[] is the same as *str and str[1] is the same as *(str+1) only incrementing the pointer by one char (8 bits) and getting the address of the second element.
C doesn't really have strings. A string is an array of characters, terminated by a nul (0). Now arrays and pointers in C are closely linked, and a char * or const char * usually points to a string, but only in the same way as other pointers usually point to arrays. An individual char * might only point to a single character, you have to know from context, just as an int * might point to one integer or an array of integers.
Because strings are handy, there's a special syntactical rule for strings literal. A string literal in quotes becomes a const char * (in fact its type is char * for backwards compatibility). So in this sense, C has strings. But all that is happening is that the string is being laid out in the data section of the program, then its address taken.

How do I call char constructor instead of char[] constructor

My school project asks me to re-create the std::string class (with less detail). I'm having a small problem that I have two conflicting(?) constructors.
The problem is when I want to create a String from a single character. Instead of calling
String(char);
it calls
String(char[]);
How can I specify which constructor I would like called?
Update
Wow, now I feel silly. I was calling using char* and not a char so of course it would call the array/pointer version. Thanks for making this painfully obvious to me :)
Supposed you have the following
class String {
public:
String(char);
String(char[]);
};
you'll use
char charvar = 'X';
String s(charvar);
to call the 1st form, and
char strvar[] = "XXXX";
String s(strvar);
to call the second.
Beyond this your question is too unclear/unspecific, to give a concise answer for what you actually want to achieve.
You need to use single quotes to specify a char otherwise it will consider it a char[] with a single character (aside from the termination character)
'a' // char
"a" // char[]

Difference between char , char[] , char * [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I tried to set simple char with empty value without success. The main goal was to compare between std::string single char and pre-defined char
std::string str ="fcvfr";
char c = '' //trying to set empty char here .... but it gives me error
if(c == str[0])
{
//do something
}
This leads me to the question when should I use each of the following types:
char * , char , char[]
char represents a character (allocated on the stack). If you want to set it to empty, use char c = '\0' or char c = (char) 0.
char* cPtr is a pointer to a character. You can allocate an empty character on the heap with char* c = new char('\0').
char c[n] is a character array of size n.
Edit
As people have correctly pointed out below, a char is never empty, in the same sense as a container such as std::vector or std::string can be empty. A char is not fundamentally different to, say, an int, it's just shorter (1 byte as opposed to 2 or 4 or 8). Can an int be empty? Not as such; it can be zero, meaning that all its bits are set to zero in memory, and the same goes for a char. char c = '\0' will be represented as "00000000" on the stack.
A pointer to a char (char* cPtr), on the other hand can be 'empty' in the sense that it can point nowhere, by setting it to NULL. In this case, the pointer itself will exist on the stack and will contain a special sequence of 0/1's that your system interprets as NULL. Once you do cPtr = new char('\0'), a char (i.e. a byte) will be allocated on the heap and set to "00000000", and the value of cPtr on the stack will be changed to point to the address of the new character on the heap.
PS: don't actually do char* cPtr = new char('\0'), use an std::vector<char> or an std::string. Also, you may want to look into smart pointers.

how to define an array of chars in c++

I have this code and it's compiling correctly :
char classfname[512] = "classifiers/cabmodel_VOC05motorbikes.xml";
strcpy(classfname,argv[i]);
but when I tried to define an array contains strings from the same size of the above size
and with your all help it didn't work !
std::vector<std::string> classfname = {
"classifiers/cabmodel_VOC05motorbikes.xml",
"classifiers/cabmodel_interm_nst100_VOC06person01train5_orienthistmod.xml" ,
"classifiers/cabmodel_interm_nst40_VOC06cat01train5_trainval_orienthistmod_nopert_facereg.xml",
"classifiers/cabmodel_interm_nst100_VOC06bicycle01train5_trainval_orienthistmod.xml",
"classifiers/cabmodel_VOC06carside.xml",
"classifiers/cabmodel_interm_nst100_VOC06horse01train5_trainval_orienthistmod_randsel0100.xml"
};
char *classfname[6]={-----}
std::vector<std::string> classfname;
classfname.push_back(",,,");
with the function strcpy(classfname,argv[i]);
I got the error:
Error 2 error C2664: 'strcpy' : cannot convert parameter 1 from 'std::string' to 'char *
Converting string literals to a char* is no longer allowed, since it was never safe. Instead, make an array of const char*. (Although I'm not 100% positive this is the cause of your error, but your code doesn't match your error well, I think you changed something to put it on SO). std::string has a constructor from const char*, so this should work fine.
Also, it's good to note that (const::std string & is not right, so we know you changed stuff when you posted it here. Don't do that, or we can't help you much at all. It should be (const std::string&.
Also, MrC64 notes that you should use RAII instead of raw arrays and pointers. It's easier to use, and harder to mess up.
std::vector<std::string> classfname = {
"classifiers/cabmodel_VOC05motorbikes.xml",
"classifiers/cabmodel_interm_nst100_VOC06person01train5_orienthistmod.xml" ,
"classifiers/cabmodel_interm_nst40_VOC06cat01train5_trainval_orienthistmod_nopert_facereg.xml",
"classifiers/cabmodel_interm_nst100_VOC06bicycle01train5_trainval_orienthistmod.xml",
"classifiers/cabmodel_VOC06carside.xml",
"classifiers/cabmodel_interm_nst100_VOC06horse01train5_trainval_orienthistmod_randsel0100.xml"
};
If your compiler can't handle that syntax yet (many can't), use the code that Mr_C64 suggested.
[EDIT] You have changed your question dramatically to be a completely different question. Generally this is bad, because anyone who comes to this page looking for answers will see that our answers don't match your question anymore. If you have additional questions, you should use the search feature, or make a new question page.
Now your code has a std::vector of std::strings. Treat a std::string like you would an int. Just copy it, or pass it around with no worries. You don't have do use a special function to copy a int, so you don't need a special function to copy a string. Just do std::string newstring = classfname[0]; to get a copy of the string at index 0 in the array classfname.
Your "old" code makes an array of chars initialized to a string literal, and over-rights it with the input from argv[i] The best way to do that code is:
std::string classfname = "classifiers/cabmodel_VOC05motorbikes.xml";
classfname = argv[i];
If you just want to make an array of each of the arguments, that's easy:
int main() {int argc, const char** argv) {
std::vector<std::string> classfname(argv, argv+argc);
One solution is to use const char* like this:
const char *classfname[7]={"classifiers/cabmodel_VOC05motorbikes.xml",
"classifiers/cabmodel_interm_nst100_VOC06person01train5_orienthistmod.xml" ,
"classifiers/cabmodel_interm_nst40_VOC06cat01train5_trainval_orienthistmod_nopert_facereg.xml",
"classifiers/cabmodel_interm_nst100_VOC06bicycle01train5_trainval_orienthistmod.xml",
"classifiers/cabmodel_VOC06carside.xml",
"classifiers/cabmodel_interm_nst100_VOC06horse01train5_trainval_orienthistmod_randsel0100.xml",
};
Also if you want to have a std::vector containing these strings use can initialize it with the following statement:
const std::vector<std::string> classfname_vector(classfname, classfname + 7);
One more thing I noticed is that you declared an array with 7 elements but initialized it only with 6 string literals.
I'd just use std::vector<std::string> instead of a "raw" C array:
#include <string>
#include <vector>
std::vector<std::string> classfname;
classfname.push_back("classifiers/cabmodel_VOC05motorbikes.xml");
classfname.push_back("classifiers/cabmodel_interm_nst100_VOC06person01train5_orienthistmod.xml");
...
std::vector overloads operator[], so your call xmlloadmodel(classfname[i],model); should work.