C++ - How to parse a char* substring into int? [duplicate] - c++

This question already has answers here:
How can I read and parse CSV files in C++?
(39 answers)
Closed 2 years ago.
I am working on a simulate file. The file has many rows with numbers, letters and characters.
Example:
GR123,7894.5444,A,4687.5643,P
GR456,1234.6556,A,9657.5686,P
GR789,2344.3422,A,9786.8465,P
GR987,6522.6354,A,3245.5754,P
I need to take the values before A and P (for the first row, 7894.5444 and 4687.5643).
How can I parse by position this string into an int? Already tried with:
double exampleA = stoi(row.substr(6,9));
double exampleP = stoi(row.substr(18,9));
But it gives me this error: request for member ‘substr’ in ‘row’, which is of non-class type ‘char*’
Also tried:
char exampleA[9];
char exampleP[9];
memcpy(&exampleA, &row[6],sizeof(exampleA));
memcpy(&exampleP, &row[6],sizeof(exampleP));
In order to convert the values after having separated them from the row but the memcpy buffer always brings the value of exampleP with exampleA like:
A : 7894.5444
P : 4687.5643?7894.5444

request for member ‘substr’ in ‘row’, which is of non-class type ‘char*’
Yeah, you can't call substr on a pointer. Perhaps you meant to store these things in a std::string instance?
As to your second attempt, there are multiple big problems with what you wrote:
The buffers you're using are 9 bytes long, but the largest number in your example looks to be 10 bytes (4 + 1 + 4 + 1). You're overflowing your buffer and overwriting random memory in your process. Edit: or you would be if you wrote proper null-terminated strings.
Related to the above, because it sort of hides the problem, don't use memcpy to copy strings. A much better first attempt would be strncpy to copy a substring to a buffer, though you still have to manually null-terminate it.
The reason why the P line shows both entries is that your compiler seems to put exampleA after exampleP on the stack, separated by a guard character, and since you don't null-terminate your strings, trying to display exampleP spills over into exampleA, which out of sheer luck seems to be followed by a null character.

Since the data seems to be in a C string anyway, you might as well use std::strtod which has the advantage of not requiring you to copy the substring:
char* endp;
double exampleA = std::strtod(row+6, &endp);
double exampleP = std::strtod(row+18, &endp);
In both cases, you might want to double check that *endp == ',' and that no conversion error was signalled.
You could use std::strtod even with a std::string, of course. It's often the most efficient solution.
Note that strtod is locale-aware, so this might not work if the input doesn't correspond to your current locale (eg. Files using period fir decimals and commas for field separators while the locale uses comma and semicolon, respectively).
I'm not sure what you mean by converting a floating point number to an integer (truncate? round? multiply by 10,000?). So I didn't address that part of the question.

Related

Is there a way to multiply a string and an integer in C++? [duplicate]

This question already has answers here:
Multiplying a string by an int in C++
(10 answers)
Closed 2 years ago.
In Python, there is a way to multiply a string, for example, "A" * 3 would return "AAA". However, this syntax doesn't work in C++, it just gives me an error, invalid operands of types 'const char [2]' and 'int' to binary 'operator*'. Is there a way to multiply a string like this in C++?
There is no such operator in C++.
But you can write a function that takes a string and a number as argument, and return the repeated string.
std::string also has a constructor that repeats given character a number of times. This may be useful since you used a string of one character as the example.
You can overload an operator
std::string operator*(const std::string& s, unsigned n)
{
... // your code here
}
Not really... Although you can right one yourself. C++ is a very different beast to Python. It's much more low level and It is not as forgiving.
C++ deals with "real" memory (as it were).
You can't really just say "A" * 3 because before the "A" simply used 1 byte of memory if you have 3 "A"'s you need 3 bytes. and since C++'s main benefit is in it's ability to allow the user to author It's memory use, C++ won't just create 3 extra bytes.
You can implement your own version of Python's "A" * 3 by using the overload operator (although you would have to use a class type like string) C++ provides But I wouldn't really recommend this.
I'd suggest just using a std::vector and append the character as many times as you would like.
Also have a think about what you are trying to really do. C++ is all about performance rather than usability. If you are trying to set multiple bytes to a certain value you can use std::memset

understand C++ - "character literal" vs "string literal" [duplicate]

This question already has answers here:
Single quotes vs. double quotes in C or C++
(15 answers)
Closed 4 years ago.
i was reading a textbook that was talking about "character literal" vs "string literal." It said the following:
'A' is stored as 65
"A" is stored as 65 0
char letter;
letter = 'A' // this will work
letter = "A" // this will not work!
the textbooks explanation confused me. It said "because char variables are only large enough to hold one character, you cannot assign string literals to them." Can anyone explain further, its not clicking in my head. Thank you for your time
You should see this:
Single quotes vs. double quotes in C or C++
As everyone has said here, think about arrays.
A character is only one leter or digit or symbol and it is declared by simple quotes. However, when you are declaring with double quotes, you are actually indicating that is about a string or array. Thus, you should declare your variable like an array. For instance:
char letter[] = "A";
Or
char *letter = "A";
If you want a static Array, You could try something like this:
char letter[5] = {'H','E','L','L','O'};
If you want see another point view, you could read this:
http://www.cplusplus.com/doc/tutorial/ntcs/
Hope I was helpful.
What you might be missing is the fact that strings can be of arbitrary length. The compiler places the string somewhere in the program / memory the way you type it, but it needs to know where the string ends! This type of strings is known as zero- or null-terminated. It means simply that the string is the actual string data followed by a single byte with the value 0.
So in the example, 'A' is the character A. In memory, it may immediately be followed by some garbage / unrelated data, but it's fine, because the compiler knows to only ever use that one byte.
"A" is the string A. In memory, it must be followed by a null terminator, otherwise the program could get confused because there might be garbage data immediately after the string.
Think about strings as array of characters, where one element of this array is simply 'character literal'.

What is the advantage of using gets(a) instead of cin.getline(a,20)?

We will have to define an array for storing the string either way.
char[10];
And so suppose I want to store smcck in this array. What is the advantage of using gets(a)? My teacher said that the extra space in the array is wasted when we use cin.getline(a, 20), but that applies for gets(a) too right?
Also just an extra question, what exactly is stored in the empty "boxes"of an array?
gets() is a C function,it does not do bounds checking and is considered dangerous, it has been kept all this years for compatibility and nothing else.
You can check the following link to clear your doubt :
http://www.gidnetwork.com/b-56.html
Don't mix C features with C++, though all the feature of C works in C++ but it is not recommended . If you are working on C++ then you should probably avoid using gets(). use getline() instead.
Well, I don't think gets(a) is bettet because it does not check for the size of the string. If you try to read a long string using it, it may cause an buffer overflow. That means it will use all the 10 spaces you allocated for it and then it will try to use space allocated for another variables or another programs (what is going to make you publication crash).
The cin.getline() receives an int as a parameter with tells it to not read more than the expected number of characters. If you allocate a vector with only 10 positions and read 20 characters it will cause the same problem I told you about gets().
About the strings representation in memory, if you put "smcck" on an array
char v[10];
The word will take the first 5 positions (0 to 4), the position 5 will be taken by a null character (represented by '\0') that will mark the end of the string. Usually, what comes next in the array does not matter and are kept the way it were in the past.the null terminated character is used to mark where the string ends, so you can work it safely.

C++: Format not a string literal and no format arguments [duplicate]

This question already has answers here:
warning: format not a string literal and no format arguments
(3 answers)
Closed 8 years ago.
I've been trying to print a string literal but seems like I'm doing it wrong, since I'm getting a warning on compilation. It's probably due to wrong formatting or my misunderstanding of c_str() function, which I assume should return a string.
parser.y: In function ‘void setVal(int)’:
parser.y:617:41: warning: format not a string literal and no format arguments [-Wformat-security]
Line 617:
sprintf(temp, constStack.top().c_str());
Having those declarations
#include <stack>
const int LENGTH = 15;
char *temp = new char[LENGTH];
stack<string> constStack;
How can I provide a proper formating to string?
Simple - provide a format string:
sprintf(temp, "%s", constStack.top().c_str());
But much, much better:
string temp = constStack.top();
You are telling me in your comment that the problem is not so much the warning as the fact that your code doesn't do what you expect it to.
The solution to this and other, similar problems is to get rid of the strong C influence in your C++ code. Specifically, don't use raw dynamically allocated char arrays or sprintf. Use std::string instead.
In this case, you are using sprintf very incorrectly. Have you ever seen its signature? It goes like this:
sprintf(char *str, char const *format, ...)
str is the output of the operation. format describes what the output should be. The rest are the format arguments, which must by pure convention match what's described in format.
Now this "rest", written as ..., means that you can pass any number of arguments, even zero. And this is why your code even compiles (delivering a nice example for why ... is a dangerous feature, by the way).
In your code, the output string is, possibly incorrectly, your temp string. And the format to describe the output is, almost certainly incorrectly, what happens to sit on top of your stack.
Is this just about assigning one string to another, using sprintf simply because it more or less can do that as a very special case of what its feature set offers? There's no need for such hacks, as C++ has string assignment out of the box with std::string:
std::string temp = constStack.top();
Notice that this also eliminates the need to know the length of the string in advance.
If, for some reason, you really need formatting (but your question doesn't really show any need for it), then learn more about string streams as an alternative solution to format strings.
As the warning indicates it is issued as a result of the -Wformat-security option; you could simply disable the warning by removing the option; but it would be perhaps unwise.
The security issue is perhaps theoretical unless your code is to be widely distributed. Of perhaps more immediate concern is the possibility of your code crashing or behaving abnormally.
The problem is that the string is variable, and may at runtime contain formatting characters that cause it to attempt to read non-existent arguments. If for example the string is received from user input and the user entered "%s" it would attempt to read a string from some somewhere on the stack. That would at best place junk in temp, but worse if the memory read happened not to contain a nul character in the first 15 bytes, it would overrun temp, and corrupt the heap (in this case). Heap corruptions are probably worse than stack corruptions - the latent bug can remain unnoticed in your code for a long time only to start crashing after some unrelated change; and if it does crash, it is unlikely to be in any proximity to the cause.

What is the purpose of buffer = "\0" [duplicate]

This question already has answers here:
What is a null-terminated string?
(7 answers)
Closed 9 years ago.
I remember reading the explanation on the use of this line of code, but I've read so many books on sockets for the past week that I can't find it anymore.
I do remember in the book, they wrote their code using =\0, then said it would be better to have it at 1
I tried searching it, but had no luck, this is a piece of the code I'm reading where it is used
nread = recv(newsock, buffer, 25, 0);
buffer[nread] = '\0';
It turns the received buffer into a NUL-terminated C-string, that you can use with strlen, strcpy, etc.
I assume the code you show is for illustrative purposes only, not production code, because you're not checking the return value of recv, which can be -1. If that happens it will cause memory corruption.
This is the C/C++ null terminator which indicates the end of content in a character array.
http://en.wikipedia.org/wiki/Null-terminated_string
It is to signify that the string ends at that byte. In this case the last one.
\0 is the null character.
So you don't get garbage like "This is my message.aG¤(Ag4h98av¤"G#¤". Just imagine there's a \0 at the end of that string.
When dealing with networking, you usually want to send data like integers, and the most common practice is to send it in binary and not plaintext. An integer may look like "$%\0n" for example. 4 bytes, but the third one is a \0. So you have to take into account that there can be a \0. Therefore you should not store binary representation of data as a string, but rather as a buffer/stringstream.
Of course, maybe you don't want to print out the binary representation of it. But you have to keep it in mind. Maybe you want to print it out, who knows.