In my program, I have a char array (char data[]) from which i have to extract the data and store it in an integer variable(value). To do so, I have used atoi in my program. Problem is that I sometime receive null in the char array(data). If i use atoi on this value, I get the value 0 in integer variable instead of (null)
The real function is quite big and I cannot post the entire code here. From function mentioned below, I hope you guys will get some idea about what I am doing here.
Get_Data(char data[])
{
int value;
value = atoi(p);
}
I recently read that we should use strtol instead of atoi. I tried that too. but I am still getting 0 in variable value.
I want to know which function should i use so that i get (null) in integer variable value?
By null, I mean empty character array here
Please provide solutions specific to the problem. In the above function, if data gets empty char value, how do i make sure that my int variable value also gets empty value and not zero??
atoi return zero for
If the first sequence of non-whitespace characters in str is not a
valid integral number, or if no such sequence exists because either
str is empty or it contains only whitespace characters, no conversion
is performed and zero is returned.
Also you requrement for returning NULL is not possible because you assign those value in int and int can't hold not NULL.
Because atoi tries to read as much as it can.
You should use strtol instead , like this:
char* endptr = NULL
char* myString = "OUPS";
long n = strtol(myString, &endptr, 10);
if (*endptr != '\0') {
// ERROR
}
Read the reference link for more explanation (and example too).
Isn't that good?
There is no Integer value in C++ spelled as null
NULL in an integer form is 0 only.
Related
So I have a function which edits the values, but I cout the values in main to see that it outputs 1309668848 and changes every time I run the program. (this isn't happening in the preprocessor). I have been struggling with this for a while and decided to come here for advice.
Here's the function.
void GetDahInt() {
std::string NewValueS;
getline(std::cin, NewValueS);
NewValue = (int)NewValueS.c_str();
}
You can use
std::stoi( str )
Discards any whitespace characters (as identified by calling isspace()) until the first non-whitespace character is found, then takes as many characters as possible to form a valid base-n (where n=base) integer number representation and converts them to an integer value.
Source :Documentation of stoi
NewValueS.c_str() returns a pointer to array of characters.
You are casting the pointer to int (get the memory address of c_str()).
See: http://www.cplusplus.com/reference/string/string/c_str/
string::c_str
Get C string equivalent
Returns a pointer to an array that contains a null-terminated sequence of characters (i.e., a C-string) representing the current value of the string object.
This array includes the same sequence of characters that make up the value of the string object plus an additional terminating null-character ('\0') at the end.
NewValue = (int)NewValueS.c_str(); cast the address to string, and the address changes every time you execute your code.
You're looking for something like std::stoi (string to int), called like this:
std::string str = ...;
int value = std::stoi(str);
The pros and cons of this option compared to others such as std::stringstream are discussed here:
How to parse a string to an int in C++?
The reason your cast produces a "random" number is that c_str returns a pointer to the start of an array of char.
Casting from a const char* to an int is undefined behavior (these types may not even have the same size), but will likely produce a memory address that depends on where your std::string is allocated.
I got an unsigned char with the value of 1, I need to put this in a string like "1".
But if I try to put this directly into a stringstream it will get the value of char(1) and I need it to be "1".
I know that if I can get this into the function atoi it will return the "1" value.
But I tried to cast it to char and put it in the atoi function, but it throws an exception.
Already tried to put it in a string and them cast c_str() into atoi function, but without success yet.
If someone can help me I'll apreciate.
Simply cast a char to an int before inserting it into the std::stringstream:
ss << static_cast<int>(c);
This will treat the value of the char not as a character but as a numerical value.
I believe you're confusing two functions here.
You wish to convert an integer to a string.
atoi (ascii to integer) however takes a string and parses it into an integer, making "123" into 123.
You are looking for the itoa function here, which has this prototype:
char * itoa ( int value, char * str, int base );
In your case, this would look like this:
char Buf[10];
itoa(123, Buf, 10);
printf("%s", Buf); //Outputs 123
Please remember though, that itoa is not part of the standard, even though it is supported by some compilers. For a more standard-compliant version use:
sprintf(Buf, "%d", 123);
Of course all of this is plain C, but any C++ compiler will work with this all the same.
To convert a numeric value in the range [0,9] to the corresponding character, just add '0' to it. That's guaranteed to work on all systems.
For a program I'm writing based on specifications, a variable is passed in to a function as a string. I need to set that string to a char variable in order to set another variable. How would I go about doing this?
This is it in the header file:
void setDisplayChar(char displayCharToSet);
this is the function that sets it:
void Entity::setElementData(string elementName, string value){
if(elementName == "name"){
setName(value);
}
else if(elementName == "displayChar"){
// char c;
// c = value.c_str();
setDisplayChar('x');//cant get it to convert :(
}
else if(elementName == "property"){
this->properties.push_back(value);
}
}
Thanks for the help in advanced!
You can get a specific character from a string simply by indexing it. For example, the fifth character of str is str[4] (off by one since the first character is str[0]).
Keep in mind you'll run into problems if the string is shorter than your index thinks it is.
c_str(), as you have in your comments, gives you a char* representation (the whole string as a C "string", more correctly a pointer to the first character) rather than a char.
You could equally index that but there's no point in this particular case.
you just need to use value[0] and that returns the first char.
char c = value[0];
Could someone explain why those calls are not returning the same expected result?
unsigned int GetDigit(const string& s, unsigned int pos)
{
// Works as intended
char c = s[pos];
return atoi(&c);
// doesn't give expected results
return atoi(&s[pos]);
return atoi(&static_cast<char>(s[pos]));
return atoi(&char(s[pos]));
}
Remark: I'm not looking for the best way to convert a char to an int.
None of your attempts are correct, including the "works as intended" one (it just happened to work by accident). For starters, atoi() requires a NUL-terminated string, which you are not providing.
How about the following:
unsigned int GetDigit(const string& s, unsigned int pos)
{
return s[pos] - '0';
}
This assumes that you know that s[pos] is a valid decimal digit. If you don't, some error checking is in order.
What you are doing is use a std::string, get one character from its internal representation and feed a pointer to it into atoi, which expects a const char* that points to a NULL-terminated string. A std::string is not guaranteed to store characters so that there is a terminating zero, it's just luck that your C++ implementation seems to do this.
The correct way would be to ask std::string for a zero terminated version of it's contents using s.c_str(), then call atoi using a pointer to it.
Your code contains another problem, you are casting the result of atoi to an unsigned int, while atoi returns a signed int. What if your string is "-123"?
Since int atoi(const char* s) accepts a pointer to a field of characters, your last three uses return a number corresponding to the consecutive digits beginning with &s[pos], e.g. it can give 123 for a string like "123", starting at position 0. Since the data inside a std::string are not required to be null-terminated, the answer can be anything else on some implementation, i.e. undefined behaviour.
Your "working" approach also uses undefined behaviour.
It's different from the other attempts since it copies the value of s[pos]to another location.
It seems to work only as long as the adjacent byte in memory next to character c accidentally happens to be a zero or a non-digit character, which is not guaranteed. So follow the advice given by #aix.
To make it work really you could do the following:
char c[2] = { s[pos], '\0' };
return atoi(c);
if you want to access the data as a C string - use s.c_str(), and then pass it to atoi.
atoi expects a C-style string, std::string is a C++ class with different behavior and characteristics. For starters - it doesn't have to be NULL terminated.
atoi takes pointer to char for it's argument. In the first try when you are using the char c it takes pointer to only one character hence you get the answer you want. However in the other attempts what you get is pointer to a char which has happened to be beginning of a string of chars, therefore I assume what you are getting after atoi in the later attempts is a number converted from the chars in positions pos, pos+1, pos+2 and up to the end of the s string.
If you really want to convert just a single char in the string at the position (as opposed to a substring starting at that position and ending at the end of the string), you can do it these ways:
int GetDigit(const string& s, const size_t& pos) {
return atoi(string(1, s[pos]).c_str());
}
int GetDigit2(const string& s, const size_t& pos) {
const char n[2] = {s[pos], '\0'};
return atoi(n);
}
for example.
I like "reinventing the wheel" for learning purposes, so I'm working on a container class for strings. Will using the NULL character as an array terminator (i.e., the last value in the array will be NULL) cause interference with the null-terminated strings?
I think it would only be an issue if an empty string is added, but I might be missing something.
EDIT: This is in C++.
"" is the empty string in C and C++, not NULL. Note that "" has exactly one element (instead of zero), meaning it is equivalent to {'\0'} as an array of char.
char const *notastring = NULL;
char const *emptystring = "";
emptystring[0] == '\0'; // true
notastring[0] == '\0'; // crashes
No, it won't, because you won't be storing in an array of char, you'll be storing in an array of char*.
char const* strings[] = {
"WTF"
, "Am"
, "I"
, "Using"
, "Char"
, "Arrays?!"
, 0
};
It depends on what kind of string you're storing.
If you're storing C-style strings, which are basically just pointers to character arrays (char*), there's a difference between a NULL pointer value, and an empty string. The former means the pointer is ‘empty’, the latter means the pointer points to an array that contains a single item with character value 0 ('\0'). So the pointer still has a value, and testing it (if (foo[3])) will work as expected.
If what you're storing are C++ standard library strings of type string, then there is no NULL value. That's because there is no pointer, and the string type is treated as a single value. (Whereas a pointer is technically not, but can be seen as a reference.)
I think you are confused. While C-strings are "null terminated", there is no "NULL" character. NULL is a name for a null pointer. The terminator for a C-string is a null character, i.e. a byte with a value of zero. In ASCII, this byte is (somewhat confusingly) named NUL.
Suppose your class contains an array of char that is used to store the string data. You do not need to "mark the end of the array"; the array has a specific size that is set at compile-time. You do need to know how much of that space is actually being used; the null-terminator on the string data accomplishes that for you - but you can get better performance by actually remembering the length. Also, a "string" class with a statically-sized char buffer is not very useful at all, because that buffer size is an upper limit on the length of strings you can have.
So a better string class would contain a pointer of type char*, which points to a dynamically allocated (via new[]) array of char s. Again, it makes no sense to "mark the end of the array", but you will want to remember both the length of the string (i.e. the amount of space being used) and the size of the allocation (i.e. the amount of space that may be used before you have to re-allocate).
When you are copying from std::string, use the iterators begin(), end() and you don't have to worry about the NULL - in reality, the NULL is only present if you call c_str() (in which case the block of memory this points to will have a NULL to terminate the string.) If you want to memcpy use the data() method.
Why don't you follow the pattern used by vector - store the number of elements within your container class, then you know always how many values there are in it:
vector<string> myVector;
size_t elements(myVector.size());
Instantiating a string with x where const char* x = 0; can be problematic. See this code in Visual C++ STL that gets called when you do this:
_Myt& assign(const _Elem *_Ptr)
{ // assign [_Ptr, <null>)
_DEBUG_POINTER(_Ptr);
return (assign(_Ptr, _Traits::length(_Ptr)));
}
static size_t __CLRCALL_OR_CDECL length(const _Elem *_First)
{ // find length of null-terminated string
return (_CSTD strlen(_First));
}
#include "Maxmp_crafts_fine_wheels.h"
MaxpmContaner maxpm;
maxpm.add("Hello");
maxpm.add(""); // uh oh, adding an empty string; should I worry?
maxpm.add(0);
At this point, as a user of MaxpmContainer who had not read your documentation, I would expect the following:
strcmp(maxpm[0],"Hello") == 0;
*maxpm[1] == 0;
maxpm[2] == 0;
Interference between the zero terminator at position two and the empty string at position one is avoided by means of the "interpret this as a memory address" operator *. Position one will not be zero; it will be an integer, which if you interpret it as a memory address, will turn out to be zero. Position two will be zero, which, if you interpret it as a memory address, will turn out to be an abrupt disorderly exit from your program.