Is there a better way I could be receiving this input? C++ - c++

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;
}
}

Related

arrange line in txt file in ASCII order using array and display them

#include <stdio.h>
#include <string.h>
#include <fstream>
#include <iostream>
using namespace std;
int main() {
ifstream infile; // ifstream is reading file
infile.open("read.txt"); // read.txt is the file we need to read
std::cout << infile;
string str;
if (infile.is_open()) {
while (getline(infile, str)) {
char str[2000], ch;
int i, j, len;
len = strlen(str);
for (i = 0; i < len; i++) {
for (j = 0; j < (len - 1); j++) {
if (str[j] > str[j + 1]) {
ch = str[j];
str[j] = str[j + 1];
str[j + 1] = ch;
}
}
}
}
cout << "\nProcessed data:" << str;
}
return 0;
}
My txt file:
Today is a fine day.
It’s sunny.
Let us go out now!
My result should be:
.Taaaddefiinosyy
’.Innsstuy
!Legnooosttuuw
Spaces is consider here as well.
I'm new to C++.
I need some pros help.
Thank you very much!
Making use of the STL:
Read your file line by line into a std::string using std::getline.
Sort every line using std::ranges::sort.
Print it.
The example below:
also uses the fmt library instead of std::cout, and
reads from a std::istringstream instead of a std::ifstream.
[Demo]
#include <algorithm> // sort
#include <fmt/core.h>
#include <sstream> // istringstream
#include <string> // getline
int main() {
std::istringstream iss{
"Today is a fine day.\n"
"It's sunny.\n"
"Let us go out now!\n"
};
fmt::print("Original file:\n{}\n", iss.str());
fmt::print("Processed file:\n");
std::string line{};
while (std::getline(iss, line)) {
std::ranges::sort(line);
fmt::print("{}\n", line);
}
}
// Outputs:
//
// Original file:
// Today is a fine day.
// It's sunny.
// Let us go out now!
//
// Processed file:
// .Taaaddefiinosyy
// '.Innsstuy
// !Legnooosttuuw
Your code does not work, because:
The line std::cout << infile; is wrong. If you want to print the result of istream::operator bool() in order to determine whether the file was successfully opened, then you should write std::cout << infile.operator bool(); or std::cout << static_cast<bool>(infile); instead. However, it would probably be better to simply write std::cout << infile.fail(); or std::cout << !infile.fail();.
The function std::strlen requires as a parameter a pointer to a valid string. Maybe you intended to write str.length()? In that case, you should delete the declaration char str[2000], because it shadows the declaration string str;.
You should print the sorted result immediately after sorting it, before it gets overwritten by the next line. Currently you are only printing the content str a single time at the end of your program, so you are only printing the last line.
After performing the fixes mentioned above, your code should look like this:
#include <stdio.h>
#include <string.h>
#include <fstream>
#include <iostream>
using namespace std;
int main() {
ifstream infile; // ifstream is reading file
infile.open("read.txt"); // read.txt is the file we need to read
std::cout << infile.fail();
string str;
if (infile.is_open()) {
while (getline(infile, str)) {
char ch;
int i, j, len;
len = str.length();
for (i = 0; i < len; i++) {
for (j = 0; j < (len - 1); j++) {
if (str[j] > str[j + 1]) {
ch = str[j];
str[j] = str[j + 1];
str[j + 1] = ch;
}
}
}
cout << "\nProcessed data:" << str;
}
}
return 0;
}
For the input
Today is a fine day.
It's sunny.
Let us go out now!
this program has the following output:
0
Processed data: .Taaaddefiinosyy
Processed data: '.Innsstuy
Processed data: !Legnooosttuuw
Note that the input posted in your question contains a forward tick ’ instead of an apostrophe '. This could cause trouble. For example, when I tested your program, this forward tick was encoded into a multi-byte UTF-8 character, because it is not representable in 7-bit US-ASCII. This caused your sorting algorithm to fail, because it only supports single-byte characters. I was only able to fix this bug by replacing the forward tick with an apostrophe in the input.

Need Help Debugging my Code That Reverses the Words in a String

I need some help debugging my code. This code is intended to reverse the words in a string that is in the form of a sentence [assuming that the string does not have a "." at the end]. For some reason what I'm getting as an output is the indented output plus an extra space after the first word as well as the indented output minus the first word. I am a beginner at coding; so if possible, I would appreciate more simple to understand solutions, or a solution that uses a loop, strings, and arrays.
Sample Input:
My name is Edward
Intended Output:
Edward is name My
Output Received:
Edward is name
Here is my code so far:
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
int main() {
string s, n, a;
getline(cin, s);
for (int i = s.length(); i >= 0; i--){
if (s[i] != 32 ) {
n += s[i];
}
else {
for (int j = n.length() -1; j >= 0; j--){
a += n[j];
}
cout << a << ' ';
n.clear();
a.clear();
}
}
cin.ignore();
getchar();
return 0;
}
Also, I just noticed that there is also an extra space at the end. If there is a way to maybe cancel outputting the last space; please tell me.
Thanks for reading, I appreciate your help.
As mentioned in my comment, you're reversing the whole string by characters, but you need to split up for words and reverse:
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
string s, n;
getline(cin, s);
std::istringstream iss(s);
std::vector<string> words;
while(iss >> n) {
words.push_back(n);
}
std::reverse(words.begin(),words.end());
for(auto word : words) {
std::cout << word << ' ';
}
getchar();
return 0;
}
Live Demo
So this is really just an additional step of abstraction from πάντα ῥεῖ's excellent answer. You can use istream_iterator and ostream_iterator to further simplify your code.
The entire code to answer your question can be boiled down to:
const vector<string> words{ istream_iterator<string>(cin), istream_iterator<string>() };
copy(crbegin(words), crend(words), ostream_iterator<string>(cout, " "));
Live Example
Edit: Thanks for the help from the comments and answers, I fixed the problem with the extra space and added something at the end that outputs the final word. It's not perfect, but it works. :)
#include <iostream>
#include <string>
using namespace std;
int main() {
string s, n;
getline(cin, s);
for (int i = s.length() -1; i >= 0; i--){
if (s[i] != 32) {
n += s[i];
}
else {
for (int j = n.length() -1; j >= 0; j--){
cout << n[j];
}
cout << ' ';
n.clear();
}
}
for (int k = n.length() -1 ; k >= 0; k--)
cout << n[k];
cin.get();
return 0;
}
you can use strrev(); function instead all of your for block.

Cannot Properly Print Contents of Vector

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] << ' ';
}

Outputting a map in a specific order

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

array size and split of string

Ok guy i had to make a program to split elements of a string. And after that print those words.
there are some problems i am facing:
1) the array prints more than the size of the words in string i want that it should end printing as soon as last word is printed. i tried to prevent that but it always gives runtime error when i try to break at the last word.
2)is there any other efficient way to split and print ???
#include <sstream>
#include <iostream>
#include<cstdio>
#include<cstdlib>
#include <string>
using namespace std;
int main()
{
std::string line;
std::getline(cin, line);
string arr[1000];
int i = 0;
int l=line.length();
stringstream ssin(line);
while (ssin.good() && i < l)
{
ssin >> arr[i];
++i;
}
int size = sizeof(arr) / sizeof(arr[0]);
for(i = 0; i <size; i++){
cout << arr[i] << endl;
}
return 0;
}
int size = sizeof(arr) / sizeof(arr[0]);
That is a compile time value, and it's always going to be the number of elements in your array (1000). It has no idea how many strings you assigned to in your loop. You stored the number of successfully read strings (plus 1) in the i variable, so you could do this instead:
int size = i - 1;
But if it were up to me, I would just use a growable structure, like vector (#include <vector>)
std::vector<std::string> arr;
std::string temp;
while (ssin >> temp)
{
arr.push_back(temp);
}
for (auto const & str : arr)
{
std::cout << str << std::endl;
}
/* If you're stuck in the past (can't use C++11)
for (std::vector<std::string>::iterator = arr.begin(); i != arr.end(); ++i)
{
std::cout << *i << std::endl;
}
*/
For general purpose character based splitting, I would much prefer boost::split (I know you can't use it, but for future reference)
std::vector<std::string> arr;
boost::split(arr, line, boost::is_any_of(".,;!? "));
Read up on the function strtok. It is old school but very easy to use.
1) there are a couple of changes you should make to your program:
#include <sstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
std::string line("hello string world\n");
string arr[1000];
int i = 0;
stringstream ssin(line);
while (ssin.good() && i < 1000)
{
ssin >> arr[i++];
}
int size = i-1;
for(i = 0; i < size; i++){
cout << i << ": " << arr[i] << endl;
}
return 0;
}
namely, you don't want to print sizeof(arr)/sizeof(arr[0]) (i.e. 1000) elements. There is no point in the condition i < l
2) stringstream is fine if you just want to separate the single strings; if more is needed, use boost/tokenizer for splitting strings. It's modern c++, once you try it you'll never come back!
this is the best method i think no worry now
#include <sstream>
#include <iostream>
#include<cstdio>
#include<cstdlib>
#include <cstring>
#include <string>
using namespace std;
int main ()
{
std::string str;
std::getline(cin, str);
string arr[100];
int l=0,i;
char * cstr = new char [str.length()+1];
std::strcpy (cstr, str.c_str());
// cstr now contains a c-string copy of str
char * p = std::strtok (cstr,".,;!? ");
while (p!=0)
{
//std::cout << p << '\n';
arr[l++]=p;
p = strtok(NULL,".,;!? ");
}
for(i = 0; i <l; i++)
{
cout << arr[i] << endl;
}
delete[] cstr;
return 0;
}