Link to home
Start Free TrialLog in
Avatar of masta_mind
masta_mind

asked on

IstringStream Problems

Basically, I'm trying to take a string, switching it to integers and printing it out.. But for some reason, no matter what char it finds, it gives it the same value..

code:

#include <iostream> // For COUT
#include <string> // Strings
#include <sstream> // StringStreams
#include <iomanip>

using namespace std;

int main() {
      string name;
      cout << "Enter your name: ";
      getline(cin, name);
      int count = name.length();
      string split;
      int intcode;
      for (int j=0; j <= count; j++) {
            split = name.substr(0, j+1);
            istringstream toint(split);
            toint >> intcode;
      cout << intcode;
      ostringstream tostr(intcode);
      string code;
      tostr << setprecision(15) << code;
      cout << code;
      }
  return 0; // End
}

end code:

thanks alot,

Rob
Avatar of n_fortynine
n_fortynine

A quick test I can think of...

string num, test;
int i;
istringstream strm(num);
strm >> i;
stringstream buff;
buff << i;
buff >> test;
if(test != num) cout << "num is not an legal integer\n";
else cout << "num is a legal integer\n";
If the characters you feed the program can't be converted to an integer, the line

toint >> intcode;

is not going to change intcode, so it will always contain the same thing (uninitialized garbage).

When I fed digits to the program, it behaved reasonably according to the code.  When I entered "123", it put out 112123123, which makes sense the way the loop is coded.

It doesn't make sense to initialize tostr with intcode.  The constructor will take this as a bunch of flags, which is probably not what you want.

The string named "code" is constructed empty by default and never gets any content, so it doesn't do anything useful to put it into either cout or tostr.

--efn
         split = name.substr(0, j+1);
puts the first j elements in the substr. Intcode gives the integer of the first element in the substring which stays the first element of the name. Did you ment
         split = name.substr (j,j+1); ?
Avatar of masta_mind

ASKER

SteH::  Ya, I noticed that, I was thinking that might be the problem, but it wasn't.

efn:: Ya, I see what you mean.  So I came up with this:

#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>

using namespace std;

int main() {
      string name;
      cout << "Enter your name: ";
      getline(cin, name);
      int count = name.length();
      string split;
      int intcode;
      for (int j=0; j <= count; j++) {
            split = name.substr(j, j+1);
            istringstream toint(split);
            int intcode = toint.get(); // NEW LINE
      cout << intcode;
      }
  return 0; // End
}

So I changed it to toint.get.. but my question now is how to use setprecision.  I'm not sure, I have tried a few different combos and none seem to work
Well, the more I read up on setprecision, it looks as though it doesn't *seem* to change things to the left of the decimal.  So is there any better way cause i want it no matter what name you have the same length of numbers, and I also want to get rid of the -1 after everything.
Sorry, I can't tell what you are trying to do here.  Perhaps it would help if you showed some input strings and the integers you would like the program to get from those inputs.

--efn
Well when I enter my name:

Rob Shaw .. it outputs::

8211198328310497119-1

I am not sure what the -1 means..

And if I enter like RS::

8283-1

So basically, I want to set it so they all have the same length.. is this possible at all?
I know that each integer is basically one or two numbers so if I enter R it equals 82 and so forth, but I am wondering what other way I could get the same length..
I also put it in a menu program and am having a hard time getting it to display outside the for statement...

#include <iostream>
#include <algorithm>
#include <string>
#include <stdio>
#include <sstream>
#include <iomanip>

using namespace std;

      int menu(); // Menu Function
       void Validate(); // Program
       void Keygen(); // Program

int main() {
      bool exit = false;
      for (;;) {
        int choice = menu();
        switch(choice) {
            case (1):
              Validate(); //
              break;
            case (2):
              Keygen();
              break;
            case (3):
              exit=true;
              break;
            default:
              cout << "Please select again!\n";
              system("PAUSE");
              break;
            }
      if (exit)
            break;
      }      
}

int menu() {
               int choice;
            system("CLS");
            cin.clear(); // clear all previous cin's
            cout << "*******************************" << "\n"
               << "*             Menu            *" << "\n"
               << "*******************************" << "\n\n";
                  cout << "(1) Validator.\n";
                  cout << "(2) Key Generator.\n";
                  cout << "(3) Quit. \n\n";
                  cout << "Enter Choice --> ";
                  cin >> choice;
                  cout << "\n";
                  return choice;
}

int length(string name) {
      int x = name.length();
      return x;
}

int split(string name) {
         string split;
     int count = length(name);
     int intcode;
     for (int j=0; j <= count; j++) {
          split = name.substr(j, j+1);
          istringstream toint(split);
          intcode = toint.get();
              intcode = intcode;
            }
            return intcode; // outside the for loop i get -1, and inside i get the int for the first letter of string name..
}
// *** //
void Keygen() {
            string name, blank; // declare the strings
      getline (cin, blank);
      cout << "Please Type In Your Name: ";
      getline (cin, name);
      cout << "Key: " << split(name) << endl;
      system("PAUSE");
}
// *** //
void Validate() {
            string name, blank; // declare the strings
            int key;
      getline (cin, blank);
      cout << "Please Type In Your Name: ";
      getline (cin, name);
      cout << "\nPlease Enter The KeyGen: ";
      cin >> key;
      if (key == split(name)) cout << "Valid Keygen!" << endl;
      else cout << "Invalid." << endl;
      system("PAUSE");
}



// outside the for loop i get -1, and inside i get the int for the first letter of string name..
Also don't worry, this key-generator is for a school project soo nothing illegal.. ;)
OK, I can explain the -1.  Let's take the case where you enter "RS".  Then name == "RS" and count == 2.

The first time through the loop, j == 0 and split == "R".  So intcode gets the numeric value of 'R'.

The second time through the loop, j == 1 and split == "S", so intcode gets the numeric value of 'S'.

After the second time through the loop, j is incremented to 2 and j <= count is still true, so the loop runs a third time.  There are only two characters in name, with indexes 0 and 1, so name.substr(2, 3) returns an empty string.  So split is an empty string.  So toint has no character in its buffer.  So toint.get() returns the EOF (end of file) code, which is -1.

As you may have figured out by now, when there are two characters, you only want to run the loop two times, but the test j <= count makes it run three times.

The second parameter to substr is a length, so name.substr(j, j + 1) doesn't make sense.  In the example above, the second time through the loop, it would be getting name.substr(1, 2), but 2 is the length and there are not 2 characters available at position 1.

You can get the numeric value of character j of name much more simply, like this:

int intcode = name[j];

You don't need the stringstream.

I don't understand what you mean by all having the same length.  If you can explain more, I may be able to advise you.

--efn
Well, the whole reason for the program is to have a key-generator so if someone in class wants to log-in they have a special keygen to login as.  So basically, I want every output to be let's say 7 numbers long so if I enter::

Rob Shaw  --> (i get)  123-4567
RS --> 345-1234

Not necessarily those numbers but the same numeric length.
OK, it looks like you want to define a mapping from strings to k-digit numbers where k is a constant.  To do that, you need an algorithm, a precise method.  What's your algorithm?

--efn
I have no idea.. I'm still really new to C++ so...

I figured you might be able to do something like test for different string lengths and ****.. or maybe at least have it test if less then 5 chars then it says invalid input.  [since i don't know algorithms too well]
The only other problem I seem to be having is inside my menu program, trying to get it to return the code, because I can't get it to work outside the for statement..
ASKER CERTIFIED SOLUTION
Avatar of efn
efn

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Ahh thank you!
I dunno if you can also look up at my for statement to return intcode in my void Keygen thing and tell me how I can get it out of there to return it..


Thanks..
My new menu code is:


#include <iostream>   // for cout function
#include <string>        // for string related stuff

using namespace std;

      int menu();         // declare menu function
       void Validate();   // declare validator function
       void Keygen();     // declare keygenerator function

int main() {
      bool exit = false;
      for (;;) {
        int choice = menu();
        switch(choice) {
            case (1):
              Validate();
              break;
            case (2):
              Keygen();
              break;
            case (3):
              exit=true;
              break;
            default:
              cout << "Please select again!\n";
              system("PAUSE");
              break;
            }
      if (exit)
            break;
      }      
}

int menu() {
               int choice;
            system("CLS");
            cin.clear();
            cout << "*******************************" << "\n"
               << "*             Menu            *" << "\n"
               << "*******************************" << "\n\n";
                  cout << "(1) Validator.\n";
                  cout << "(2) Key Generator.\n";
                  cout << "(3) Quit. \n\n";
                  cout << "Enter Choice --> ";
                  cin >> choice;
                  cout << "\n";
                  return choice;
}

int length(string name) {
      int x = name.length();
      return x;
}

int split(string name) {
         string split;
     int count = length(name);
     int intcode;
     for (int j=0; j<count; j++) {
              split = name.substr(j, count-j);
          intcode = name[j];
       }
             return intcode;
}

void Keygen() {
 string name, blank; // declare the strings
      getline(cin, blank);
      cout << "Please Type In Your Name: ";
      getline(cin, name);
      if (length(name) < 5) {
             cout << "Invalid Input.." << endl;
      } else {  // if length >= 5
             cout << "Key: " << split(name) << endl;
      }
 system("PAUSE");
}

void Validate() {
 string name, blank; // declare the strings
            int key;
      getline(cin, blank);
      cout << "Please Type In Your Name: ";
      getline(cin, name);
      if (length(name) < 5) {
             cout << "Invalid Input.." << endl;
      } else {  // if length >= 5
      cout << "\nPlease Enter The KeyGen: ";
      cin >> key;
      if (key == split(name)) cout << "Valid Keygen!" << endl;
      else cout << "Invalid." << endl;
      }
 system("PAUSE");
}
Sorry, I don't understand your last question.
Well, when I enter a name after selecting keygenerator in my menu program there, it returns :: 119 instead of the actual number...

Basically because I put it outside the for statement,but if I put it in, I get an even weirder number..

This is your loop for calculating intcode:

     for (int j=0; j<count; j++) {
            split = name.substr(j, count-j);
          intcode = name[j];
      }

name is a string.  name[j] is a character.  Each iteration of the loop assigns a different character to intcode, wiping out whatever was there before.  At the end of the loop, intcode will contain the numeric value of the last character in the string.  You could do the same thing in one statement without a loop:

intcode = name[name.length() - 1];

Presumably you have a loop because you want each character of the name to have some effect on the integer in which it is encoded.  Just assigning each character to the integer won't do that.  I suggested one way to do it in a previous comment.  Bear in mind, though, that if you use that algorithm, you may get what you consider a weird number.

--efn
Ahh.. Alright, so I can can use algorithms better to get to my answer.  Thanks alot..


lol about the weird number part.. The only reason I called it a weird number was because whatever name I would enter, I would get [123] <--always and [xxx] for the rest..