How to pass array of strings to a main() - c++

I have not been successful on searching for this topic. I want to pass an array of strings to a C++ console app. The closest I have found is using argv(), but the number (variable) may be 50 strings which would be ugly on the calling side.
Is it possible to pass an array, or a structure to main()? I am totally open to which way to go, I have almost no experience with interprocess communication.

The conventional approach is just STDIN, as then you can send in whatever using pipes or redirection. As in: program < input
The second option is your first argument is a file to read this data from. As in program input.file
There are conventions that accommodate both, like where - as a filename is presumed to mean "read STDIN", or where no filename given means read from STDIN (e.g. grep), so you can have it both ways.
If your strings contain newlines which complicate framing you may want to use a format like INI, JSON, or YAML to read in the data.

Related

"Input is provided as CSV format via STDIN"

I'm working on a programming problem in C++, where I need to write a CSV parser. I've written this before for files, but the instructions state:
Input is provided as CSV format via STDIN. The first line is a header. The subsequent lines are data.
Here's an example of the input "file":
#id,time,amount
0,4,5
2,8,3
8,1,2
...
Now I'm a bit confused by this because I haven't worked with STDIN much since picking up C++ a few years ago. How exactly does one read in a csv file through STDIN? When I've used std::cin in the past, if I try to paste multiple lines, only the first line will get read.
The instructions of the programming problem did not make it clear how the input "file" will be fed in through STDIN, or perhaps there's some classical way it's done and my lack of knowledge makes me think it's unclear? Is there some standard way a CSV file is read in through STDIN?
All I am tasked to do is to process what comes through STDIN, and I'm not given how things are passed into STDIN. I feel like I need to know how things are passed in to know what I'm supposed to do? Like it could be passed in character by character, line by line, entry by entry, or the entire file at a time?

How to read .inp file in c++?

I have a dataset, a ".inp" format file, and I need to read this file in c++. However, the fopen() fread() method seemed to fail and read the wrong data(e.g. the first integer should be 262144, the fread yields an integer much larger than this nevertheless).
To be more specific, my ".inp" file contains a few integers and float points, how can I read them successfully in c++?
enter image description here
This is the screenshot of the "*.inp" file from Notepad++. Basically this is a text file.
I solved it by coping the data into a txt. However, I am still not aware how to read "*.inp"
I found some info about INP file extension. It seems like there are multiple variances of it, each meant to be used for different purpose. Where is your file coming from? As for soultion, if you can't open the file using fopen/fstream normally, you could treat it as binary and read each value in the way you specify. Other than that, I could think of calling system functions to get file contents (like cat in linux for example), then if there are some random characters, you could parse your string to ommit them.
Here is example of how to call cat in C++:
Simple way to call 'cat' from c++?

How to input an arbitrary number of text files in C++?

so I'm working on a coding project for a class, and I understand the basic things I want to accomplish, but one thing that nobody seems to be able to help me with is inputting an unspecified number of text files. The user is prompted to enter the text files they want to compare (overall purpose of my code), separated by spaces, thus allowing them to compare an arbitrary amount of text files (eg. 2, 3, 8, 16, etc). I know that the getline function is helpful here, as well as searching for the number of "." because files can only contain one ".", all within a for loop. After that logic I am utterly lost. Eventually, I'm going to have to open the text files and put them in sets to compare them against every other file once, and output their similarities and differences into yet another text file. Any ideas?
Here is the general process I would try to follow (if I interpreted the prompt correctly)
Get the line of text files using getline
Put that into a stringstream
Open the next file in the stream while there is still information in the stringstream (not at eof)
Store all of that information in a Vector of strings, each new file just appended on after it is read
compare strings in the vector
If you pass the text files on the commandline rather than getting them from a little dialog with the user via stdin life will be easier. Most users will type
compare *
which on Unix type systems is expanded to a list of files. ON DOS you need to match and expand the wild card yourself.
You've got an N squared problem, but the logic is easy, it's just
int mian(int argc, char **argv)
{
int i, j;
for(i=1;i<argc;i++)
for(j=i+1;j>argc;j++)
compare(argv[i], argv[j];
}

getline() text with UNIX formatting characters

I am writing a C++ program which reads lines of text from a .txt file. Unfortunately the text file is generated by a twenty-something year old UNIX program and it contains a lot of bizarre formatting characters.
The first few lines of the file are plain, English text and these are read with no problems. However, whenever a line contains one or more of these strange characters mixed in with the text, that entire line is read as characters and the data is lost.
The really confusing part is that if I manually delete the first couple of lines so that the very first character in the file is one of these unusual characters, then everything in the file is read perfectly. The unusual characters obviously just display as little ascii squiggles -arrows, smiley faces etc, which is fine. It seems as though a decision is being made automatically, without my knowledge or consent, based on the first line read.
Based on some googling, I suspected that the issue might be with the locale, but according to the visual studio debugger, the locale property of the ifstream object is "C" in both scenarios.
The code which reads the data is as follows:
//Function to open file at location specified by inFilePath, load and process data
int OpenFile(const char* inFilePath)
{
string line;
ifstream codeFile;
//open text file
codeFile.open(inFilePath,ios::in);
//read file line by line
while ( codeFile.good() )
{
getline(codeFile,line);
//check non-zero length
if (line != "")
ProcessLine(&line[0]);
}
//close line
codeFile.close();
return 1;
}
If anyone has any suggestions as to what might be going on or how to fix it, they would be very welcome.
From reading about your issues it sounds like you are reading in binary data, which will cause getline() to throw out content or simply skip over the line.
You have a couple of choices:
If you simply need lines from the data file you can first sanitise them by removing all non-printable characters (that is the "official" name for those weird ascii characters). On UNIX a tool such as strings would help you with that process.
You can off course also do this programmatically in your code by simply reading in X amount of data, storing it in a string, and then removing those characters that fall outside of the standard ASCII character range. This will most likely cause you to lose any unicode that may be stored in the file.
You change your program to understand the format and basically write a parser that allows you to parse the document in a more sane way.
If you can, I would suggest trying solution number 1, simply to see if the results are sane and can still be used. You mention that this is medical data, do you per-chance know what file format this is? If you are trying to find out and have access to a unix/linux machine you can use the utility file and maybe it can give you a clue (worst case it will tell you it is simply data).
If possible try getting a "clean" file that you can post the hex dump of so that we can try to provide better help than that what we are currently providing. With clean I mean that there is no personally identifying information in the file.
For number 2, open the file in binary mode. You mentioned using Windows, binary and non-binary files in std::fstream objects are handled differently, whereas on UNIX systems this is not the case (on most systems, I'm sure I'll get a comment regarding the one system that doesn't match this description).
codeFile.open(inFilePath,ios::in);
would become
codeFile.open(inFilePath, ios::in | ios::binary);
Instead of getline() you will want to become intimately familiar with .read() which will allow unformatted operations on the ifstream.
Reading will be like this:
// This code has not been tested!
char input[1024];
codeFile.read(input, 1024);
int actual_read = codeFile.gcount();
// Here you can process input, up to a maximum of actual_read characters.
//ProcessLine() // We didn't necessarily read a line!
ProcessData(input, actual_read);
The other thing as mentioned is that you can change the locale for the current stream and change the separator it considers a new line, maybe this will fix your issue without requiring to use the unformatted operators:
imbue the stream with a new locale that only knows about the newline. This method may or may not let your getline() function without issues.

Converting argv back to a single string

I'm writing a (Win32 Console) program that wraps another process; it takes parameters as in the following example:
runas.exe user notepad foo.txt
That is: runas parses user and then will run notepad, passing the remaining parameters.
My problem is that argv is broken down into individual parameters, but CreateProcessAsUser requires a single lpszCommandLine parameter.
Building this command line is probably not as simple as just joining argv back together with spaces. Any pointers?
This is just an example. My first argument isn't actually a user name, and might have spaces in it. This makes manually parsing the result of GetCommandLine tricky.
Similarly, a naive concatenation of argv won't work, because it needs to deal with the case where the original arguments were quoted and might have spaces in them.
Manually recombining them is hard:
You could try to re-combine them, I think it would work, but be sure to following the same command line escaping rules that windows has. This could be more than the trivial solution you're looking for.
Also if there are any parameters that have spaces in them, then you would want to join them to the string with quotes around them. Here is an example of a strange escaping rule: if you have --folderpath "c:\test\" then the last backslash has to be doubled --folderpath "c:\test\\".
If you are using MFC:
You can can get the value you want from your derived CWinApp's theApp.m_lpCmdLine. Note you could still access them the other way too with __argc, and __argv or CommandLineToArgvW.
If you are using Win32 only (even without a GUI):
You can get it from WinMain. Which can be your program's entry point.
Note you could still access them the other way too with __argc, and __argv or CommandLineToArgvW.
If you must use a console based application with main or wmain:
The Win32 API GetCommandLine seems to be the way to go. You would need to still parse this to get past the .exe name though. Take into account quotes around the exe name/path too. If there are no such quotes at the start, then just go to the next space for the start.
You can use the GetCommandLine function.
Why not use 'WinMain' instead of 'main'? This should give you the string in the format you want.
There is Win32 API call that returns command line: GetCommandLine
Provided you have a string allocated with enough space then use strcat on each item in the list. Yes, it is as simple as joining them back together with spaces.
Edit: Of course, you would need to enclose any items containing spaces within quotes.