unsigned short n = 0;
while (!in.eof())
{
in >> opString; //Read in string from file
//Read the string from file character by character
for (int i = 0; i < opString.size(); i++)
{
if (!op1b) //If we do not yet know our first operand (op1b = false, b stands for bool, clever naming eh?)
{ //Check if our next item is an operator. If it is...
if (!(opString[i] == '+' || opString[i] == '-' || opString[i] == '*' || opString[i] == '/' || opString[i] == '$'))
op1[i] = opString[i];
else //We finally know it since when we hit an symbol, our first number is known; do not repeat this if block
op1b = true;
n++;
}
if (op1b && !operb) //If we know our first operand but not our operator...
{
oper = opString[i]; //Find out what our operator is. Now we know it (operb = true)
operb = true;
i++; //We increment i because if we did not we'd double dip on the if statement below and wind up
} // with an operator tacked onto the beginning of the second operand
if (op1b && operb) //If we know our first operand and the operation, let's find operand #2
{
if (opString[i] == '=')
break;
else
{
op2[i-n] = opString[i];
j++;
}
}
}
cout << "Op 1: " << op1.c_str() << endl << "Oper: " << oper.c_str() << endl << "Op 2: " << op2.c_str() << endl;
}
return 0;
}
What I have here is (the beginning of) a program that is meant to read in strings from a text file to add hexadecimal operands together. The strings have the form of "op1OperatorOp2=" (minus the quotation marks). I am just starting. I am trying to take out op1, op2, and the operator (all strings) out of that by reading the string from the file (opString) character by character (as indicated by i in the for loop). The while loop just checks that it's not end of file for the fstream variable. op1b and operb are bool values that help determine when we 'know' what our first operand and operator are (and then when we can figure out operator number 2).
However, when I extract op2 from the string, my op1 gets replaced with the value of op2, even when I only say op2[whatever] = opString[i] where i is long past where op1 would even be.
Example: if the string coming in from the file is "3+2=", op1 should get 3, oper should get +, and op2 should get 2. However, op2 always ends up being the same as op1 at the end of the loop. Thus, instead of op1 = 3, oper = +, op2 = 2, I end up with op1 = 2, oper = +, op2 = 2.
Is there some undocumented C++ feature I am missing? I cannot figure out why this occurs. Is it because I am in a loop? Should I break up my loop? I do not see why that should make a difference, however. Thanks.
Next time post complete code (with all declration). op1 and op2 are std::string? You try to write characters in op1 and op2 but you haven't allocated any space, i.e. you should either op1.resize(SOME_SIZE) before the loop or use std::string::push_back to append chars to the operands.
Related
I know there are already answered questions about it, but I have read most of them and still couldn't solve my problem.
I have a program that will read notes, keep them in a list and give options to the user to delete, change, or select a specific note.
I'm using this struct:
struct List {
char title [101];
char text [501];
int cont; //code of the note.
struct List* next;
};typedef List list;
I'm stuck at the point of selection, if the user types a * it must return all notes, and if the user type a number it must return only the corresponding note.
So far i just have this:
List* select (List *l, int v) {
List *p = l;
for (p = l; p != NULL; p = p -> next){
if( p -> cont == v){
cout << "\nTitle: " << p -> title << "\n";
cout << "Text: " << p -> text << "\n";
cout << "Code: " << p -> cont << "\n" << "\n";
}
}
how can I read a symbol in char and transform to int, to compare it with the code of the note.
sorry if i write something wrong, i'm brazilian and i have none practice for writing.
EDIT:
Thank you so much guys, it realy realy helped me a lot and now i get to finish my work! :D
Try this:
Get the input as a string
string str;
cin >> str;
If the string is a *
if (str == "*")
{
// print out all notes
}
Else, attempt too convert string into number with strtol. Strtol gives better error checking than atol because it tells you whether the whole string was converted and if not, where so you can go look.
char * endp;
long code;
code = strtol(str.c_str(), // the string converted to characters
&endp, // where in the string the number ended.
10); // the base of the number, base 10 in this case for
// decimal. 16 if you want to input in hex.
// Unlikely in this case.
if (*endp == '\0') // If the number didn't end didn't end at the end
// of the string, the number is invalid
{
// print note for code
}
A quick note on strtol(str.c_str(), &endp, 10); and testing endp.
This doesn't actually work. endp winds up pointing at a memory location that may not be valid by the time you get to check. Really, you need to get the char array out of the string and into something for which you can guarantee the scope.
The above warning is incorrect based on old, or faulty data. Thank you #TamásSzabó. Makes future code writing a wee bit simpler.
No std::string version is almost the same:
char str[64]; // allocate storage for a big number.
cin.get(str, sizeof(str)); // read up to size of string -1 and null terminate
if ((str[0] == '*') && (str[1] == '\0'))
// first character in string is '*' and there
// is no second character
{
// print out all notes
}
else
{
char * endp;
long code;
code = strtol(str,
&endp,
10);
if (*endp == '\0') //this time endp will be valid
{
// print note for code
}
}
If you really need to only char and int types, you could try this:
char buf[10]; // Assuming that you won't have more than 10 characters in your number
char *endp;
cin >> buf; // This may cause you problems if the input string is more than 9 characters long!
From here on you can use user4581301's answer:
if ( (buf[0] == '*') && (buf[1] == '\0') )
{
// Print all your notes here
}
code = strtol(but, // the string converted to characters
&endp, // where in the string the number ended.
10); // the base of the number, base 10 in this case for
// decimal. 16 if you want to input in hex.
// Unlikely in this case.
if (*endp == '\0') // If the number didn't end didn't end at the end
// of the string, the number is invalid
{
// print note for code
}
I have an assignment where I need to create a postfix calculator. I'm running into some difficulties that previous questions regarding the subject on SO didn't cover adequately.
Here's an example of input I want to handle:
12 6 +
2 *
[Carriage return]
Result: 36
The description of the assignment:
The arithmetical expressions we normally use are infix expressions, meaning that the operator appears between its two operands, as in "4 + 5". In postfix expressions, the operator appears after its operands, as in "4 5 +". Here is a slightly more complex postfix expression: "25 12 7 - 2 * /". The equivalent infix expression is: "25 / ((12 - 7) * 2)". The result of that expression should be 2.5 (don't use integer division). Postfix expressions don't require parentheses.
Write a program that uses a stack to evaluate postfix expressions.
Each input expression should be entered on its own line, and the
program should terminate when the user enters a blank line. The only
symbols in an expression will be +, -, *, /, digits and spaces.
Hint: Read a postfix expression from left to right. When you read a
number, push it on the stack. When you read an operand, pop the top
two numbers off the stack, apply the operator to them, and push the
result on top of the stack. At the end, the result of the expression
should be the only number on the stack.
Here's my code so far:
#include <list> /* Linked Lists */
#include <stack> /* Stacks */
#include <iostream> /* cout cin */
int main() {
std::stack< double, std::list<double> > postfixStack;
std::string input;
std::cout << "Enter a postfix expression: ";
std::getline(std::cin, input);
while (input != "") {
std::cout << "Input expression: " << input << std::endl;
for (int i = 0; i<input.length()-1; i++) {
if (input.compare(i, 1, " ")) { // should ignore spaces, but doesn't
std::cout << "Skipping element " << i << " \n";
} else if (static_cast<int>(input[i]) == input[i]) { // push numbers onto the stack
postfixStack.push(static_cast<double>(input[i]));
std::cout << "Pushing " << input[i] << " onto the stack.\n";
} else if (input.compare(i, 1, "+")) { // pop two numbers off the stack (1), apply the operator to them (2), and push that onto the stack (3)
double operand1 = postfixStack.top();
postfixStack.pop();
double operand2 = postfixStack.top();
postfixStack.pop();
postfixStack.push(operand1 + operand2);
std::cout << "Adding " << operand1 << " and " << operand2 << std::endl;
}
}
std::getline(std::cin, input);
}
if (!postfixStack.empty()) {
std::cout << "Result of expression: " << postfixStack.top() << std::endl;
} else {
std::cout << "It appears that you did not enter an expression to evaluate.\n";
}
return 0;
}
Syntax highlighting and line numbers on Gist.
Where I'm struggling:
My while loop should allow more than one line of input per the spec. I was originally using cin instead of getline, but that presented the opposite problem: unlimited lines to enter anything whatsoever, even when checking for /r and the empty string.
I'm trying to skip over spaces in my loop, but instead my conditional appears to skip over anything that isn't a space.
Checking string subscripts means that I can only use numbers with one digit, which definitely isn't what I want. When I encounter a number: I think I could check the next element, if that's a number then I could concatenate them and bump up the loop counter. In theory, at least. I'd like to get basic functionality before I work on that.
My while loop should allow more than one line of input per the spec.
You've already found getline. You can simply use that to read whole lines. That approach you've taken looks fine.
I'm trying to skip over spaces in my loop, but instead my conditional appears to skip over anything that isn't a space.
That's right. You're checking the result of string::compare, but the result isn't a boolean, and non-zero doesn't mean the strings are equal, it means they aren't equal.
The way you've performed the comparison is uncommon, BTW, and more usual would be to simply compare the character to ' ', or to use isspace or maybe isblank.
Checking string subscripts means that I can only use numbers with one digit, which definitely isn't what I want.
Right. When you see a digit, you can enter a nested loop to read all subsequent digits. The base case, a one-digit string, is trivially converted to a number. (But just a tad less trivial than you think, see the note below.) And if you know how to determine the value of an N-digit string (let's say ABC), you can determine the value of an N+1-digit string (let's say ABCD) by multiplying by 10, and adding the value of the next digit.
Note: static_cast<int>(input[i]) == input[i] is always true. This doesn't mean what you think it means. Use your debugger to inspect the value of static_cast<int>(input[i]) for some characters, and try to understand what this cast is doing. When you understand what this does, think about another check you could do instead, and how you can use that, after checking a character is a digit, to determine the numeric value of that digit.
For an assignment, we have to do a large program that manipulates C++ strings in a variety of ways. Most of it is working, but this particular function is messing with me. I am trying to cycle through a string and remove all non-alphanumeric (tab, blank newline) characters before the first alphanumeric one occurs, and then end the string when the first non-alphanumeric character appears again. For example, " bob jon" would be saved as "bob". Something is going wrong where every string is considered empty. Most peers have been telling be that
*(point++) = *marker;
can't be done and that I should change this before trying anything else...is this a way to increment the iterator while assigning its value to another iterator's value? Is it that the problem or something else?
void clean_entry( const string& j, string& k )
{
string::iterator point = k.begin();
bool checker = false;
//cycle through the constant string and check for numbers and letters
for(string::const_iterator marker = j.cbegin(); marker!=j.cend(); ++marker)
{
if( isalnum(*marker) == true )
{
*(point++) = *marker; //copy to the new k string if alphanum, and increment iterator
cout << "I found a real letter!" << endl; //debugging
checker = true;
}
else if( checker == true )
break;
}
cout << "So far we have " << k << endl; //debugging
if (checker == false )
k = "(empty word)";
cout << "The new string is " << k << " apparently." << endl; //debugging
}
isalnum doesn't return bool. It returns int. The guarantee is that it returns nonzero if the character is alphanumeric and zero otherwise.This means that you can't compare the return value to true, as that comparison causes true to be converted to int, yielding 1, before the comparison is done.. if(isalnum(*marker)) is both idiomatic and actually works.Similarly, if( checker == true ) is bloated and should be if(checker), and if (checker == false ) should be if(!checker).
Your interface is questionable, since the caller must ensure that k's size is large enough to accommodate the resulting string. Better to clear k and then use push_back() or similar rather than an iterator.
On the assumption that k.size() is sufficiently large, there's nothing wrong with *(point++) = *marker;.
I'm trying to find the amount of letters of the alphabet from a file I have. I can get the first letter A to give me the correct number, but when the for loop goes through it only gives me 0 for the rest of the letters. I feel like it has to do with my .get() not starting at the beginning of the file again. What do I need to do to fix this? Thanks!
ifstream openFile("data.txt");
int numberOfLetters(0);
char letter;
for (int i = 0; i < 26; i++)
{
numberOfLetters = 0;
openFile.clear();
while (!openFile.eof())
{
openFile.get(letter);
if (letter == char(i + 97) || letter == char(i + 65))
{
numberOfLetters++;
}
}
cout << numberOfLetters;
}
The problem is your outer loop: It looks like you want to use this loop to check if the characters taken from the file are equal to certain characters from a certain range. If this is the case, performing the input within the loop is not the way to go.
On the first iteration of the loop, the file will be read completely such that by the second iteration openFile.get(letter) won't extract anything into letter, leaving it with its previous value, same for the rest of the outer iterations. It must be that the last value previous had didn't pass the if() statement test, so numberOfLetter didn't increment.
The solution is to change the way you check if the character is alphabetic. Characters are represented using the ASCII format, which are just integers mapped to characters. Since characters are really integers, you can use arithmetic operations on them. Moreover, characters are represented alphabetically in ASCII, so you can simply compare their values to see if they are in the range of alphabetic characters:
while (openFile.get(letter))
{
if (('a' <= letter && letter <= 'z') || ('A' <= letter && letter <= 'Z'))
{
numberOfLetters++;
}
}
cout << numberOfLetters;
Fortunately the standard library provides a function std::isalpha() that does this for you.
...
if (std::isalpha(letter))
{
numberOfLeters++;
}
...
Based on your comment, checking if a character is alphabetic is not enough. Instead, use a data structure like std::map in order to keep a total count of the number of certain characters:
#include <map>
std:map<char, std::size_t> alpha_count;
while (openFile.get(letter))
{
if (std::isalpha(letter))
alpha_count[letter]++;
}
Now to print how many specific characters there are, loop through the map and print the character's count():
for (auto&& c : alpha_count)
{
std::cout << "# of " << c << ": " << alpha_count.count(c) << '\n';
}
>The character 'b' is char('a'+1),'c' is char('a'+2),etc. Use a loop to write out a table of characters with their corresponding integer values.
I cannot finish this exercise because of this error.
error: lvalue required as increment operand
for(char a='a'; a<24; ++a)
{
cout<<char('a'++);
}
The loop body will never execute with the controlling expression a < 24 because you have initialized variable a with character a and all printable characters are not less than ASCII value 32.
Try this:
for(char a='a'; a < 'a' + 24; ++a)
{
cout << a;
}
I think you would be less confused if you named your variable letter instead of a, because it only represents the letter 'a' at the very beginning.
for(char letter='a'; letter<24; ++letter)
{
cout<<char('a'++);
}
I'm going to assume you actually want to print out the entire alphabet, not just the first 24 letters.
It looks from here like you tried to do a mix of two possible approaches. In the first approach, you increment a char from a to z with each iteration of the for loop and print it out each time. In the second approach, you increment some offset from 0 to 25 and print out 'a' + offset.
You mix these two approaches up in the first line. You're starting the loop with letter set to 'a', which you do not know the numerical value of. You then compare letter to see if it is less than 24. Well in any ASCII-compatible character set, the character 'a' has value 97, so this condition will never pass.
You then misuse ++ on the cout line. The ++ operator attempts to modify its operand, yet 'a' is a literal and so cannot be modified. Have a look at what your assignment told you. You can do 'a' + 1 to get 'b', for example, so this assumes you have an offset (which you don't with your current approach).
So to repeat, you have two options. First: keep letter as a char starting at 'a' and fix the condition so that it checks if letter is less than or equal to the value of 'z' and then just print out letter. Second: change letter to offset and start it off at 0 and increment it while it is less than 26, and then print out 'a' + offset.
Note, however, that both of these approaches assume that the letters have consecutive values in the execution character set. This is not necessarily true.
The ++ operator is a "hidden assignment" (the operand's value is changed by it). But you can only assign to variables, which 'a' is not.
I know this has been closed for a while but since the exercise was about while loops and not for loops, I thought I would offer my solution. I'm just going through the book myself and someone in the future might stumble over this.
int i = 0;
char n = 'a'; // this will list the alphabet
int conv = 0;
conv = n; // this converts the alphabet into integer
while (i < 26) { // starts from 0 and goes to 25
cout << char(n + i) << '\t' << conv + i << '\n';
++i;
}
You may use the following: (http://ideone.com/akwGhl)
#include <iostream>
int main()
{
for (char c = 'a'; c <= 'z'; ++c) {
std::cout << "letter " << c << " has value " << int(c) << std::endl;
}
return 0;
}
hey through troubleshooting i obtained a sample that worked , i have yet to perfectly understand how my code works but as the solutions that were proposed to me here seemed too technical for my level i figured that i should publish mine
#include"header files . h"//i use the libraries given in the book
int main () {
char a ='a';
int i = 0 ;
while (i <= 25)//for (i = 0 ; i <= 25 ; i++)
//for those who used for
{
cout << a << '\t' << 'a' + i << endl;
a += 1; // augments the character value of a to b ... then to z
i++; // augments the value of i allowing us thus to make the augmentation,if you are using the for structure do not put I in your code
}
}