Task: A text input as command-line argument is to be written to a file.
Issue: Some encoding conversion is happening somewhere, so the file doesn't contain the exact text which was input. e.g. s%3A_blabla becomes s:_blabla . (Some HTML kind of thing)
Environment: Visual Studio 2019, C++17
How is the command-line argument being supplied: Using Smart Command Line Arguments extension. Also read 'Edit 1'.
How is the input being processed:
I've tried two methods:
static std::vector<const char*> args;
for (size_t i = 0; i < __argc; i++)
{
args.push_back(__argv[i]);
};
..........
std::string filePath = "random.txt";
std::string final_write(args[i+1]); //some value of i is chosen using a for loop
std::cout<<final_write<<std::endl;//this will print "s:_blabla"
std::ofstream out(filePath);
out << final_write;
Second method:
#include <atlstr.h>
........
LPWSTR *szArgList;
int argCount;
szArgList = CommandLineToArgvW(GetCommandLineW(), &argCount);
for (int i = 0; i < argCount; i++)
{
CString pathCString(szArgList[i]);
std::cout<<pathCString<<std::endl; //Here also it prints "s:_blabla" for appropriate i
}
What I know:
I don't think cout is at fault, because in first case the file writing also give the same transformed output, and if I explicitly modify the string and add "%3A" to it, the cout is able to display that normally. I've not tried writing to file in the second case, as cout tells that something fishy has already happened during input.
It might be the extension, or an encoding issue somewhere else, I'm not sure. Any help?
Edit 1: As suggested, I checked the behaviour after removing the command line extension. I took input from Properties->Debugging section->Command Arguments, and I still face the same issue. Disabled the extension too.
Related
I have the following snippet which I'm trying to log into the terminal for debug purposes:
void DebugVector(vector<string> word_list) {
size_t word_count = word_list.size();
for (int i = 0; i < word_count; i++) {
for (int j = 0; j < word_count; j++) {
if (i == 156 && j == 156) {
fflush(stdout);
printf("We're supposed to find the word with value lares; ");
fflush(stdout);
const char *wordi = word_list[i].c_str();
const char *wordj = word_list[j].c_str();
printf("Actual values are %s and %s", wordi, wordj);
fflush(stdout);
}
}
}
}
I'm using Windows with the Windows Subsystem for Linux feature turned on and when I'm building the program with the following command
cl.exe /Zi /EHsc /nologo /Fe: C:\Users\user\Documents\VSCode_projects\test_program\main.exe C:\Users\user\Documents\VSCode_projects\test_program\main.cpp
and after I run it, the output is
We're supposed to find the word with value lares; Actual values are lares and lares
However, when I'm running it from the bash terminal in Windows, after building it with the following command:
$ g++ main.cpp -o main-linux.exe && ./main-linux.exe
The output is
and laresosed to find the word with value lares; Actual values are lares
It looks like the cursor is moved to the beginning of the line right after printing the first string. From what I understand c_str only outputs null terminated values, so I don't understand why this could happen.
I've tried creating a concatenated string, using cout instead, and I'm getting pretty much the same result. Also, the word_list has about 10,000 words in it, so I believe I'm not accessing any out of range values.
Is there anything that I can do here to make the program output the correct value?
The issue was from the difference getline() makes when compiled with g++ and cl.exe. The vector was generated via this code:
if (list_file.is_open()) {
while (getline(list_file, line)) {
word_list.push_back(line);
}
}
getline() deals with new line in windows differently which is not very surprising. g++ will read the word including the carriage return (\r) value while cl.exe won't. This results in the print issue.
you can access vector elements with subscripts like array
because its object and it has address storage values
YOU CAN ALSO use .at() method of vector
https://www.geeksforgeeks.org/vector-in-cpp-stl/
here in the element access method
and c_str() here works fine! no issue with that...
EDIT: Problem solved! Turns out Windows 7 wont let me read/ write to files without explicitly running as administrator. So if i run as admin it works fine, if i dont i get the weird results i explain below.
I've been trying to get a part of a larger program of mine to read a file.
Despite trying multiple methods(istream::getline, std::getline, using the >> operator etc) All of them return with either /0, blank or a random number/what ever i initialised the var with.
My first thought was that the file didn't exist or couldn't be opened, however the state flags .good, .bad and .eof all indicate no problems and the file im trying to read is certainly in the same directory as the debug .exe and contains data.
I'd most like to use istream::getline to read lines into a char array, however reading lines into a string array is possible too.
My current code looks like this:
void startup::load_settings(char filename[]) //master function for opening a file.
{
int i = 0; //count variable
int num = 0; //var containing all the lines we read.
char line[5];
ifstream settings_file (settings.inf);
if (settings_file.is_open());
{
while (settings_file.good())
{
settings_file.getline(line, 5);
cout << line;
}
}
return;
}
As said above, it compiles but just puts /0 into every element of the char array much like all the other methods i've tried.
Thanks for any help.
Firstly your code is not complete, what is settings.inf ?
Secondly most probably your reading everything fine, but the way you are printing is cumbersome
cout << line; where char line[5]; be sure that the last element of the array is \0.
You can do something like this.
line[4] = '\0' or you can manually print the values of each element in array in a loop.
Also you can try printing the character codes in hex for example. Because the values (character codes) in array might be not from the visible character range of ASCII symbols. You can do it like this for example :
cout << hex << (int)line[i]
This is related to the answer to my previous question by Mats Petersson.
According to his method, I can successfully save the line in the header and print it out later whenever I want. However, I now want to save the whole header to print it later. I am using append() to fulfill that purpose. But it's not working.
Here is the code that is outside the two functions:
static map<string, string> headermap;
static char headerline[1024];
Here is the code for the reading function:
string paragraph;
for (int i=0; i<8; ++i) {//8 lines of the header
fgets(buffer,1024,fp);
if(buffer[0] == '#'){
paragraph = paragraph.append(buffer);
}
}
headermap[filename] = paragraph;
Here is the code for the writing function:
const char *headerline = headermap[filename].c_str();
fprintf(fp, headerline);
Previously I was using headerline[i] = buffer[i]; instead of paragraph.append(buffer); in the reading function. And headermap[filename] = headerline; instead of headermap[filename] = paragraph;.
When I print, nothing is printed to the output file. As i said before, previously when I tried to print just one line, it works fine.
I have a C++ program which exposes a Python interface to execute users' embedded Python scripts.
The user inserts the path of the Python script to run and the command-line arguments.
Then the script is executed through
boost::python::exec_file(filename, main_globals, main_globals)
To pass the command-line arguments to the Python script we have to set them through the Python C-API function
PySys_SetArgv(int args, char** argv)
before calling exec_file().
But this requires to tokenize the user's string containing the command-line arguments to get the list of arguments, and then to pass them back to the Python interpreter through PySys_SetArgv.
And that's more than a mere waste of time, because in this way the main C++ program has to take the responsibility of tokenizing the command-line string without knowing the logics behind, which is only defined in the custom user's script.
A much nicer and cleaner approach would be something like this in metacode:
string command_line_args = '-v -p "filename" -t="anotherfile" --list="["a", "b"]" --myFunnyOpt'
exec_file( filename, command_line_args, ...)
I spent hours looking at the Boost and Python C-API documentation but I did not find anything useful.
Do you know if there is a way to achieve this, i.e. passing a whole string of command line
arguments to an embedded Python script from C++?
Update:
As Steve suggested in the comments here below, I solved my problem tokenizing the input string, following https://stackoverflow.com/a/8965249/320369.
In my case I used:
// defining the separators
std::string escape_char = "\\"; // the escape character
std::string sep_char = " "; // empty space as separator
std::string quote_char = ""; // empty string --> we don't want a quote char'
boost::escaped_list_separator<char> sep( escape_char, sep_char, quote_char );
because I wanted to be able to parse tuples containing strings as well, like:
'--option-two=("A", "B")'
and if you use:
escaped_list_separator<char> sep('\\', ' ', '"');
as in the original post, you don't get the quoted strings tokenized correctly.
Since you are not adverse to executing an external file, you can use a helper program to make your shell command do the parsing for you. Your helper program could be:
#include <stdio.h>
int main (int argc, char *argv[])
{
for (int i = 1; i < argc; ++i) printf("%s\n", argv[i]);
return 0;
}
And then you could have code that sends your single string of arguments to the helper program (perhaps using popen) and read back the parsed arguments, each arg on a separate line.
unparsed_line.insert(0, "./parser_helper ");
FILE *helper = popen(unparsed_line.c_str(), "r");
std::vector<std::string> args;
std::vector<const char *> argv;
std::string arg;
while (fgetstring(arg, helper)) {
args.push_back(arg);
argv.push_back(args.rbegin()->c_str());
}
pclose(helper);
The fgetstring routine is something I wrote that is like a cross between fgets and std::getline. It reads from the FILE * one line at a time, populating a std:string argument.
static bool
fgetstring (std::string &s, FILE *in)
{
bool ok = false;
std::string r;
char buf[512];
while (fgets(buf, sizeof(buf), in) != 0) {
++ok;
r += buf;
if (*r.rbegin() == '\n') {
r.resize(r.size()-1);
break;
}
}
if (ok) s = r;
return ok;
}
I seem to remember a post on SO that had a routine similar to this, but I couldn't find it. I'll update my post if I find it later.
I am currently developing an application, which gets the input from a text file and proceeds accordingly. The concept is the input file will have details in this fomat
A AND B
B OR C
Each and every line will be seperated by a blank space and the input must be taken from the text file and processed by logic. I use a TCPP compiler and i am facing problems reading the input. Please help me with the issue...
Reading input a line at a time is normally done with std::getline, something like this:
std::string line;
std::ifstream infile("filename");
while (std::getline(line, infile))
// show what we read
std::cout << line << "\n";
If you're having trouble with things like this, you might consider looking for a (better) book on C++ than whatever you're now (hopefully) using.
Following can be used straightaway:
BOOL ReadFile(CString filename)
{
BOOL bRead = TRUE;
std::ifstream m_strmFile;
m_strmFile.open(filename, std::ios::in);
char pszLine[256];
memset(pszLine, 256, 0);
if (m_strmFile)
{
// Read whatever number of lines in your file
for (unsigned int i = 0; i < 5/*number of lines*/; i++)
m_strmFile.getline(pszLine, 256);
// Do whatever you want to do with your read lines here...
}
else bRead = FALSE;
return bRead;
}
are you using headr files like:
include
or #include and you can make use of the fileobject.getline(), (do check its proper syntax.) function in C++ or for char by char use fileobject.get(ch) kind of function