How can I store input after a comma as an integer? - c++

I've been working on a program to display user input in a table and a histogram, I've got those down, but I can't figure out how to take the user input and separate it by a comma and save the first part as a string and the second as an integer. I used streams but it separates it by spaces and the string might need to have spaces in it, so that's not reliable. I also tried substrings but I need the second half to be an int. Any tips are appreciated. Thank you.
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iomanip>
#include <ctype.h>
using namespace std;
int main() {
string title, col1, col2, userInput, one, two;
istringstream inSS;
string lineString;
string author;
int books;
vector<string> vecAuthors;
vector<int> vecBooks;
bool inputDone;
cout<<"Enter a title for the data:"<<endl;
getline(cin, title);
cout<<"You entered: "<<title<<endl;
cout<<"Enter the column 1 header:"<<endl;
getline(cin, col1);
cout<<"You entered: "<<col1<<endl;
cout<<"Enter the column 2 header:"<<endl;
getline(cin, col2);
cout<<"You entered: "<<col2<<endl;
while (!inputDone) {
cout<<"Enter a data point (-1 to stop input):"<<endl;
getline(cin, lineString);
while (lineString.find(',') == string::npos) {
if (lineString == "-1") {
break;
}
cout << "Error: No comma in string.\n" << endl;
cout << "Enter a data point (-1 to stop input):" << endl;
getline(cin, lineString);
}
string::size_type position = lineString.find (',');
if (position != string::npos)
{
while (lineString.find (',', position+1) != string::npos) {
if (lineString == "-1") {
break;
}
cout << "Error: Too many commas in input." << endl;
cout << "Enter a data point (-1 to stop input):" << endl;
getline(cin, lineString);
}
}
one = lineString.substr(0, lineString.find(','));
two = lineString.substr(lineString.find(',') + 1, lineString.size() - 1);
inSS.clear();
inSS.str(lineString);
inSS >> author;
inSS >> books;
if (inSS.fail()) {
if (lineString == "-1") {
break;
}
cerr << "Error: Comma not followed by an integer." << endl << endl;
cout << "Enter a data point (-1 to stop input):" << endl;
getline(cin, lineString);
}
inSS.clear();
inSS.str(lineString);
inSS >> author;
if (author == "-1") {
cout<<"Finished."<<endl;
inputDone = true;
}
else {
inSS >> books;
author.pop_back();
vecAuthors.push_back(author);
vecBooks.push_back(books);
cout << "Data string: " << author << endl;
cout << "Data integer: " << books << endl;
}
}
cout<<setw(33)<<right<<title<<endl;
cout<<setw(20)<<left<<col1<<"|";
cout<<setw(23)<<right<<col2<<endl;
cout<<setfill('-')<<setw(43)<<""<<endl;
cout<<setfill(' ');
for(int i=0; i<vecAuthors.size(); ++i){
cout<<setw(20)<<left<<vecAuthors[i]<<"|"<<setw(23)<<right<<vecBooks[i]<<endl;
}
cout<<endl;
for(int i=0; i<vecAuthors.size(); ++i){
cout<<setw(20)<<right<<vecAuthors[i];
for(int k = 0; k<vecBooks[i]; ++k) {
cout<<left<<"*";
}
cout<<endl;
}
return 0;
}

Code to get the first part to a string and second part to an int:
#include <iostream>
#include <string>
int main()
{
std::string input{};
std::cin >> input;
int commaSlot{};
for (int i = 0; i < input.length(); i++) {
if (input[i] == ',') {
commaSlot = i;
break;
}
}
std::string firstPart = input.substr(0,commaSlot);
int secondPart = std::stoi(input.substr(commaSlot+1));
std::cout << firstPart << " " << secondPart;
}

because what you need is quite custom (you need comma as a separator and not space ) you can get a line and parse it as you want with the getline function of std afterwards you can separate the string on the comma (the simplest way I can think off is a simple for loop but you can use std's algorithm's also) and then you can use the stoi function to convert a string to an int ,all of them together:
std::string row{};
unsigned positionofcomma{};
std::getline(std::cin,row);
for (unsigned i=0;i<row.length();i++)
if (row[i]==','){
positionofcomma=i;
break;
}
std::string numberstring=row.substr(positionofcomma+1, row.length());
int number=std::stoi(numberstring);

Related

Dealing with file io in c++

I have a program that takes input for names and outputs the last names in a string. The task I have now is to include FileIO in it. Specifically, "get user input for the filename, and then read the names from the file and form the last name string."
When I run the program, the console will show the name string from the text file. But only initially. As you keep entering names, that string disappears. Also, my user input for file name seems to be doing nothing, because I can enter anything and it still show the string of last names from the text file.
Here is what I have so far. Included all of it, just to make sure.
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <fstream>
using namespace std;
// function declerations
int Menu();
void getName(vector<string> &names, int &count);
void displayName(vector<string> &names, int count);
string getLastNames(vector<string> &names, int count);
int main()
{
vector<string> names;
int count = 0;
int choice = Menu();
ifstream File;
string line;
cout << "Enter file name: ";
getline(cin,line);
File.open("File.txt");
while(File.good()){
getline(File,line);
cout << line << endl;
}
File.close();
while (choice != 0)
{
// switch statement to call functions based on users input
switch (choice)
{
case 1: {
getName(names, count);
} break;
case 2: { displayName(names, count); } break;
case 3: {
cout << getLastNames(names, count) << endl;
} break;
case 0: {
return 0;
} break;
}
choice = Menu();
}
return 0;
}
// function definition for vector of strings
void getName(vector<string> &names, int &count)
{
string name;
// get input for name
cout << "Enter name: ";
getline(cin, name);
// find position of space in string
int pos = name.find(' ');
// reverse order of name
if(pos != -1) {
string first = name.substr(0, pos);
string last = name.substr(pos+1);
name = last + "," + first;
}
// add name to end of vector
names.push_back(name);
count++;
}
// give user option of what to do
int Menu() {
int choice;
cout << "1. Add a name" << endl;
cout << "2. Display names " << endl;
cout << "3. Show all Last Names" << endl;
cout << "0. Quit" << endl;
cout << "Enter a option: ";
cin >> choice;
// if outside of above choices, print 'choice not on list'
while (choice < 0 || choice > 3)
{
cout << "Choice not on list: ";
cin >> choice;
}
cin.ignore();
return choice;
}
// defining function that gets last names
string getLastNames(vector<string> &names, int count) {
stringstream ss;
for (int i = 0; i<count; i++)
{
int pos = names[i].find(',');
if (pos != -1) {
ss << "\"" << names[i].substr(0, pos) << "\", ";
} else {
ss << "\"" << names[i] << "\", ";
}
}
return ss.str();
}
// display the names
void displayName(vector<string> &names, int count)
{
if (count == 0)
{
cout << "No names to display" << endl;
return;
}
for (int i = 0; i<count; i++)
{
cout << names[i] << endl;
}
}

Error on getline function no instance matches the arguments

Why my code is not executing and showing me error ?? Im getting error on this line
while (getline(s, word, ' , '))
my Code is below:
#include <fstream>
#include <string>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
// first we define a class that will represent all the candidates
class Candidate
{
string name;
int votes;
public:
Candidate()
{
name = "";
int votes = 0;
}
Candidate(string cand_name, int vote_count)
{
name = cand_name; votes = vote_count;
} string getName() { return name; } int getVotes() { return votes; } void get_details() { cout << name << ", " << votes << endl; }
//Following member method is used to increment the vote count
void vote_this_candidate() { votes++; }
};
int main()
{
cout << "Welcome to Student President Voting System!!!" << endl;
Candidate allCandidates[100];
int totalVotes = 0;
// File pointer fstream fin; // Open an existing file
fstream fin;
fin.open("candidantes.txt", ios::in); // Read the Data from the file // as String Vector
vector <string> row;
string line, word, temp; int index = 0; // Following while loop will iterate for each line in the file
while (fin >> temp) {
row.clear(); // read an entire row and // store it in a string variable 'line'
getline(fin, line); // used for breaking words
string s(line); // read every column data of a row and // store it in a string variable, 'word'
while (getline(s, word, ' , '))
{ // adding the splitted words to row
row.push_back(word);
} allCandidates[index] = Candidate(row[0], stoi(row[1])); totalVotes += stoi(row[1]); index++;
}
string name = ""; cout << "\nPlease enter the name of the candidante you want to vote : ";
getline(cin, name); int cand_no = -1; string userChoice; int i = 0; //Now we find the candidante with the same inputted name
while (i < index) {
if (allCandidates[i].getName() == " " + name) {
cand_no = i; cout << "Do you want to vote this candidante [y/n] : ";
cin >> userChoice; //After finding the candidate just ask the user to vote the candidante
if (userChoice == "y") { //to vote just call the member method that increments the vote count
allCandidates[cand_no].vote_this_candidate(); totalVotes++; cout << endl << "You successfully voted to " << name << " Thanks for voting!!!" << endl;
}
else { cout << "You didn't vote!!!" << endl; } break;
}
i++;
} if (cand_no == -1) {
cout << "Candidante not found!!! Do you like to add this candidate [y/n]: ";
cin >> userChoice; if (userChoice == "y") { allCandidates[index + 1] = Candidate(name, 1); totalVotes++; index++; }
}
//To show top five candidates we first sort the array with lambda
std::sort(allCandidates, allCandidates + 10, [](Candidate a, Candidate b) -> bool { return a.getVotes() > b.getVotes(); });
//then we show only first five candidates
cout << endl << "These are top 5 candidantes so far : " << endl;
for (int i = 0; i < 5; i++)
{
cout << i + 1 << ","; allCandidates[i].get_details();
} cout << endl << "Total studnets voted: " << totalVotes;
}
Problem is here:
string s(line);
while (getline(s, word, ' , '))
because getline has no overload that takes a std::string as its first parameter.
However, there is an overload that takes a stringstream, so you can do:
stringstream ss(line);
while (getline(ss, word, ' , '))
Also, ' , ' won't do what you think. Perhaps you meant ','.
Finally, int votes = 0; in your Candidate() constructor should just be votes = 0;. As it is, you are just declaring, initialising and then discarding a local variable.
The problem is that the compiler is telling you that the parameters you've given don't match a definition of the function. In your case I believe the problem is that you've given it 3 characters instead of 1 in the character portion (remember, a space is also a character). Try changing ' , ' to ','

c++ input for-loop followed by another input

c++ Microsoft visual studio on a windows.
im very new to coding. currently going through Programming -- Principles and Practice Using C++ by Stroupstrup and I came across a difficulty. I am to create a "score chart" with vector name and vector score from the user input. I used for-loop to get the input. now I am to modify the program so that with 2nd input from the user I can search the list and "cout<<" the score for a person. the problem is the the program completely ignores the 2nd "cin>>" command.
I search online and could not find a reasonable answer to this problem. Is there any special interaction between a for-loop input being terminated and another input (not looped)
syntax:
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <string>
using namespace std;
int main()
{
vector<string> name;
vector<int> score;
string temp2;
int i;
for (string temp; cin >> temp >> i;) //input terminated with "Ctrl+Z"
name.push_back(temp), score.push_back(i);
for (int i = 0; i < name.size(); ++i) {
for (int j = i + 1; j < name.size(); ++j) {
if (name[i] == name[j]) {
name[j] = "error";
score[j] = 0;
}
}
}
for (int i = 0; i < name.size(); ++i) {
cout << name[i] << "------" << score[i] << "\n";
}
cout << "name"; //this line shows in the console
cin >> temp2; //but I cannot prompt the user to input again?
return 0;
}
CTRL-Z is interpreted as "End-Of-File", such that any subsequent access to this stream will not read in items any more. The only secure way is to change program logic such that the list of names is terminated by, let's say "END", and not a CTRL-Z. Then you can continue in a save manner.
Often input from a terminal is read in line by line and parsed afterwards. This makes error handling easier. See the following code following such an approach:
#include <sstream>
int main() {
string line;
map<string,int> scoreboard;
cout << "enter name score (type END to finish):" << endl;
while (std::getline(cin, line) && line != "END") {
stringstream ss(line);
string name;
int score;
if (ss >> name >> score) {
scoreboard[name] = score;
} else {
cout << "invalid input. Type END to finish" << endl;
}
}
cout << "enter name:" << endl;
string name;
if (cin >> name) {
auto item = scoreboard.find(name);
if (item != scoreboard.end()){
cout << "score of " << name << ":" << item->second << endl;
}
else {
cout << "no entry for " << name << "." << endl;
}
}
}

How to alphabetize a list on C++

I have been having some trouble on my code for my final project. I have looked everwhere and I am having a hard time so I thought I would ask on here. I need to make sure that when all the names are listed in this phonebook that they will come out in alphabetical order but as of yet I am unsure how to do that. Here is the program that i currently have! Thank you!
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
using namespace std;
struct Contact {
string name, number, notes;
};
Contact contactList[100];
int rec_num = 0;
int num_entries;
string toUpper (string S) {
for (int i= 0; i < S.length(); i++)
S[i] = toupper(S[i]);
return S;
}
void ReadFile () {
string S;
fstream input("PhoneData.txt");
while (!input.eof() && !input.fail()){
input >> contactList[rec_num].name >> contactList[rec_num].number;
getline(input, S);
contactList[rec_num].notes = S;
rec_num++;
}
cout << "Book read." << endl;
num_entries = rec_num;
input.close();
return;
}
// stores phonebook for future runs of the program
void StoreFile () {
fstream F ("PhoneData.txt");
rec_num = 0;
while (rec_num < num_entries){
F << contactList[rec_num].name << " " << contactList[rec_num].number << " " << contactList[rec_num].notes << " " << endl;
rec_num++;
}
cout << "Phonebook stored." << endl;
return;
}
// adds contact
void add_name(string name, string number, string notes){
contactList[num_entries].name = name;
contactList[num_entries].number = number;
contactList[num_entries].notes = notes;
num_entries++;
return;
}
// finds contact
void retrieve_name(string name){
for (int i = 0; i < num_entries; i++){
if (toUpper(contactList[i].name) == toUpper(name)) {
cout << "Phone Number: " << contactList[i].number << endl << "Notes: " << contactList[i].notes << endl;
return;
}
}
cout << "Name not found" << endl;
return;
}
// updates contact info
void update_name(string name){
string new_number;
string new_notes;
cout<<"New Phone Number"<<endl;
cin>> new_number;
cout<<"New Notes"<<endl;
cin>> new_notes;
for (int i = 0; i < num_entries; i++){
if (toUpper(contactList[i].name) == toUpper(name)) {
contactList[i].number = new_number;
contactList[i].notes = new_notes;
return;
}
}
}
// deletes contact
void delete_name(string name){
int INDEX=0;
for (int i = 0; i < num_entries; i++){
if (toUpper(contactList[i].name) == toUpper(name)) {
INDEX=i;
for ( int j=INDEX; j < num_entries; j++ ){
contactList[j].name = contactList[j+1].name;
contactList[j].number = contactList[j+1].number;
contactList[j].notes = contactList[j+1].notes;
}
}
}
return;
}
void listAllContacts() {
int i = 0;
while (i < num_entries) {
cout << "-- " << contactList[i].name << " " << contactList[i].number << endl << "-- " << contactList[i].notes << endl << endl;
i++;
}
}
int main(){
string name, number, notes;
string FileName;
char command;
FileName = "PhoneData.txt";
ReadFile ();
cout << "Use \"e\" for enter, \"f\" for find, \"l\" for list, \"d\" for delete, \"u\" for update, \"s\" for send message, \"q\" to quit." << endl << "Command: ";
cin >> command;
while (command != 'q'){
switch (command){
case 'e': cin >> name; cout << "Enter Number: ";
cin >> number; cout << "Enter Notes: ";
cin.ignore(); getline(cin, notes);
add_name(name, number, notes); break;
case 'f': cin >> name; retrieve_name(name); break;
case 'l':
listAllContacts(); break;
case 'u': cin>> name; update_name (name);break;
case 'd' : cin>> name; delete_name (name); break;
}
cout << "\nCommand: "; cin >> command;
}
StoreFile();
cout << "All set !";
return 0;
}
Given
Contact contactList[100];
int num_entries;
you can use std::sort to sort the list of contacts. std::sort has two forms. In the first form, you can use:
std::sort(contanctList, contactList+num_entries);
if you define operator< for Contact objects.
In the second form, you can use:
std::sort(contanctList, contactList+num_entries, myCompare);
if you define myCompare to be callable object that can compare two Contact objects.
To use the first form, change Contact to:
struct Contact {
string name, number, notes;
bool operator<(Contact const& rhs) const
{
return (this->name < rhs.name);
}
};
If you want to the comparison of names to be case insensitive, convert both names to either uppercase or lowercase and them compare them.

Reading string with spaces in c++

How can I read input line(type string) with whitespace? I tried getline but it goes into infinite loop. Following is my code.
#include <iostream>
#include <cstring>
#define MAX 50 //size of array
//Used G++ 4.6.3 compiler
using namespace std;
int main() {
struct Manager {
string name;
int age;
int working_years;
string phone;
int salary;
}info[MAX];
char inp; //To choose options
int array_pos = 0; //Current position in array of Manager structure
string search_name; //Manager name you want to search
cout << "Press 'i' to insert manager information or 's' to search for manager information by name or 'a' to abort: ";
cin >> inp;
while(inp != 'a') {
int search_num = 0; //array position at which search result is found
int found = 0;
if (inp == 'i' || inp == 's') {
if (inp == 'i') {
int k = array_pos;
cout << "Enter the information of the manager no "<<k+1<<" is : ";
cout << "Enter the Name : ";
//infinte loop occurs
getline(info[array_pos].name, '\n');
//cin >> info[array_pos].name;
cout<<"Enter manager age : ";
cin >> info[array_pos].age;
cout << "Enter manage working years : ";
cin >> info[array_pos].working_years;
cout << "Enter manager phone no. : ";
cin >> info[array_pos].phone;
cout << "Enter manager salary : ";
cin >> info[array_pos].salary;
array_pos++;
}
if (inp == 's') {
cout << "Enter the manager name you want to search : ";
cin >> search_name;
for(int i = 0; i < array_pos; i++) {
//using str1.compare(str2) to compare manager name
if(info[i].name.compare(search_name) == 0) { //manager name found in array of structure
found = 1;
search_num = i;
cout << "Name : " << info[search_num].name << "\n";
cout << "Age: " << info[search_num].age << "\n";
cout << "Working Years: " << info[search_num].working_years << "\n";
cout << "Phone No. : " << info[search_num].phone << "\n";
cout << "Salary : " << info[search_num].salary << "\n";
} //end of if loop for comparing string
} //end of for loop for searching
if(found == 0)
cout << "No Manager by this name exist in record" << "\n";
} //end of if loop
} //end of if loop for searching or insertion
if(inp == 'a')
break;
cout << "Press 'i' to insert manager information or 's' to search for manager information by name or 'a' to abort: ";
cin >> inp;
} //end of while loop
return 0;
}
How can I read input line(type string) with whitespace?
std::string line;
if (std::getline(std::cin, line)) {
...
}
Note that apart from checking the return value of std:getline call, you should also avoid mixing >> operator with std::getline calls. Once you decide reading the file line by line, it seems to be cleaner and more reasonable to just make one huge loop and do the additional parsing while using string stream object, e.g.:
std::string line;
while (std::getline(std::cin, line)) {
if (line.empty()) continue;
std::istringstream is(line);
if (is >> ...) {
...
}
...
}
Simplest way to read string with spaces without bothering about std namespace is as follows
#include <iostream>
#include <string>
using namespace std;
int main(){
string str;
getline(cin,str);
cout<<str;
return 0;
}
Solution #1:
char c;
cin >> noskipws; // Stops all further whitespace skipping
while (cin >> c) { // Reads whitespace chars now.
count++;
}
Solution #2:
char c;
while (cin.get(c)) { // Always reads whitespace chars.
count++;
}