C tokenize polynomial coefficients - c++

I'm trying to put the coefficients of polynomials from a char array into an int array
I have this:
char string[] = "-4x^0 + x^1 + 4x^3 - 3x^4";
and can tokenize it by the space into
-4x^0
x^1
4x^3
3x^4
So I am trying to get: -4, 1, 4, 3 into an int array
int *coefficient;
coefficient = new int[counter];
p = strtok(copy, " +");
int a;
while (p)
{
int z = 0;
while (p[z] != 'x')
z++;
char temp[z];
strncpy(temp[z], p, z);
coefficient[a] = atoi(temp);
p = strtok(NULL, " +");
a++;
}
However, Im getting an error that I cant convert a char* into a char
on strncpy(temp[z], p, z);
error: invalid conversion from ‘char’ to ‘char*’
error: initializing argument 1 of ‘char* strncpy(char*, const char*, size_t)’
What would be the best way to do this?

This:
strncpy(temp[z], p, z);
Needs to be:
strncpy(temp, p, z);
But remember that strncpy doesn't always null-terminate the string.
Also, z will be the length of the coefficient, but you need an extra byte in the buffer for the null terminator.
Update:
examining your link, I still see several serious problems:
You can't use "-" in strtok because it will pick up the one in "-4x" as well as the ones you want. I think you should split on spaces only and handle the +/- operators as tokens.
The strncpy function leaves the string un-terminated, which may cause atoi to crash or give the wrong value randomly. One idiomatic form is to write the terminator manually, e.g., temp[z] = '\0'.
The reason you're not getting any output values is that coefficient[a] = is writing to some random memory because a is uninitialized.

You're passing a char to strncpy:
strncpy(temp[z], p, z);
The first argument should be a char* pointer, not a single char. What you probably mean to do is:
strncpy(temp, p, z);

The other guys are correct about strncpy()'ing into temp rather than temp[z].
I'm going to suggest that you also want to capture the exponents on your free variable. I observe an implicit "0x^2" term that you appear to be neglecting. If your next step is to evaluate your polynomial for various values of x (or, worse, run a solver on it), you will need to know those powers.

This kind of a solution can be made easily enough but to make it proof against extra white space, missing white space and broad enough to handle multiple operators and variable names this kind of strategy increasingly complex and difficult (Especially if you need to have meaningful error messages if the parse fails).
Seems to me it would be easier to implement a bullet-proof solution using boost.regex (or even boost.spirit if the overall task requires order of operations to be analysed) which can easily handle these kind of syntaxes with a large degree of tolerance.

Related

Why do I have to make a 2d array for this

I was solving a question online on strings where we had to perform run-length encoding on a given string, I wrote this function to achieve the answer
using namespace std;
string runLengthEncoding(string str) {
vector <char> encString;
int runLength = 1;
for(int i = 1; i < str.length(); i++)
{
if(str[i - 1] != str[i] || runLength == 9)
{
encString.push_back(to_string(runLength)[0]);
encString.push_back(str[i - 1]);
runLength = 0;
}
runLength++;
}
encString.push_back(to_string(runLength)[0]);
encString.push_back(str[str.size() - 1]);
string encodedString(encString.begin(), encString.end());
return encodedString;
}
Here I was getting a very long error on this particular line in the for loop and outside it when I wrote:
encString.push_back(to_string(runLength));
which I later found out should be:
encString.push_back(to_string(runLength)[0]);
instead
I don't quite understand why I have to insert it as a 2D element(I don't know if that is the right way to say it, forgive me I am a beginner in this) when I am just trying to insert the integer...
In stupid terms - why do I gotta add [0] in this?
std::to_string() returns a std::string. That's what it does, if you check your C++ textbook for a description of this C++ library function that's what you will read there.
encString.push_back( /* something */ )
Because encString is a std::vector<char>, it logically follows that the only thing can be push_back() into it is a char. Just a single char. C++ does not allow you to pass an entire std::string to a function that takes a single char parameter. C++ does not work this way, C++ allows only certain, specific conversions betweens different types, and this isn't one of them.
And that's why encString.push_back(to_string(runLength)); does not work. The [0] operator returns the first char from the returned std::string. What a lucky coincidence! You get a char from that, the push_back() expects a single char value, and everyone lives happily ever after.
Also, it is important to note that you do not, do not "gotta add [0]". You could use [1], if you have to add the 2nd character from the string, or any other character from the string, in the same manner. This explains the compilation error. Whether [0] is the right solution, or not, is something that you'll need to figure out separately. You wanted to know why this does not compile without the [0], and that's the answer: to_string() returns a std::string put you must push_back() a single char value, and using [0] makes it happen. Whether it's the right char, or not, that's a completely different question.

C++ getting length of char array using a second function

I'm trying to get the length of a character array in a second function. I've looked at a few questions on here (1 2) but they don't answer my particular question (although I'm sure something does, I just can't find it). My code is below, but I get the error "invalid conversion from 'char' to 'const char*'". I don't know how to convert my array to what is needed.
#include <cstring>
#include <iostream>
int ValidInput(char, char);
int main() {
char user_input; // user input character
char character_array[26];
int valid_guess;
valid_guess = ValidGuess(user_input, character_array);
// another function to do stuff with valid_guess output
return 0;
}
int ValidGuess (char user_guess, char previous_guesses) {
for (int index = 0; index < strlen(previous_guesses); index++) {
if (user_guess == previous_guesses[index]) {
return 0; // invalid guess
}
}
return 1; // valid guess, reaches this if for loop is complete
}
Based on what I've done so far, I feel like I'm going to have a problem with previous_guesses[index] as well.
char user_input;
defines a single character
char character_array[26];
defines an array of 26 characters.
valid_guess = ValidGuess(user_input, character_array);
calls the function
int ValidGuess (char user_guess, char previous_guesses)
where char user_guess accepts a single character, lining up correctly with the user_input argument, and char previous_guesses accepts a single character, not the 26 characters of character_array. previous_guesses needs a different type to accommodate character_array. This be the cause of the reported error.
Where this gets tricky is character_array will decay to a pointer, so
int ValidGuess (char user_guess, char previous_guesses)
could be changed to
int ValidGuess (char user_guess, char * previous_guesses)
or
int ValidGuess (char user_guess, char previous_guesses[])
both ultimately mean the same thing.
Now for where things get REALLY tricky. When an array decays to a pointer it loses how big it is. The asker has gotten around this problem, kudos, with strlen which computes the length, but this needs a bit of extra help. strlen zips through an array, counting until it finds a null terminator, and there are no signs of character_array being null terminated. This is bad. Without knowing where to stop strlen will probably keep going1. A quick solution to this is go back up to the definition of character_array and change it to
char character_array[26] = {};
to force all of the slots in the array to 0, which just happens to be the null character.
That gets the program back on its feet, but it could be better. Every call to strlen may recount (compilers are smart and could compute once per loop and store the value if it can prove the contents won't change) the characters in the string, but this is still at least one scan through every entry in character_array to see if it's null when what you really want to do is scan for user_input. Basically the program looks at every item in the array twice.
Instead, look for both the null terminator and user_input in the same loop.
int index = 0;
while (previous_guesses[index] != '\0' ) {
if (user_guess == previous_guesses[index]) {
return 0; // prefer returning false here. The intent is clearer
}
index++;
}
You can also wow your friends by using pointers and eliminating the need for the index variable.
while (*previous_guesses != '\0' ) {
if (user_guess == *previous_guesses) {
return false;
}
previous_guesses++;
}
The compiler knows and uses this trick too, so use the one that's easier for you to understand.
For 26 entries it probably doesn't matter, but if you really want to get fancy, or have a lot more than 26 possibilities, use a std::set or a std::unordered_set. They allow only one of an item and have much faster look-up than scanning a list one by one, so long as the list is large enough to get over the added complexity of a set and take advantage of its smarter logic. ValidGuess is replaced with something like
if (used.find(user_input) != used.end())
Side note: Don't forget to make the user read a value into user_input before the program uses it. I've also left out how to store the previous inputs because the question does as well.
1 I say probably because the Standard doesn't say what to do. This is called Undefined Behaviour. C++ is littered with the stuff. Undefined Behaviour can do anything -- work, not work, visibly not work, look like it works until it doesn't, melt your computer, anything -- but what it usually does is the easiest and fastest thing. In this case that's just keep going until the program crashes or finds a null.

How to create a function that removes all of a selected character in a C-string?

I want to make a function that removes all the characters of ch in a c-string.
But I keep getting an access violation error.
Unhandled exception at 0x000f17ba in testassignments.exe: 0xC0000005: Access violation writing location 0x000f787e.
void removeAll(char* &s, const char ch)
{
int len=strlen(s);
int i,j;
for(i = 0; i < len; i++)
{
if(s[i] == ch)
{
for(j = i; j < len; j++)
{
s[j] = s[j + 1];
}
len--;
i--;
}
}
return;
}
I expected the c-string to not contain the character "ch", but instead, I get an access violation error.
In the debug I got the error on the line:
s[j] = s[j + 1];
I tried to modify the function but I keep getting this error.
Edit--
Sample inputs:
s="abmas$sachus#settes";
ch='e' Output->abmas$sachus#settes, becomes abmas$sachus#stts
ch='t' Output-> abmas$sachus#stts, becomes abmas$sachus#ss.
Instead of producing those outputs, I get the access violation error.
Edit 2:
If its any help, I am using Microsoft Visual C++ 2010 Express.
Apart from the inefficiency of your function shifting the entire remainder of the string whenever encountering a single character to remove, there's actually not much wrong with it.
In the comments, people have assumed that you are reading off the end of the string with s[j+1], but that is untrue. They are forgetting that s[len] is completely valid because that is the string's null-terminator character.
So I'm using my crystal ball now, and I believe that the error is because you're actually running this on a string literal.
// This is NOT okay!
char* str = "abmas$sachus#settes";
removeAll(str, 'e');
This code above is (sort of) not legal. The string literal "abmas$sachus#settes" should not be stored as a non-const char*. But for backward compatibility with C where this is allowed (provided you don't attempt to modify the string) this is generally issued as a compiler warning instead of an error.
However, you are really not allowed to modify the string. And your program is crashing the moment you try.
If you were to use the correct approach with a char array (which you can modify), then you have a different problem:
// This will result in a compiler error
char str[] = "abmas$sachus#settes";
removeAll(str, 'e');
Results in
error: invalid initialization of non-const reference of type ‘char*&’ from an rvalue of type ‘char*’
So why is that? Well, your function takes a char*& type that forces the caller to use pointers. It's making a contract that states "I can modify your pointer if I want to", even if it never does.
There are two ways you can fix that error:
The TERRIBLE PLEASE DON'T DO THIS way:
// This compiles and works but it's not cool!
char str[] = "abmas$sachus#settes";
char *pstr = str;
removeAll(pstr, 'e');
The reason I say this is bad is because it sets a dangerous precedent. If the function actually did modify the pointer in a future "optimization", then you might break some code without realizing it.
Imagine that you want to output the string with characters removed later, but the first character was removed and you function decided to modify the pointer to start at the second character instead. Now if you output str, you'll get a different result from using pstr.
And this example is only assuming that you're storing the string in an array. Imagine if you actually allocated a pointer like this:
char *str = new char[strlen("abmas$sachus#settes") + 1];
strcpy(str, "abmas$sachus#settes");
removeAll(str, 'e');
Then if removeAll changes the pointer, you're going to have a BAD time when you later clean up this memory with:
delete[] str; //<-- BOOM!!!
The I ACKNOWLEDGE MY FUNCTION DEFINITION IS BROKEN way:
Real simply, your function definition should take a pointer, not a pointer reference:
void removeAll(char* s, const char ch)
This means you can call it on any modifiable block of memory, including an array. And you can be comforted by the fact that the caller's pointer will never be modified.
Now, the following will work:
// This is now 100% legit!
char str[] = "abmas$sachus#settes";
removeAll(str, 'e');
Now that my free crystal-ball reading is complete, and your problem has gone away, let's address the elephant in the room:
Your code is needlessly inefficient!
You do not need to do the first pass over the string (with strlen) to calculate its length
The inner loop effectively gives your algorithm a worst-case time complexity of O(N^2).
The little tricks modifying len and, worse than that, the loop variable i make your code more complex to read.
What if you could avoid all of these undesirable things!? Well, you can!
Think about what you're doing when removing characters. Essentially, the moment you have removed one character, then you need to start shuffling future characters to the left. But you do not need to shuffle one at a time. If, after some more characters you encounter a second character to remove, then you simply shunt future characters further to the left.
What I'm trying to say is that each character only needs to move once at most.
There is already an answer demonstrating this using pointers, but it comes with no explanation and you are also a beginner, so let's use indices because you understand those.
The first thing to do is get rid of strlen. Remember, your string is null-terminated. All strlen does is search through characters until it finds the null byte (otherwise known as 0 or '\0')...
[Note that real implementations of strlen are super smart (i.e. much more efficient than searching single characters at a time)... but of course, no call to strlen is faster]
All you need is your loop to look for the NULL terminator, like this:
for(i = 0; s[i] != '\0'; i++)
Okay, and now to ditch the inner loop, you just need to know where to stick each new character. How about just keeping a variable new_size in which you are going to count up how long the final string is.
void removeAll(char* s, char ch)
{
int new_size = 0;
for(int i = 0; s[i] != '\0'; i++)
{
if(s[i] != ch)
{
s[new_size] = s[i];
new_size++;
}
}
// You must also null-terminate the string
s[new_size] = '\0';
}
If you look at this for a while, you may notice that it might do pointless "copies". That is, if i == new_size there is no point in copying characters. So, you can add that test if you want. I will say that it's likely to make little performance difference, and potentially reduce performance because of additional branching.
But I'll leave that as an exercise. And if you want to dream about really fast code and just how crazy it gets, then go and look at the source code for strlen in glibc. Prepare to have your mind blown.
You can make the logic simpler and more efficient by writing the function like this:
void removeAll(char * s, const char charToRemove)
{
const char * readPtr = s;
char * writePtr = s;
while (*readPtr) {
if (*readPtr != charToRemove) {
*writePtr++ = *readPtr;
}
readPtr++;
}
*writePtr = '\0';
}

Usage of strtol on std::string

I recently migrated from C to C++, and there's a little confusion about strings. Strings just aren't what they used to be any more, as in, not just char arrays with a terminating '\0'.
I haven't found a real answer to this question, so how far can you treat the std::string class like C-Strings?
For example: If I know there's a number somewhere in a string, let the string be ireallylike314, in C I could use strtol(string + 10, NULL, 10) to just get that number.
And, if this doesn't work, is there a way to use std::string like C-strings?
Use c_str().
strtol(string.c_str() + 10, NULL, 10);
If you want to get C-style string from std::string, then as mentioned use c_str() method. But another solution to this specific problem would be just using stol instead of strtol.
While stol doesn't (in itself) support what you want, I think I'd use it in conjunction with substr to get the required result:
std::string in = "ireallylike314";
// extract number and print it out multiplied by 2 to show we got a number
std::cout << 2 * stol(in.substr(11));
Result:
628
This has both good and bad points though. On the bad side, it creates a whole new string object to hold the digits out of the input string. On the good side, it gives a little more control over the number of digits to convert, so if (for example) you only wanted to convert the first two digits from the string (even if, as in this case, they're followed by more digits) you can do that pretty easily too:
std::cout << 2 * stol(in.substr(11, 2));
Result:
62
In quite a few cases, the degree to which this is likely to be practical for you will depend heavily upon whether your implementation includes the short string optimization. If it does, creating a (small) string is often cheap enough to make this perfectly reasonable. If it doesn't, the heap allocation to create the temporary string object as the return value from substr may be a higher price than you want to pay.
The C-like way:
long n = std::strtol( string.c_str() + offset, nullptr, 10 );
// sets ERRNO on error and returns value by saturating arithmetic.
The Java-ish way:
long n = std::stol( string.substr( offset, std::string::npos ) );
// exception (no return value) and perhaps ERRNO is set on error.
The streams way:
long n = 0;
std::istringstream( string ).ignore( offset ) >> n;
// n is unmodified on error
The locales way:
long n = 0;
std::ios_base fmt; // Use default formatting: base-10 only.
std::ios::iostate err = {};
std::num_get< char, std::string::iterator >()
.get( string.begin() + offset, string.end(), fmt, err, n );
// err is set to std::ios::failbit on error
This is maybe beyond the scope of the question but since you are migrating to C++ and you seem confused about std::string, you'll likely find the following useful.
The point of having std::string is not to use it like C-Strings (ofc you can do it, like the previous answers showed). You can take a lot more advantages of std::string capabilities. For example it is a C++ container, there are functions to get substrings, to compare strings, etc ...
String manipultions are generally a lot easier with std::string rather than C-Strings.
See for example http://www.cplusplus.com/reference/string/string/ for its capabilities.
Strings just aren't what they used to be any more, as in, not just
char arrays with a terminating '\0'.
You are wrong. In C++ strings are defined the same way. In both languages strings are defined like
A string is a contiguous sequence of characters terminated by and
including the first null character.
You mix strings with class std::string (or std::basic_string) that are not the same.
For example: If I know there's a number somewhere in a string, let the
string be ireallylike314, in C I could use strtol(string[10], NULL,
10) to just get that number
You are mistaken. The valid function call will look like
strtol( &string[11], NULL, 10)
or
strtol( string + 11, NULL, 10)
The same function you can call for an object of class std::string using member function c_str() or (starting from C++ 2011) data()
For example
std::string s( "ireallylike314" );
auto x = std::strtol( s.c_str() + 11, NULL, 10 );
or
auto x = std::strtol( s.data() + 11, NULL, 10 );

Read equation from text

Hello I am making a program that uses linked lists, stack, and queues to convert infix to postfix and solve the equation. I have made a Push, Pull, etc, for the stack and queue linked list. However the problem that I am having is converting between char and float.
When I read in from the text file, I convert the equation into a string, simple equation like 2+3/(5+1). My push function takes in a char and the pull returns a char. What I can't figure out what to do first is how to convert these strings to char/floats. I wrote this test code to see if typeid would distinguish the char and int.
int i, j;
for(i=0; i<lines; i++){
j = 0;
while(readIn[i][j] != '\0'){
cout << typeid(readIn[i][j]).name();
j++;
}
cout << endl;
}
However my result looks like this:
ccccccccccccccc
ccccccccccccccccccccc
ccccccccc
So it's interpreting every character in the string as a char.
And my second question involves the pull function. In the push function, once I can get the char to float conversion correctly, I did a function overload, one with char and the other with a float. Exact same code, just stores the data into a separate part of the structure. However in the pull function, how can I pull either the char or float? I need one pull function to return a char and the other a float, but you can't have 2 functions with the same argument and different returns, I am a little lost.
I really appreciate any help!!
I don't know, whether i understand your question correctly. You simply want to know, what a char in your string represents (digit, letter, points, ...)?
In this case, I would use the C-functions
isalpha(c); // != 0, if c is a letter
isdigit(c); // != 0, if c is a digit
isspace(c); // != 0, if c is space, tab, ...