How do I make a string vector keep spaces from user input? - c++

I do apologize if this has been asked before, but I haven't really seen this come up in my books or in other examples. So here I go.
I have been getting into a card game, after getting lazy with constant shuffling I made a program that does it for me, theoretically. I realize there are already programs that do so, but where is the fun in that? Onto the problem that led to the question. Whenever I typed in a card with a two or more word name, it chopped off all the words but the first. I have known this to happen but I don't know how to fix it normally. Let alone how to store "A, the C" in a vector and keep spaces.
The Question: How do I store a string like "A, the C" in a string and put it in a container and be able to retrieve it with the spaces in tact? Am I doing something wrong in the code, or am I using the wrong tool for the shed?
#include <iostream>
#include <string>
using namespace std;
int main()
{
string example = " ";
cin >> example; //typed eggs and milk, only got eggs
cout << example << endl;
}

Instead of
cin >> example;
use
std::getline(std::cin, example);
cin >> example; will stop reading when it finds a white space. std::getline will cotinue reading until a specified delimiter ('\n' by default) is found.
More on std::getline.

Related

searching a name in the csv file on C++

I am a young programmer who is trying to learn c++. i have a working csv.file. but i want to search for a specific number assigned to the name and then displays the name of what i'm looking for. i have the file here:
1,Bulbasaur,grass
2,Ivysaur, grass
3,Venusaur, grass
4,Charmander, fire
5,Charmeleon, fire
6,Charizard, fire
7,Squirtle, water
8,Wartortle, water
9,Blastoise, water
Code
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream ip("pokedex.csv");
string pokedexnum[9];
string pokemonName[9];
string pokemonType[9];
cout<<"please enter a pokemon number:"<<" ";
cin>>pokemonType[0];
while (ip.good()){
getline( ip, pokedexnum[0]);
getline( ip, pokemonName[0]);
getline( ip, pokemonType[0]);
}
cout<<"the pokemon that is:"<< " "<<pokedexnum[0]<< "is the pokemon called:"<< pokemonName[0];
ifstream close("pokedex.csv");
return 0;
}
when it runs
please enter a pokemon number: 1
the pokemon that is: is the pokemon called:8,Wartortle, water
could you please point out what i am doing wrong?
Among the issues in this code:
You're not using std::getline correctly for comma-separated data. The result is each pass is consuming three lines from your input file; not three values from each line.
You're also not using ip.good() correctly as a while-condition.
You're retaining your test value in the array, which will be overwritten on the first iteration pass, so it is lost.
You're ignoring potential IO failures with each std::getline invoke.
You're overwriting slot-0 in your arrays with each loop iteration.
Minor, ifstream close("pokedex.csv"); clearly isn't doing what you think it is. That just creates another fstream object called close on the given file name.
The later may be intentional for now, but clearly broken in the near future.
In reality, you don't need arrays for any of this. All you're doing is reading lines, and seem to want to test the input number against that of the CSV data first column, reporting the line that you find, then ending this.
So do that:
Read the input value to search for.
Open the file for scanning.
Enumerate the file one line at a time.
For each line from (3), use a string stream to break the line into the comma separated values.
Test the id value against the input from (1). If the same, report the result and break the loop; you're done.
The result is something like this:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <cstdlib>
int main()
{
std::cout<<"please enter a pokemon number: ";
long num;
if (std::cin >> num && num > 0)
{
std::ifstream ip("pokedex.csv");
std::string line;
while (std::getline(ip, line))
{
std::istringstream iss(line);
std::string id, name, skill;
if (std::getline(iss, id, ',') &&
std::getline(iss, name, ',') &&
std::getline(iss, skill))
{
char *endp = nullptr;
long n = std::strtol(id.c_str(), &endp, 10);
if (id.c_str() != endp && n == num)
{
std::cout << "The pokemon that is: " << num << " is called: " << name << '\n';
break;
}
}
}
}
}
Admittedly untested, but it should work.
Whether you want to store the items in arrays at this point is entirely up to you, but it isn't needed to solve the somewhat abstract problem you seem to be attempting, namely finding the matching line and reporting the name from said-same. If you still want to store them in arrays, I suggest you craft a structure to do so, something like:
struct Pokemon
{
int id;
std::string name;
std::string skill;
};
and have a single array of those, rather than three arbitrary arrays that must be kept in sync.
Four issues jump out at me:
You store the user's input into pokemonType, but then also use pokemonType for reading data from your CSV file. The file input is going to overwrite the user input.
Your file input loop always references index 0. All of the lines from your data file are going into element 0. That's the main reason that even if the user inputs 1, the output is from the last line of the data file.
Your file reading loop is structured like you want to put one part of each data line into a different array, but what you've written actually reads three lines on every iteration, storing those lines into the three different arrays.
This isn't affecting your output, but the code ifstream close("pokedex.csv"); is written like you want to close the file stream you opened, but I do believe what this line actually does is create a new ifstream called close, and opens pokedex.csv attached to it. In other words, it's just like your other line ifstream ip("pokedex.csv"); but with close as the variable name instead of ip.
You are going to want to look into something called "string tokenization". Start with some web searches, apply what you read about to your code, and of course if you hit another snag, post a new question here to Stack Overflow, showing (as you did here) what you tried and in what way it isn't working.
Elaborating on #3, here's what how your data file is being read:
at the end of the 1st iteration of the file-reading loop, ...
pokedexnum[0] is "1,Bulbasaur,grass"
pokemonName[0] is "2,Ivysaur, grass"
pokemonType[0] is "3,Venusaur, grass"
at the end of the 2nd iteration of the file-reading loop, ...
pokedexnum[0] is "4,Charmander, fire"
pokemonName[0] is "5,Charmeleon, fire"
pokemonType[0] is "6,Charizard, fire"
at the end of the 3rd iteration of the file-reading loop, ...
pokedexnum[0] is "7,Squirtle, water"
pokemonName[0] is "8,Wartortle, water"
pokemonType[0] is "9,Blastoise, water"
And that's why
<< "is the pokemon called:"<< pokemonName[0];
outputs
is the pokemon called:8,Wartortle, water

Building a list of words from a sentence inputted

I am fairly new to programming and would like help with my homework. I have no idea where to even start.
"
1. Have the user input a sentence
2. Print out the individual words in the sentence, along with the word number
So the string "This is a test of our program." should produce:
1. This
2. is
3. a
4. test
5. of
6. our
7. program
This should strip out all spaces, commas, periods, exclamation points."
if you can give me some pointers. thanks.
You will have to use strings and streams from the standard library. You can start by including the following headers
#include <string>
#include <iostream>
A good starting point would be to look at the introduction here
Try some stuff with std::cout. This method allows you to output content to the console. Start with something easy, such as:
std::cout << "Hello World" << endl;
You can also output the content of a variable the same way:
std::string myString = "SomeText";
std::cout << myString << endl;
std::cout does the opposite. It allows you to capture the user input into a variable.
int myNumber;
std::cin >> myNumber;
or
std::string userInputString;
std::getline(std::cin, userInputString)
Notice that in the second case we're using std::getline. This is because std::cin behaves in such a way that it will stop after the first word if you write an entire sentence.
Now that you've captured the user input string, you can remove undesired characters, split the string, etc.. Look at what is available in the string class. Good luck.

Stop new line for C++ cin

In C++, iostream automatically puts in a new line after cin. Is there a way to get rid of this?
I want use iomanip to format information into a table, like so:
cin cout
0.078125 3DA00000
-8.75 C10C0000
23.5 41BC0000
(random numbers)
example code:
#include <iostream>
using namespace std;
int main()
{
int num;
cin >> num; //now a new line.
cout << num << endl;
return 0;
}
You presumably pressed the return key to send your input from the command line to your program's standard input. That's where the newline is coming from. You can't read your number from cin before this newline appears in the console, because the newline is what causes the console to hand your input over to the program in the first place. You could, as a user, configure your console (or whatever is running your program) to act differently, but there's no way for the program itself to force such behavior.
If you really want to have your input and your output on the same line, you need to find a way to "write to the previous line". How that works depends on your console (see also How to rollback lines from cout?). There is no standard way to do this because cin and cout are in no way obligated to be attached to a console or anything resembling one, so it is not clear that "writing to the previous line" even means anything.
'endl' makes a new line just don't use it.
cout << num;

Visual C++ using Console: Char/String compatibility issues with while loop

cout << "Would you like to make another transaction? (y/n)" << endl;
cin >> repeat_transaction;
static_cast<char>(repeat_transaction);
while (repeat_transaction != 'y' && repeat_transaction != 'n')
{
cout << "Invalid selection: Please enter y or n";
cin >> repeat_transaction;
static_cast<char>(repeat_transaction);
}
During the Invalid selection loop, I once accidentally pressed "mn". I noticed the console read out Invalid selection..., So, it did in fact finish and re-enter the while loop. However, after this the console terminated the program. If you enter a single character 'a' or 'y' or 'n' it acts just as it should. Ending or not ending. This was before I attempted to use static_cast to force the truncation of the user input.
Since you managed to get this program to compile I can only assume that repeat_transaction was specified as a char and not a std::string.
When you use cin to get a character it only gets one character but it doesn't flush the buffer. I believe you understand this issue since you wrote This was before I attempted to use static_cast to force the truncation of the user input. . You can attempt to use cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); instead of static_cast<char>(repeat_transaction); after each call to cin >> repeat_transaction; . There are downsides to this. If you enter 'mn' it will work as expected. It reads the m which is not y or n and then flushes the extra characters until it finds end of line \n. If you do nm, n will match and the m will be thrown away. So in that case it will accept nm as valid and exit the loop.
There are other ways that may be easier and give you the effect closer to what you are looking for. Instead of reading a character at a time you can read an entire line into a string using getline (See the C++ documentation for more information). You can then check if the length of the string is not equal to 1 character. If it's not length 1 then it is invalid input. If it is 1 then you want to check for y and n. Although basic (and not overly complex) this code would do a reasonable job:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string repeat_transaction;
cout << "Would you like to make another transaction? (y/n)" << endl;
getline(cin, repeat_transaction);
while (repeat_transaction.length() != 1 || (repeat_transaction != "y" && repeat_transaction != "n"))
{
cout << "Invalid selection: Please enter y or n";
getline(cin, repeat_transaction);
}
return 0;
}
I said reasonable job since one deficiency you might see is that you want to trim white spaces from the beginning and end. If someone enters n or y with a space or tab in front it will be seen as invalid (whitespace at the end would be similar). This may not be an issue for you, but I thought I would mention it.
On a final note, you may have noticed I used using namespace std;. I did so to match what was in the original question. However, this is normally considered bad practice and should be avoided. These StackOverflow answers try to explain the issues. It is better to not do it and prepend all standard library references with std::. For example string would be std::string, cin would be std::cin etc.

How do I input variables using cin without creating a new line?

Whenever I input a variable using cin, after one hits enter it automatically goes to a new line. I'm curious if there's a way to use cin without having it go to a new line. I'm wanting to cin and cout multiple things on the same line in the command prompt. Is this possible?
You can't use cin or any other standard input for this. But it is certainly possible to get the effect you are going for. I see you're on Windows using Visual Studio, so you can use, for example, _getch. Here's an example that reads until the next whitespace and stores the result in a string.
#include <conio.h> // for _getch
std::string get_word()
{
std::string word;
char c = _getch();
while (!std::isspace(c))
{
word.push_back(c);
std::cout << c;
c = _getch();
}
std::cout << c;
return word;
}
It's not very good. For example, it doesn't handle non printing character input very well. But it should give you an idea of what you need to do. You might also be interested in the Windows API keyboard functions.
If you want a wider audience, you will want to look into some cross-platform libraries, like SFML or SDL.
you can also use space for input instead of enter
something like this:
cin >> a >> b >> c;
and in input you type
10 20 30
then
a=10
b=20
c=30
As others have noted, you can't do this with cin, but you could do it with getchar(). What you would have to do is:
collect each character individually using getchar() (adding each to the end of a string as it is read in, for instance), then
after reading each character, decide when you've reached the end of one variable's value (e.g. by detecting one or more ' ' characters in the input, if you're reading in int or double values), then
if you've reached the end of the text for a variable, convert the string of characters that you've built into a variable of the appropriate type (e.g. int, double, etc.), then
output any content onto the line that might be required, and then
continue for the next variable that you're reading in.
Handling errors robustly would be complicated so I haven't written any code for this, but you can see the approach that you could use.
I don't think what you want to do can be achieved with cin. What you can do is to write all your input in one line, with a delimiter of your choosing, and parse the input string.
It is not possible. To quote #Bo Persson, it's not something controlled by C++, but rather the console window.
I can't comment but if you leave spaces between integers then you can get the desired effect. This works with cin too.
int a, b, c;
cin>>a; cin>>b; cin>>c;
If you enter your values as 10 20 30 then they will get stored in a, b, and c respectively.
just use the gotoxy statement. you can press 'enter' and input values in the same line
for eg. in the input of a 3*3 matrix:
#include<iostream.h>
#include<conio.h>
void main()
{clrscr();
int a[20][20],x,y;
cout<<"Enter the matrix:\n ";
for(int r=2;r<7;r+=2)
for(int c=2;c<7;c+=2)
{gotoxy(c,r);
cin>>a[r][c];
}
getch();}