I have some C++ code where I'm taking input from a user, adding it to a vector splitting the string by delimiter, and for debugging purposes, printing the vector's contents. However, the program only prints the first location of the vector, and then none of the rest.
main.cpp
#include <cstdlib>
#include <iostream>
#include <string>
#include <stdio.h>
#include <vector>
//Custom headers
#include "splitting_algorithm.hpp"
#include "mkdir.hpp"
#include "chdir.hpp"
#include "copy.hpp"
//Used to get and print the current working directory
#define GetCurrentDir getcwd
using namespace std;
int main(int argc, char* argv[])
{
string command;
//Gets current working directory
char cCurrentPath[FILENAME_MAX];
if (!GetCurrentDir(cCurrentPath, sizeof(cCurrentPath)))
{
return 1;
}
//Placeholder for arguments
for(int i=1; i<argc; i++)
{
cout<<string(argv[i])<<endl;
}
//Begin REPL code
while (true)
{
//Prints current working directory
cout<<cCurrentPath<<": ";
cin>>command;
vector<string> tempCommand = strSplitter(command, " ");
//Exit command
if(string(tempCommand[0])=="exit")
{
for(int i=0; i<tempCommand.size(); ++i){
cout << tempCommand[i] << ' ';
}
}
}
return 0;
}
splitting_algorithm.cpp
#include <string>
#include <vector>
using namespace std;
vector<string> strSplitter(string command, string delim)
{
vector<string> commandVec;
size_t pos = 0;
string token;
string delimiter = delim;
while ((pos = command.find(delimiter)) != string::npos)
{
token = command.substr(0, pos);
commandVec.push_back(token);
command.erase(0, pos + delimiter.length());
}
commandVec.push_back(command);
return commandVec;
}
Entering "exit 1 2 3" in the terminal returns:
exit /home/tay/Git/batch-interpreter: /home/tay/Git/batch-interpreter: /home/tay/Git/batch-interpreter: /home/tay/Git/batch-interpreter:
(The output has no newlines in it)
Why is this occurring?
You said:
I have some C++ code where I'm taking input from a user, adding it to a vector splitting the string by delimiter, and for debugging purposes, printing the vector's contents.
And your code does:
while (true)
{
//Prints current working directory
cout<<cCurrentPath<<": ";
///
/// This line of code reads only one token.
/// It does not contain multiple tokens.
/// Perhaps you meant to read an entire line.
///
cin>>command;
vector<string> tempCommand = strSplitter(command, " ");
//Exit command
if(string(tempCommand[0])=="exit")
{
for(int i=0; i<tempCommand.size(); ++i){
cout << tempCommand[i] << ' ';
}
}
}
Change the line
cin>>command;
to
std::getline(std::cin, command);
Also, to make the output cleaner, add a line to print a newline.
Add
std::cout << std::endl;
immediately after
for(int i=0; i<tempCommand.size(); ++i){
cout << tempCommand[i] << ' ';
}
Related
We have a string (25;16;67;13;14;.......)
We need to print out the numbers separately. The last number does not have a semicolon behind it.
Output should be something like that:
25
16
67
13
14
......
Assuming we are using str.find, str.substr and size_t variables current_pos, prev_pos, what will be the condition of the while loop we are using to browse the line, so that it prints out all the numbers, not just the first one?
You can make use of std::istringstream:
#include <sstream>
#include <iostream>
int main() {
std::string text("25;16;67;13;14");
std::istringstream ss(text);
std::string token;
while(std::getline(ss, token, ';'))
{
std::cout << token << '\n';
}
return 0;
}
Running the above code online results in the following output:
25
16
67
13
14
If you need only to print the numbers in the string (rather than represent them in data structures) the solution is quite easy. Simply read the entire string, then print it character by character. If the character is a semicolon, print a new line instead.
#include <iostream>
#include <string>
using namespace std;
int main(){
string input;
cin >> input;
for(int i = 0; i < input.length(); i++){
if(input.at(i) == ';') cout << endl;
else cout << input.at(i);
}
}
using namespace std;
int main() {
string a{ "1232,12312;21414:231;23231;22" };
for (int i = 0; i < a.size(); i++) {
if (ispunct(a[i])) {
a[i] = ' ';
}
}
stringstream line(a);
string b;
while (getline(line, b, ' ')) {
cout << b << endl;
}
}
//any punctuation ",/;:<>="
I will give you an exact answer to your question with an example and an alternative solution with an one-liner.
Please see
#include <iostream>
#include <string>
#include <iterator>
#include <algorithm>
#include <regex>
const std::regex re(";");
int main() {
std::string test("25;16;67;13;14;15");
// Solution 1: as requested
{
size_t current_pos{};
size_t prev_pos{};
// Search for the next semicolon
while ((current_pos = test.find(';', prev_pos)) != std::string::npos) {
// Print the resulting value
std::cout << test.substr(prev_pos, current_pos - prev_pos) << "\n";
// Update search positions
prev_pos = current_pos + 1;
}
// Since there is no ; at the end, we print the last number manually
std::cout << test.substr(prev_pos) << "\n\n";
}
// Solution 2. All in one statement. Just to show to you what can be done with C++
{
std::copy(std::sregex_token_iterator(test.begin(), test.end(), re, -1), {}, std::ostream_iterator<std::string>(std::cout, "\n"));
}
return 0;
}
Currently just trying to edit some basic input to get rid of a singular '.' at the beginning of a line.
However, this only functions when I force EOF. My submission review for this assignment on the uni site seems to be getting stuck in the while loop and not outputting the result. The amount of input can be up to 1000 lines and I can't seem to think of how I could best receive this input without it getting stuck like this. main.cpp below:
Example input and output would be:
Input:
..hello
.hello
hello
Output:
.hello
hello
hello
#include <cstdlib>
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
int main(int argc, char *argv[])
{
string inputLine;
vector<string> vect;
string s;
string temp;
while (getline(cin, s)) {
vect.push_back(s);
}
for (int i = 0; i < (int)vect.size(); i++) {
temp = vect[i];
if (temp[0] == '.') {
for (int k = 0; k < (int)temp.length(); k++) {
temp[k] = temp[k + 1];
}
}
vect[i] = temp;
}
for (int j = 0; j < (int)vect.size(); j++) {
cout << vect[j] << endl;
}
return 0;
}
The tester of your program is probably opening a pipe and waiting for your program to output the first line before sending the second. A case of dead-lock.
If you want to ignore the . character you can use std::basic_istream::peek to check if the line starts with this character and then simply std::basic_istream::ignore it. You may also want to flush your output for each line, using std::endl will do.
#include <string>
#include <iostream>
int main() {
std::string line;
while(std::cin) {
if(std::cin.peek() == '.')
std::cin.ignore();
if(std::getline(std::cin, line))
std::cout << line << std::endl;
}
}
I wrote this code to detect if an input string has a space or not. Please tell what is wrong in this approach.
#include <iostream>
#include <string>
using namespace std;
int main(){
string inp;
getline(cin, inp);
for (int i = 0; i < inp.length(); i++) {
string z = to_string(inp[i]);
if (z == " ") {
cout << "space";
}
else {
i++;
}
}
}
If i enter a string with spaces, it doesn't print "space".
Since inp is an std::string, inp[i] will be a char. Since std::to_string only has overloads for arithmetic, non-char values, calling it on a char is akin to calling it on the integer representation of said char. (If you log z, you'll likely find a number printed.)
Instead, directly compare inp[i] to a space. else { i++; } is also unnecessary – you may be jumping over spaces.
for (int i = 0; i < inp.length(); i++) {
if (inp[i] == ' ') { // note single quotes for char
cout << "space";
}
}
#TrebledJ's answer explains why your code is broken and how to fix it.
Another way to handle this situation is to use std::string::find() instead:
#include <iostream>
#include <string>
int main(){
std::string inp;
std::getline(std::cin, inp);
if (inp.find(' ') != std::string::npos) {
std::cout << "space";
}
}
Alternatively, your original code tries to output "space" for each space character found. You could use find() in a loop:
#include <iostream>
#include <string>
int main(){
std::string inp;
std::getline(std::cin, inp);
std::string::size_type idx = inp.find(' ');
while (idx != std::string::npos) {
std::cout << "space at " << idx << std::endl;
idx = inp.find(' ', idx+1);
}
}
Hopefully I can explain exactly what's going on, but basically I have a map of words and their corresponding line numbers on a document that is read in by the program. I can output the map and everything with the words and their line numbers but I'm confused on how to change how they output. So here is the code:
here is the main:
#include <iostream>
#include <string>
#include <vector>
#include <set>
#include <algorithm>
#include <fstream>
#include "dictionary.h"
#include "document.h"
using namespace std;
void sentancetoword(string sentance, set<string> words, int lineNum)
{
dictionary d;
document doc;
bool wordCheck;
string word;
stringstream ss(sentance);
while (ss >> word)
{
wordCheck = d.findWord(word, words);
if(!wordCheck)
{
doc.missingMap(word, lineNum);
}
}
doc.displayMap();
}
string letterCheck(string sentance)
{
for(unsigned i = 0; i < sentance.length(); i++)
{
if (!isalpha(sentance[i]))
{
sentance[i] = ' ';
}
}
return sentance;
}
int main(int argc, char* argv[])
{
dictionary dic;
document doc;
set<string> words;
set<string>::iterator it;
string doc_word;
int lineNum = 1;
ifstream in;
in.open(argv[1]);
string word;
while (in >> word)
{
transform(word.begin(), word.end(), word.begin(), ::tolower);
words.insert(word);
}
in.close();
//dic.makeSet(words);
ifstream in2;
in2.open(argv[2]);
while (getline(in2, doc_word))
{
transform(doc_word.begin(), doc_word.end(), doc_word.begin(), ::tolower);
doc_word = letterCheck(doc_word);
sentancetoword(doc_word, words, lineNum);
lineNum++;
}
in2.close();
system("pause");
return 0;
}
#include "document.h"
document::document(void){}
document::~document(void){}
void document::missingMap(string word, int lineNum)
{
misspelled[word].push_back(lineNum);
}
void document::displayMap()
{
for (map<string, vector<int>>::iterator i = misspelled.begin(); i != misspelled.end(); i++)
{
cout << i->first << ": ";
for (vector<int>::iterator j = i->second.begin(); j != i->second.end(); j++)
{
cout << *j << endl;
}
}
}
so the last function is doing the outputting of the map and it outputs as follows:
debugging: 1
process: 2
removing: 2
programming: 3
process: 4
putting: 4
but i need it to output like this:
debugging: 1
process: 2 4
programming: 3
putting: 4
removing: 2
is there something I'm doing wrong in the code or do i need to add a sort function to sort it by the words? I'm honestly lost and don't know where to go from here to get it to output only the word one time followed by the line numbers it appears on. If anyone could help that would be great, and if any more information is needed I'll be happy to add it to the question! Thanks!
Your output doesn't make sense, though I think you will want to do this:
cout << i->first << ": ";
for (vector<int>::iterator j = i->second.begin(); j != i->second.end(); j++)
{
cout << *j << " ";
}
cout << "\n"; //endl is okay, but I prefer only for I really do need to flush the stream
I'm trying to read from a file, and make a vector of all the words from the file. What I tried to do below is have the user input the filename, and then have the code open the file, and skip characters if they aren't alphanumeric, then input that to a file.
Right now it just closes immediately when I input the filename. Any idea what I could be doing wrong?
#include <vector>
#include <string>
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
int main()
{
string line; //for storing words
vector<string> words; //unspecified size vector
string whichbook;
cout << "Welcome to the book analysis program. Please input the filename of the book you would like to analyze: ";
cin >> whichbook;
cout << endl;
ifstream bookread;
//could be issue
//ofstream bookoutput("results.txt");
bookread.open(whichbook.c_str());
//assert(!bookread.fail());
if(bookread.is_open()){
while(bookread.good()){
getline(bookread, line);
cout << line;
while(isalnum(bookread)){
words.push_back(bookread);
}
}
}
cout << words[];
}
I think I'd do the job a bit differently. Since you want to ignore all but alphanumeric characters, I'd start by defining a locale that treats all other characters as white space:
struct digits_only: std::ctype<char> {
digits_only(): std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table() {
static std::vector<std::ctype_base::mask>
rc(std::ctype<char>::table_size,std::ctype_base::space);
std::fill(&rc['0'], &rc['9']+1, std::ctype_base::digit);
std::fill(&rc['a'], &rc['z']+1, std::ctype_base::lower);
std::fill(&rc['A'], &rc['Z']+1, std::ctype_base::upper);
return &rc[0];
}
};
That makes reading words/numbers from the stream quite trivial. For example:
int main() {
char const test[] = "This is a bunch=of-words and 2#numbers#4(with)stuff to\tseparate,them, I think.";
std::istringstream infile(test);
infile.imbue(std::locale(std::locale(), new digits_only));
std::copy(std::istream_iterator<std::string>(infile),
std::istream_iterator<std::string>(),
std::ostream_iterator<std::string>(std::cout, "\n"));
return 0;
}
For the moment, I've copied the words/numbers to standard output, but copying to a vector just means giving a different iterator to std::copy. For real use, we'd undoubtedly want to get the data from an std::ifstream as well, but (again) it's just a matter of supplying the correct iterator. Just open the file, imbue it with the locale, and read your words/numbers. All the punctuation, etc., will be ignored automatically.
The following would read every line, skip non-alpha numeric characters and add each line as an item to the output vector. You can adapt it so it outputs words instead of lines. I did not want to provide the entire solution, as this looks a bit like a homework problem.
#include <vector>
#include <sstream>
#include <string>
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string line; //for storing words
vector<string> words; //unspecified size vector
string whichbook;
cout << "Welcome to the book analysis program. Please input the filename of the book you would like to analyze: ";
cin >> whichbook;
cout << endl;
ifstream bookread;
//could be issue
//ofstream bookoutput("results.txt");
bookread.open(whichbook.c_str());
//assert(!bookread.fail());
if(bookread.is_open()){
while(!(bookread.eof())){
line = "";
getline(bookread, line);
string lineToAdd = "";
for(int i = 0 ; i < line.size(); ++i)
{
if(isalnum(line[i]) || line[i] == ' ')
{
if(line[i] == ' ')
lineToAdd.append(" ");
else
{ // just add the newly read character to the string 'lineToAdd'
stringstream ss;
string s;
ss << line[i];
ss >> s;
lineToAdd.append(s);
}
}
}
words.push_back(lineToAdd);
}
}
for(int i = 0 ; i < words.size(); ++i)
cout << words[i] + " ";
return 0;
}