C++ input from file in vim - c++

I have a C++ file code.cpp, and an input file input.txt. After compiling, I want to run the file from vim like code.exe < input.txt. Doing !$code_dir < $input_dir does not work. What's the fix?

Vim perfectly supports
:!path/to/executable < other/path/to/file
It doesn't work with :term path/to/exec < path/to/file though -- unlike neovim that has no troubles here.
Given the simple
#include <iostream>
int main()
{
std::string line;
while (std::getline(std::cin, line)) {
std::cout << line << "\n";
}
}
compiled with :make %< (I'm using g++-cygwin and not g++-mingw), :!./%< < % works perfectly.
In case what I've just described doesn't work, as I see a windows tag, maybe your &shell* options are incorrectly set? With Windows, I had to change the default as I use the native gvim with cygwin. In a pure windows environment, I make sure my settings are (don't ask me why, this is the result of 15-20 year old experimentations and I definitively don't remember all the tests I made)
let &shell=$COMSPEC
set shellslash
set shellcmdflag=/c
set shellquote=
set shellxquote=
set shellredir=>
set shellpipe=>

Related

getline unreliable on macOS?

as a school project I have to code a video game with SDL2, imgui and SFML and I'm facing a really weird problem :
getline seems unreliable on macOS but not on linux
Let me explain, when I compile and run my code, I am able to read my configuration file properly and display the data on screen : it is working everytime on my linux computer but on my macbook it is working like 1 time out of 5.
My configuration file :configuration file
how the information is supposed to be displayed (working properly on linux but not everytime on macOS) : how it is when it works
The code :
// Récupération des derniers paramètres
std::ifstream fichierSauvegardeR ("data/save.txt");
if (fichierSauvegardeR.is_open())
{
getline(fichierSauvegardeR, strNbDes);
strcpy(buf_nb_des, strNbDes.c_str());
getline(fichierSauvegardeR, strNbJoueurs);
strcpy(buf_nb_joueurs, strNbJoueurs.c_str());
// getline(fichierSauvegardeR, strNomJoueur);
// strcpy(noms_joueurs[0], strNomJoueur.c_str());
for (int i = 0; i < nbJoueurs; i++) {
if(!getline(fichierSauvegardeR, strNomJoueur))
{
break;
}
else
{
strcpy(noms_joueurs[i], strNomJoueur.c_str());
}
}
fichierSauvegardeR.close();
}
Note that, the first 2 lines of the configuration file are always properly read (even on macOS), what doesn't work is the other lines (I've tried replacing the "\n" by std::endl and it didn't changed anything)
Without responding to your answer (i don't have a mac for testing). I see that you use many C features. I recommend you to use "istringstream" to parse your file.
Something like this: https://stackoverflow.com/a/9551101/12374897

gnuplot.exe path not found for writing in c++

I'm new to gnuplot and was trying to just make a plot of random numbers to visualize the distribution of the psuedo-random rand() function in c++. However, I came across a problem that appears common: the path was not found for gnuplot.exe.
Possible relevant information before I go on:
Running Windows 10 64-bit. Compiler: CLion. gnuplot.exe path: C:\Program Files (x86)\gnuplot\bin I have the latest version of gnuplot form sourceforge (as of 10/21/19: 5.2.7 I believe).
I have already checked these questions:
gnuplot-cpp cannot feed command to pipe
Gnuplot & C++: Can't find gnuplot neither in PATH nor in "
I've looked through many other questions but they weren't as relevant to the problem I have. I tried implementing the answers there and did not make any progress. I have the same gnuplot_i.hpp file and changed the problem line to:
#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__)
std::string Gnuplot::m_sGNUPlotFileName = "gnuplot.exe";
std::string Gnuplot::m_sGNUPlotPath = "C:/Program_Files(x86)/gnuplot/bin/";
I also have the correct PATH set for gnuplot as a environmental variable and can execute gnuplot from cmd.
The errors I've gotten were:
Cannot find gnuplot neither in PATH nor in "C:/Program_Files(x86)/gnuplot/bin"
and, when I removed the "_" from the path above and replaced it with a space:
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.
This last one is the only one that appears now, even though I do not have the space anymore, as it's been mentioned that having spaces in the path is a known bug with gnuplot. I am aware that Program_Files(x86) is not a real path, I was just trying to get rid of the second error message.
My main.cpp, if it even matters:
#include <iostream>
#include "gnuplot_i.h"
#include <cstdlib>
#include <vector>
using namespace std;
int main(int argc, char* argv[]) {
try {
Gnuplot rand_plot("lines");
}
catch (GnuplotException ge) {
cout << ge.what() << endl;
}
return 0;
}
Any help on solving these errors would be greatly appreciated.
Botje in the comments solved the issue. Changing lines 1714-1715 in gnuplot_i.h to std::string tmp = std::string("\"") + Gnuplot::m_sGNUPlotPath + "/" + Gnuplot::m_sGNUPlotFileName + std::string("\""); fixed the problem.

cin keyword not working in text editor

I'm using the scite text editor (I cannot make use of any IDE or compiler since I'm required to also utilize Makefiles which is only possible if I use some sort of text editor) for all of my coding in c++. However, I'm consistently facing the same challenge; the text editor (I've attempted this on multiple ones including codepad and sublime text) isn't reading any input from the keyboard. Here is the source code:
#include <iostream>
#include <iomanip>
using namespace std;
const int SIZE_OF_ARRAY = 5;
int main(){
int x, y;
int counter = 0;
int elements[SIZE_OF_ARRAY];
cout << "Please enter a number ";
cin >> x;
cin.ignore();
cout << "Please enter a choice ";
cin >> y;
if(y == 1){
for(int i = 0; i < SIZE_OF_ARRAY; i++)
elements[i] = -1*SIZE_OF_ARRAY + x;
for(int j = 0; j < SIZE_OF_ARRAY; j++)
cout << elements[j] << " ";
}
else if(y == 2){
for(int i = 0; i < SIZE_OF_ARRAY; i++){
if(i == 0)
elements[i] = -1*x;
else{
elements[i] = elements[i-1] + 1;
}
}
for(int j = 0; j < SIZE_OF_ARRAY; j++)
cout << elements[j] << " ";
}
else if(y == 3){
for(int i = 0; i < SIZE_OF_ARRAY; i++){
counter++;
elements[i] = 7*x*counter;
}
for(int j = 0; j < SIZE_OF_ARRAY; j++)
cout << elements[j] << " ";
}
}
The program is supposed to take as an input any number from the user and, depending on a numeric choice (between one and three) entered by the user, manipulate the value first entered somehow.
Choice one (User picks first choice)
The program negates the size of the array and adds the number which the user first entered and fills the array with the resulting value.
Choice Two (User picks second choice)
The program negates the number entered by the user, places this in the first array location then each successive element is added one unit more than the previous one.
Choice Three (User picks third choice)
Fills the array with the first five multiples of seven. Then shifts each number by a factor equivalent to the number the user had first entered.
I've ran it on an IDE (Codeblocks) and it works perfectly well. However, on any text editor, the 'cout' statements are printed with the variables x and y taken to each be equal to zero rather than being set to the value entered from the keyboard. It doesn't even allow any keyboard input. Any answer regarding how I can fix this would be immensely appreciated.
Hoosain, continuing from the comments above, when you use an IDE, you must configure the path to your compiler as well as all compiler options you wish to use, and the location for the resulting executable and object files, etc. When you used CodeBlocks on windows, you essentially got lucky that CodeBlocks will automatically detect whether MinGW is installed and set its compiler configuration to allow you to build and run your code without you having to configure the compiler details. Geany is another editor that does a good job auto-detecting and using MinGW.
For the remaining IDE's it is up to you to configure them to find and use the compiler you have installed (MinGW), as well as configuring all desired compiler options (at minimum enable compiler warning with -Wall -Wextra).
That is where new programmers who have only used an IDE configured for them run into problems... Before you can tell an IDE where your compiler is located and which compiler options you want to use, you have to know where you compiler is located and understand what minimum set of compiler options you should use.
The way you learn to use a compiler is with the good old command line. (yep, that's cmd.exe on windows, often labeled as the "DOS Prompt" in earlier versions) An IDE is just a front-end to your compiler that executes the same commands you can simply enter on the command line to compile your program.
Learning how to use your compiler will save you an incredible amount of time when learning to code. You can simply open a command prompt and compile any file you wish, without setting up a project, etc.. When learning to code, trying to shoehorn small examples into an IDE is much more time consuming and often more trouble than it is worth. Rather than worry how to use an IDE, focus on "how to use your compiler" first.
Since you have MinGW installed on windows, all you have to do to be able to compile from the command prompt is add the path to the MinGW bin directory to your User Environment. You do that by adding the PATH as an Environment Variable here:
Start Menu-> (rt-click on Computer)-> Properties->
Advanced System Settings-> (Advanced tab)-> Environment Variables
In the Top window (your user variables), click to add (or edit) the PATH "Variable name". Generally, if you installed MinGW in the default location, you simply add the path as the "Variable value":
c:\MinGW\bin;c:\MinGW\mingw32\bin
(verify the path on your computer)
(note: windows separates path components by the semi-colon, so if there is already a PATH variable set, just add a semi-colon between what is there and what you add. Also if you already have a command prompt open, you must close it and open it again for the new path to take effect) Just open Start Menu-> Accessories-> Command Prompt (you can rt-click on the icon (top-left) and choose Properties to set the font (recommend Lucida Console 12) and height/width)
Now you have configured your command prompt to allow you to compile any file at any location within your filesystem. For example, I tested with the code you posted (I modified it to add prompts for the information). Compiling it is a piece of cake. I keep my executables in a bin directory to keep sources and binaries separate.
I named your file array_get.cpp.
Compile
Then just enter the normal g++ compiler command, and at minimum use -Wall -Wextra options to enable compiler warnings (you can add -pedantic and whatever additional warnings you want, I would recommend at least adding -Wshadow so your compiler will warn on any variables you declare in multiple scopes that could conflict). The -o option allows you to specify the location of the executable (I just use a separate bin directory as explained above). So to compile and link your code into bin\array_get.exe all I have to enter is:
C:\Users\david\Documents>g++ -Wall -Wextra -o bin\array_get array_get.cpp
(do not accept code until it compiles without warning -- read any warning (it gives line of problem), understand what it is telling you, and go fix it)
Example Use/Output
C:\Users\david\Documents>bin\array_get.exe
Please enter a number: 21
Please enter a choice (1-3): 3
147 294 441 588 735
That's it. Since MinGW uses gcc, the compiler commands you use on windows are the exact same you would use in Linux, so learning to compile from the command line pays double-benefit.
Now you have the luxury of using any text-editor to edit your code while you have the command prompt simply and easily re-compile as you wish until your code is correct. No project dialogs, no mess of a different folder for every file, just the freedom to compile any file you wish -- right from the command line. (I actually separate my sources in directory by type, e.g. c, cpp), you find what works best for your. I also use a simple bat file that takes the exename and source.cpp names as arguments and then compiles with the options I set -- it just cuts down on typing :)
Further, since you now where your compiler is located, and which options to use, you can open the Settings window on any IDE and set the appropriate compiler command and compiler options to allow the IDE compile your code for you. Give it a try, and let me know if you have further questions.

sublime text doesn't proceed my code after cin. what should I do?

all
I'm pretty new to programming and I'm currently teaching myself C++ with sublime text editor. I'm having a problem where the code does not proceed after I input something through cin. For example,
#include <iostream>
using namespace std;
int main() {
string password = "password";
cout << "Enter your password: " << flush;
string input;
cin >> input;
if(input == password) {
cout << "Password accepted." << endl;
} else {
cout << "Access denied." << endl;
}
return 0;
}
After I put my input, it doesn't cout anything such as "password accepted" or "access denied". Does anyone know how to solve this problem and make it work? Thanks.
As mentioned your code does work as expected.
The issue is when you build a c++ program in sublime text it will compile that file and then run. What you see is sublime text piping the output from your program back to a window within sublime text.
Sublime does not have the ability to send input back to your program. Hence why your program "does not proceed after I input something through cin". There are some plugins available on the linux version of sublime that give access to a full terminal emulator, I have not tried using one of these but they do exist.
What I would recommend is that you learn how to use the gnu tool chain using the command line.
This is an old post but since I faced the same problem and this was the first page to pop up when I searched for it, I'll post the solution I think best for other newbros (Does this term work outside of Eve online? Who knows...).
Do remember I am new as well and what I am saying is probably the wrong approach and bad for you, but it will get you started....
Option 1: Use Sublime text to edit and run the file on terminal as everyone suggests. After the first few times it gets extremely repetitive and annoying. As long as you know how to do it, you should be fine. NOT RECOMMENDED.
Option 2: Use VS Code or other IDEs. The problem with this one is that sublime text is just faster to start which is primarily why I like subl. In all honesty VS code is also fast and responsive and I think switching to it is not at all a bad idea.
Option 3: If you still wanna continue using Sublime text. Set it up for something they call competitive programming. Skip the 'bits/stdc++.h' part and do everything else. Follow this link: https://www.geeksforgeeks.org/setting-up-sublime-text-for-cpp-competitive-programming-environment/
In the rare event this webpage stops existing in the future:
Step 1: Have mingw/mingw64 compiler installed and added to path. (You will find plenty of resources that will help you with that).
Step 2:
(i) Open Sublime Text editor and then go to Tools > Build System > New Build System.
(ii) Paste the following code in the file and save it.
{
"cmd": ["g++.exe", "-std=c++17", "${file}",
"-o", "${file_base_name}.exe",
"&&", "${file_base_name}.exe<inputf.in>outputf.out"],
"shell":true,
"working_dir":"$file_path",
"selector":"source.cpp"
}
(iii) Name the file as “CP.sublime-build“ (or anything really, just name something you know so that you can find it from the Tools > Build system list. Also make sure to keep the '.sublime-build' part.)
Step 3: Create these three new files and save them in the same folder. (Keep it somewhere where you store your codes or something like that).
file.cpp: The file for writing the code.
inputf.in: The file where we will be giving the input.
outputf.out: The file where the output will be displayed.
//Also don't change the names of these files since this is part of the code we had earlier.
Step 4: Setting up Window layout:
-Select View > Layout > Columns : 3. This will create three columns in the workspace. Move the three files into three columns.
-Select View > Groups > Max Columns : 2.
-Select the build system we just created from Tools > Build System > CP (or whatever you named it).
This will create a live environment for you write and run/test code at the same time in subl. o7
One way to do this in Submlime is to create a new Build System.
Goto Tools > Build System > New Build System..
Paste something like below into the open file and save it.
{
"cmd": ["bash", "-c", "/usr/bin/g++ '${file}' -o '${file_path}/${file_base_name}' && open -a Terminal.app '${file_path}/${file_base_name}'"]
}
*This is for Mac OSX, you will have the change it for your environment.
Change Build System to saved name
When you build next time, there will be a new Terminal App window waiting for the cin input.

C++ Opening file with *i pointer, Overrides in Linux but not in Windows

So I've got this program working in Windows, and I'm trying to make it also work on a Linux machine. I believe the Linux machine is running an outdated version of g++ compiler but that is out of my control. Anyway, heres my function:
for (vector<string>::iterator i = groups.begin(); i != groups.end(); ++i)
{
inStream.open((*i + "List.txt").c_str());
while (getline(inStream, next))
{
if (next == n) {
memberOf.push_back(*i);
}
}
inStream.close();
}
The issue lies with the inStream.open() call. In windows this works fine, but in Linux it seems that *i (for example lets say that *i is pointing to "Tigers") is being overridden and therefore the call is just inStream.open("List.txt"); as opposed to inStream.open("TigersList.txt");
I've tried various ways of solving this, such as setting string k = *i; which works in itself in the sense that if I call cout << k; it prints "Tigers". However as soon as I try to concatenate "List.txt" to the end it just overrides "Tigers" and I'm left with only "List.txt"
ex:
k += "List.txt";
k.append("List.txt");
etc. Nothing seems to work in Linux, however everything I've tried has the same (correct) end result in windows.
What am I doing wrong???
Edit: inStream is an ifStream object.
memberOf is another vector of strings.
It sounds like you are reading Tigers from a file that contains Windows line endings. If you read this file in Linux, then reading the line:
Tigers\r\n
will result in your string in memory being Tigers\r. Then when you concatenate to it, even though the result actually ends up being Tigers\rList.txt, when you print it out then your terminal treats \r as carriage return and so List.txt overwrites Tigers on your screen.
Of course, opening the file fails because the filename didn't contain an embedded \r.
To fix this you could do one of the following:
In Linux, make sure that the file you're opening has Linux line endings (e.g. run dos2unix on it)
Update your program to look for and discard a \r on the end of a line that it has read from the file.