how to read input files taken as parameters in C++ - c++

I've just practiced coding C++. I knew in Java, we could have a public main method, which could read input file names as parameters of the string array argument. But I wonder how I do the same task in C++?

Both Java and C++ follow the same C-like syntax. So it doesn't really differ from what you had in Java. In Java you had a string class :
class Test {
public static void main(String args[]) {
for(int i = 0; i < args.length; i++)
System.out.println("Argument " + i + " = " + args[i]);
}
}
C/C++ mostly use primitive character arrays in order to store strings. Although Standard Template Library also provides string classes, but C++ uses native char arrays to store commandline arguments. The main function takes two variables :
int argc : number of commandline arguments
char *argv[] : an array of character strings
You can also say it can be written as char **argv, because of the underlying representation of two dimensional arrays in C/C++, but both mean the same thing. The equivalent of the above code in C++ would be:
#include <iostream>
int main(int argc, char *argv[]) {
for(int i = 0; i < argc; i++)
std::cout << "Argument " << i << " = "
<< argv[i] << std::endl;
return 0;
}

You do it the same way, with slightly different syntax because C arrays do not store their length, so it is passed as a separate parameter.
int main(int argc, char** argv) {
// Read args from argv, up to argc args.
// argv[0] is the name of the program
// argv[1] is the first argument
}

The main function gives you the argument count and the actual arguments as an array of character arrays.
To safely work with this, you should first turn this information into a std::vector<std::string>.
#include <string>
#include <vector>
int main(int argc, char *argv[]) {
std::vector<std::string> arguments;
for (int index = 0; index < argc; ++index) {
arguments.push_back(argv[index]);
}
}
You will notice that arguments[0] is equal to the filename of the executable (in theory, this depends on the system you're using). If you are on Windows and have an executable called stackoverflow.exe, then starting it with
stackoverflow.exe one two
would result in arguments containing { "stackoverflow.exe", "one", "two" }.

Related

Number of elements of command line arguments

I have a problem with command-line arguments.
I need to write a program that will count the size of elements of each command-line argument passed in argv array.
Simple code looks like this.
#include <stdio.h>
int main(int argc, char *argv[])
{
int i = 0;
for (i = 0; i < argc; i++)
{
printf("%lu\n", sizeof(argv[i]));
}
return 0;
}
I understand that it is wrong and that "argv" is an array of pointers to a string. I also tried to add asterisk but it brought back "1" (byte) as a result because I said "go to that address" and it showed me the size of the first element of each command-line argument.
So, how can I solve this problem without many and many loops, just with "sizeof" function?
UPD: Sorry for that "%s" mistake. In the actual code I didn't write it.
And I DO understand that sizeof() won't bring me the size of array. I was pointing to the combination "sizeof() / sizeof (char)"
Also, thank you very much for "strlen" reminder. I am studying now. I don't know C language yet. Sorry, for my stupid mistakes.
You are printing the size of a character pointer. Instead you want the length of the string. You can use the standard function strlen :
( note: argv[0] is the program name itself, so 1st number indicates the length of program name.)
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i = 0;
for (i = 0; i < argc; i++)
{
printf("%zu\n", strlen(argv[i]));
}
return 0;
}
Instead of sizeof use strlen() that returns the size of a string while excluding the string termination character from the counting. More information here: Strlen
As it is seen from your program more preciseky from the declaration of the main arguments have type char *. That is they are pointers to first characters of strings that are passed to the program like arguments.
So you need to use standard C function strlen declared in header <string.h> to determine the size of the string passed like an argumnet.
Take into account that the last pointer in the array argv has value NULL.
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
for ( char **p = argv; *p; ++p )
{
printf( "%zu\n", strlen( *p ) );
}
return 0;
}

C++ How to pass command line argument to read txt file

What I've been trying to do is...
1) to read txt files by command line argument,
2) to use strings in the txt files as arguments for the main method (or whatever method you need to invoke).
For example, there are two txt files, one of which is named character.txt and the other match.txt.
The contents of the files would be like this.
character.txt
//This comprises of six rows. Each of the rows has two string values
Goku Saiyan
Gohan Half_Saiyan
Kuririn Human
Piccolo Namekian
Frieza villain
Cell villain
match.txt
//This comprises of three rows, each of them is one string value
Goku Piccolo
Gohan Cell
Kuririn Frieza
If I use those strings without using command line, I'd declare the strings in character.txt like this.
typedef string name; //e.g. Goku
typedef string type; //e.g. Saiyan, Human, etc
Now I'm looking for how to read and send string values from txt files like the ones above, and to use them for functions inside the main method, ideally like this way.
int main(int argc, char *argv)
{
for (int i = 1; i < argc; i++) {
String name = *argv[i]; //e.g. Goku
String type = *argv[i]; //e.g. Saiyan, Human, etc
String match = * argv[i]; //Goku Piccolo
//I don't think any of the statements above would be correct.
//I'm just searching for how to use string values of txt files in such a way
cout << i << " " << endl; //I'd like to show names, types or matchs inside the double quotation mark.
}
}
Ideally, I'd like to invoke this method in this way.
According to this web site., at least I understand it is possible to use command line arguments with C++, but I cannot find any more information. I'd appreciate if you'd give any advice on it.
PS. I'm using Windows and Code Blocks.
Asuming you just want to read contents of the files and process it, you can start with this code (Without any errors checks tho). It simply gets filenames from command line and reads file contents into 2 vectors. Then you can just process these vectors as u need.
#include <string>
#include <fstream>
#include <iostream>
#include <vector>
std::vector<std::string> readFileToVector(const std::string& filename)
{
std::ifstream source;
source.open(filename);
std::vector<std::string> lines;
std::string line;
while (std::getline(source, line))
{
lines.push_back(line);
}
return lines;
}
void displayVector(const std::vector<std::string&> v)
{
for (int i(0); i != v.size(); ++i)
std::cout << "\n" << v[i];
}
int main(int argc, char **argv)
{
std::string charactersFilename(argv[1]);
std::string matchesFilename(argv[2]);
std::vector<std::string> characters = readFileToVector(charactersFilename);
std::vector<std::string> matches = readFileToVector(matchesFilename);
displayVector(characters);
displayVector(matches);
}
to see how to use command line arguments look at this.
http://www.cplusplus.com/articles/DEN36Up4/
you cannot use the contents of the file which you have passed to your app through command line arguments. only the name of the file is passed to the app.
you should open the file using that name and read its contents. take a look at this:
http://www.cplusplus.com/doc/tutorial/files/
First the main function prototype should be
int main(int argc, char **argv)
OR
int main(int argc, char *argv[])
Second after retrieving files names in the main function you should open each file and retrieve its contents
Third Sample code
int main(int argc, char* argv[])
{
for(int i=1; i <= argc; i++) // i=1, assuming files arguments are right after the executable
{
string fn = argv[i]; //filename
cout << fn;
fstream f;
f.open(fn);
//your logic here
f.close();
}
return 0;
}
You define main prototype incorrectly. You also need std::ifstream to read files.
If you expect exactly two arguments, you may check argc and extract arguments directly:
int main(int argc, char* argv[]) {
if(argc != 3) {
std::cerr << "Usage: " << argv[0]
<< " name.txt match.txt" << std::endl;
return 1;
}
std::ifstream name_file(argv[1]);
std::ifstream match_file(argv[2]);
// ...
return 0;
}
If you expect unspecified number of files, than you need a loop and an array to save them, i.e. vector:
int main(int argc, char* argv[]) {
std::vector<std::ifstream> files;
for(int i = 1; i < argc; ++i)
files.emplace_back(argv[i]);
// ...
return 0;
}
And do not forget to check if files are openable.
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
FILE *fp = fopen( argv[1], "r");
char line[50];
if (fp == NULL)
{
printf("File opening Unsuccessful\n");
exit(1);
}
while (fgets(line , 30 , fp) != NULL)
{
printf("%s",line);
}
fclose(fp) ;
return 0;
}

C++ array not outputting full values

So i'm experimenting with arrays when I come across a bit of a problem
code:
#include <iostream>
#include <windows.h>
using namespace std;
int main(int argc, char** argv) {
char items[] = {'bread', 'water', 'crisps', 'sweets', 'vegetables'};
for (int i = 0; i < strlen(items); i++) {
cout << items[i] << endl;
}
return 0;
}
What's happening is that when the code is ran, it's only outputting the last letter of each item, so 'd' 'r' 's' 's' 's'. I know i'm clearly doing something wrong here but I can't figure out what. I've been surfing on stackoverflow/google for a question like this but clearly what I have done is so obviously wrong, no one has asked!
Any help or a nudge in the right direction to particular documentation would be appreciated!
Thanks.
Need an array of character pointers.
Need to use double quotes
Read a book on C++
i.e. code should be
#include <iostream>
#include <windows.h>
using namespace std;
int main(int argc, char** argv) {
char *items[] = {"bread", "water", "crisps", "sweets", "vegetables"};
for (int i = 0; i < (sizeof(items) / sizeof(*items)); i++) {
cout << items[i] << endl;
}
return 0;
}
Any of these items in the initializer list
{'bread', 'water', 'crisps', 'sweets', 'vegetables'};
is a multicharacter literal. According to the C++ Standard
A multicharacter literal, or an ordinary character literal containing
a single c-char not representable in the execution character set, is
conditionally-supported, has type int, and has an
implementation-defined value.
You need to use string literals. I think that what you want is the following
#include <iostream>
int main(int argc, char** argv)
{
const char *items[] = { "bread", "water", "crisps", "sweets", "vegetables" };
for ( const char *s : items ) std::cout << s << std::endl;
return 0;
}

Can main function have default argument values?

How can I put the default values for main function arguments like the user defined function?
Well, the standard says nothing which prohibits main from having default arguments and say you've successfully coalesced the compiler to agree with you like this
#include <iostream>
const char *defaults[] = { "abc", "efg" };
int main(int argc = 2, const char **argv = defaults)
{
std::cout << argc << std::endl;
}
Live example. It compiles with no errors or warnings, still it's useless; a futile experiment. It almost always would print 1.
Every time you invoke the program, say, with no arguments (or any number of arguments for that matter), argc gets set to 1 and argv[0] points to the program name, so doing it is pointless i.e. these variables are never left untouched and hence having defaults makes little sense, since the defaults would never get used.
Hence such a thing is usually achieved with local variables. Like this
int main(int argc, char **argv)
{
int const default_argc = 2;
char* const default_args[] = { "abc", "efg" };
if (argc == 1) // no arguments were passed
{
// do things for no arguments
// usually those variables are set here for a generic flow onwards
argc = default_argc;
argv = default_args;
}
}
I think you want to do two different things for the following cases.
When no arguments are passed
When arguments are passed.
Here is how you do it.
int main(int argc, char *argv[])
{
if(argc == 1)
{
// case #1
}
else
{
// case #2
}
}
Using argc and argv? Thoses will pass argument from the command line to your program. You can't really use default arguments. You have to pass them during the call to your program like this :
$> ./my_addition "4" "7"
int main(int argc, char *argv[])
{
// argc <=> 'argument count' (=3)
// argv <=> 'argument vector' (i.e. argv[1] == "4")
// argv[0] is usually the bin name, here "my_addition"
for (int i = 0; i < argc; ++i)
std::cout << argv[i] << std::endl;
return (0);
}
Maybe you could use a script to run your program, this could maybe be the closest solution to default argument for main().
exec_my_prog.sh:
#!/bin/zsh
call_your_program + very_meny_args
And calling ./exec_my_prog.sh would run your program with the "default" arguments.

Checking arguments in terminal

How can I write a program to check the arguments in the terminal are correct?
For example, if I have a program hello.cpp and I want to call it as:
./hello yes 10
I want the program to make sure that the first argument is yes or no and the second argument is a number between 1-10. So how can I read these arguments into my program to do the checking?
Thanks!
Command line arguments are passed as a count and individual strings in the argc and argv arguments to main().
int main(int argc, char *argv[])
{
...
}
Simply check the value in argc and the strings in argv for the appropriate values.
You meant to execute like this, ./hello yes 10
there is an option argc and argv in c
where argc is the number of arguments passed and argv with the index shows the argument passed itself.
Take a look at the below code for iterating through all arguments.
int main(int argc, char *argv[]){
int i = 0;
for (i = 0; i < argc; i++) {
printf("argv[%d] = %s\n", i, argv[i]);
}
return 0;
}
As mentioned by other users, The main function is the entry point of your program, and the way it gets data from the command line is through its parameters.
The first int argument is the count of all the arguments passed, including the program name, the second char ** argument is a pointer to each parameter passed, including the program name:
int main
(
int argc, // <-- how many parameters has been provided?
char **argv, // <-- what values has each parameter?
)
{
...
return 0;
}
So, knowing that, your call ./hello yes 10 must be like that:
argc = 3
argv[0] = "./hello"
argv[1] = "yes"
argv[2] = "10"
The names argc and argv are just a convention, you can name them at your pleasure, but it's a good practice to keep the names that everyone are used for.
And the argument doesn't are forced to be int, char ** they must follow a quite rigid convention, borrowed from this answer:
It shall have a return type of type int, but otherwise its type is implementation-defined. All implementations shall allow both the following definitions of main: int main() and int main(int argc, char* argv[])
Knowing that, let's focus on your question:
First of all, you must ensure that 2 arguments are passed, so you must check the argc value and ensure that equals exactly 3.
the first argument is yes or no
Next, you must store your argv[1] (because 0 contains the program name) into a string and compare it with the values "yes" and "no":
std::string YesOrNo(argv[1]);
if (YesOrNo == "yes" || YesOrNo == "no")
And finally, you must store your argv[2] into an integer and check if it is equal or less to 10:
std::stringstream Stream;
int Value = 0;
Stream << argv[2];
Stream >> Value;
if (Value <= 10)
So, the result is:
int main(int argc, char **argv)
{
if (argc == 3)
{
std::string YesOrNo(argv[1]);
if (YesOrNo == "yes" || YesOrNo == "no")
{
std::stringstream Stream;
int Value = 0;
Stream << argv[2];
Stream >> Value;
if (Value <= 10)
{
// Your stuff..
}
}
}
return 0;
}
I let you deal with all the uppercase and lowercase stuff and the false positives with the numeric argument, at least I'm not going to do all your homework ;)