Running a program from command prompt and using argv in C++ - c++

I have written a program that takes the filename from argv[1] and do operations on it .
When debugging from visual studio I pass the filename from project options>>debugging>>command arguments and It works fine and prints all results correctly .
But when trying from the command prompt , I go to the dir of project/debug the I type
program
It works fine and prints "No valid input file" in the same window (Which is my error handling technique)
but when i type
program test.txt
It just does nothing . I think no problem in code because it works fine from the debugger .
Code :
int main(int argc, char *argv[])
{
int nLines;
string str;
if(argv[1]==NULL)
{
std::cout << "Not valid input file" << endl;
return 0 ;
}
ifstream infile(argv[1]);
getline(infile,str);
nLines = atoi(str.c_str());//get number of lines
for(int line=0 ;line < nLines;line++)
{
//int currTime , and a lot of variables ..
//do a lot of stuff and while loops
cout << currTime <<endl ;
}
return 0 ;
}

You don't check if file was successfully opened, whether getline returned error code or not, or if string to integer conversion didn't fail. If any of those error occur, which I guess is the case, nLines will be equal to 0, no cycles will be performed and program will exit with return code 0.

This code worked correctly for me running on the command line.
#include <string>
#include <algorithm>
#include <functional>
#include <vector>
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int nLines;
string str;
if(argv[1]==NULL)
{
std::cout << "Not valid input file" << endl;
return 0 ;
}
else
std::cout << "Input file = " << argv[1] << endl;
}
Output :
C:\Users\john.dibling\Documents\Visual Studio 2008\Projects\hacks_vc9\x64\Debug>hacks_vc9.exe hello
Input file = hello
By the way, this code is dangerous, at best:
if(argv[1]==NULL)
You should probably be checking the value of argc before attempting to dereference a possibly-wild pointer.

The file probably contains an invalid numeric first line (perhaps starting with a space or the BOM).
That would explain no output, since if nLines == 0 no output should be expected

Related

Command Line Test Program -> Only producing first part

The assignment given in class was to test arguments that where provided.The code that wrote(added to this topic) works ( in the sense that it runs) , but it only produces the first word or set of words.
Code:
#include <fstream>
#include <iostream>
using namespace std;
int main ( int argc , char *argv[] )
{
if(argc > 1 )
{
cout << argv[1] << endl;
}
else
{
return -1;
}
ifstream infile(argv[1]);
if (infile.is_open())
{
string words;
while (infile >> words)
{
cout << words <<endl;
}
}
else
{
return -1;
}
infile.close();
}
The given line is :
"This is true" "This is fact"
The outcome it(code) produces is:
This is true
The outcome that I want is:
This is true , this is fact
Another Example:
The given line :
check if this thing works
Output using this code :
check
Wanted output:
check, if, this, thing, works
My question is if I am not adding something in my code that will produce the whole line. Also, I know that my code does not add "," to the output, but I want to worry about one issue at a time.
Some more information:
The file is read and if there is no arg then it does not produce anything, it also works if there is only one arg. he code stops working at more then one arg and quotes.
This line cout << argv[1] << endl; will print your first command line argument (after argument zero which is the application name) to the screen. Command line arguments wrapped in double quotes are treated as a single argument so for your first example argv[1] = This is true and for the second argv[1] = check. That's why you see what you see.
If you understand this you should be able to figure out how to make it print the whole thing. i.e. command line arguments > 1.

Random ascii characters keep popping up in output

I'm trying to read information from a file and process that information in a certain way. I need to make an array of all the words on the very left hand side of the file that don't have white space in front of them. I keep however getting really odd output when I try to display the contents of that char array.
Here is the sample input:
# Sample Input
LA 1,3
LA 2,1
TOP NOP
ADDR 3,1
ST 3, VAL
CMPR 3,4
JNE TOP
P_INT 1,VAL
P_REGS
HALT
VAL INT 0
TAN LA 2,1
So for instance when I run my program, my output should be:
TOP
VAL
TAN
Instead I'm getting:
a
aTOP
aVAL
aTAN
a
a
I'm not sure why this is happening. Any minor changes I make don't actually help, they just change what's in front of my expected output. Sometimes it's ASCII value 0 or 20 characters. Hopefully someone can help me fix this because it's driving me crazy.
Here's my code:
#include <string>
#include <iostream>
#include <cstdlib>
#include <string.h>
#include <fstream>
#include <stdio.h>
using namespace std;
int main(int argc, char *argv[])
{
// If no extra file is provided then exit the program with error message
if (argc <= 1)
{
cout << "Correct Usage: " << argv[0] << " <Filename>" << endl;
exit (1);
}
// Array to hold the registers and initialize them all to zero
int registers [] = {0,0,0,0,0,0,0,0};
string memory [16000];
string symTbl [1000][1000];
char line[100];
char label [9];
char opcode[9];
char arg1[256];
char arg2[256];
char* pch;
// Open the file that was input on the command line
ifstream myFile;
myFile.open(argv[1]);
if (!myFile.is_open())
{
cerr << "Cannot open the file." << endl;
}
int counter = 0;
int i = 0;
while (myFile.good())
{
myFile.getline(line, 100, '\n');
// If the line begins with a #, then just get the next line
if (line[0] == '#')
{
continue;
}
// If there is a label, then this code will run
if ( line[0] != '\t' && line[0]!=' ')
{
if( pch = strtok(line-1," \t"));
{
strcpy(label,pch);
cout << label << endl;
}
if (pch = strtok(NULL, " \t"))
{
strcpy(opcode,pch);
}
if (pch = strtok(NULL, " \t,"))
{
strcpy(arg1,pch);
}
if (pch = strtok(NULL, ","))
{
strcpy(arg2, pch);
}
}
}
return 0;
}
You are passing line-1 to strtok, which will cause it to return a pointer to the character before the start of the string; accessing line[-1] will produce undefined behaviour. strtok takes a pointer to the start of a string.
You've also got a ; at the end of your if( pch = strtok(line-1," \t")) statement, which nullifies the if test and causes the block to run even if pch is NULL.
You have a bug here: strtok(line-1," \t")
line-1 is the address of line[-1]. It's an invalid address and using it produces undefined behavior.

Redirecting input and output files on Unix and C++ using stdio

I need to do this:
$ ./compiledprog.x < inputValues > outputFile
so that I read from the file inputValues which for our case might just be \n separated int values or whatever. Then anything printf()'d goes into outputFile. But what's this called, technically speaking, and where can I find a demo of doing this.
As noted by others, it's input/output redirection.
Here's an example program that would copy the standard input to the standard output, in your example copy the contents from inputValues to outputFile. Implement whatever logic you want in the program.
#include <unistd.h>
#include <iostream>
using std::cin;
using std::cout;
using std::endl;
using std::cerr;
#include <string>
using std::string;
int main(int argc, char** argv) {
string str;
// If cin is a terminal, print program usage
if (isatty(fileno(stdin))) {
cerr << "Usage: " << argv[0] << " < inputValues > outputFile" << endl;
return 1;
}
while( getline(cin, str) ) // As noted by Seth Carnegie, could also use cin >> str;
cout << str << endl;
return 0;
}
Note: this is quick and dirty code, which expects a well behaved file as input. A more detailed error checking could be added.
This is called I/O redirection.

Linux | Segmentation Fault in C++ - Due to the function ifstream

I think I should begin by saying that I've just installed linux(debian) in my pc and have zero foreknowledge about doing things in linux. This problem is probably due to some really simple thing.
The relevant part of the code is similar to this:
ifstream stockNames("names.txt");
while (!stockNames.eof())
{
string snline;
getline(stockNames,snline);
cout << snline << endl;
.
.
.
}
this should print the first line of the file 'names.txt'. Instead it prints an empty line. And when I try to use snline as an input in another function I get the error 'Segmentation Fault'. How should I modify my code to do this? Is there any difference in usage of the ifstream in linux? Cause in windows the code works just fine
I've written the simple code below
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
int main(int argc, const char *argv[])
{
string dos = "names.txt";
ifstream stockNames(dos.c_str() );
string snline;
while (getline(stockNames,snline))
{
cout << snline << " ";
}
return 0;
}
content of names.txt is
ABC
DEFG
HBO
instead of showing those line, cout << snline produces nothing
One more update: I've written two more codes.
(1)
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
int main(int argc, const char *argv[])
{
cout << "program has initiated" << endl;
ifstream stockNames("names.txt");
if( !stockNames )
cout << "unable to open" << endl;
string snline;
while (getline(stockNames,snline))
{
cout << snline << endl;
}
return 0;
}
Result is as I desired. First 'program has initiated', then ABC, DEFG, HBO in different lines. But when I change this part
cout << snline << endl;
as
cout << snline << " hey" << endl;
Then ABC DEFG HBO does not appear and instead the only output is " hey".
This is crazy, how can this be??
btw I tried to make a debug with ddd and when I check the variable snline, ddd prints the following line
(gdb) print snline
$2 = {static npos = 4294967295, _M_dataplus = {> = {<__gnu_cxx::new_allocator> = {}, }, _M_p = 0x804c1a4 "ABC\r"}}
new mini update: when I change the relevant line as "cout << snline << " " << endl;" what's printed out is ' BC' ' FGH' ' BO' in seperate lines. Why does << operator overwrites over snline??
First of all, your while loop is wrong, because the eof flag (or any other failure flag) is set after an attempt to read from the stream fails; that means, if the attempt to read fails using getline(), the loop doesn't immediately exit, instead the loop continues which is a serious bug with your code.
So write your loop as (an idiomatic way):
string snline;
while (getline(stockNames,snline))
{
cout << snline;
//..
}
std::getline returns istream&, which can be implicitly converted into boolean type. So if getline reads successfully, then the returned value converts to true and the loop will continue, or else it will convert to false and the loop will exit.
After the edit in your question, all I can say that you need to check the stream object before using it to read contents from the file. More specifically, you need to check if the stream has been initialized properly and it has indeed opened the input file (i.e names.txt), and is ready to read data from it.
So try doing this:
//...
ifstream stockNames(dos.c_str() );
if (!stockNames)
{
cout << "file couldn't open properly" << endl;
return 0;
}
string snline;
while (getline(stockNames,snline))
{
cout << snline << " ";
}
Now run this, and see what it prints.
You have a dos file which uses \r\n at the end of each line. Linux doesn't recognise \r as part of the line ending so it gets included in the snline string. \r causes the next thing printed to appear at the beginning of the line so " hey" overwrites the stock names you were expecting to see.
Try
cout << snline << " " << endl;
and you'll see what I mean
stockNames will not actually appear to reach "end of file" until it has tried to input something and received the EOF character. Therefore, you're going to want to re-write your loop as follows:
ifstream stockNames("names.txt");
string snline;
getline(stockNames,snline);
while (!stockNames.eof())
{
cout << snline << endl;
.
.
.
getline(stockNames,snline);
}
or much simply
ifstream stockNames("names.txt");
string snline;
while (getline(stockNames, snline))
{
cout << snline << endl;
.
.
.
}
To answer your question; no, there is no significant difference in how ifstream operates on Linux and Windows. Of course if you write bugged code (as the other two answers have pointed out) then you might run into problems, but I can't see how the eof bug would cause the problems you are describing.
I would concentrate on the part where you say that using snline causes a segmentation fault, that indicates a more serious issue. Could you post code that demonstrates that?
You aren't checking whether the stream opened properly.
std::ifstream stockNames("names.txt");
if (! stockNames) {
std::cerr << "Unable to open file 'names.tex'\n";
}
else {
// Do the rest of your stuff here.
}
Always check status. Don't just plow ahead and assume everything is OK.
BTW, using namespace std; is something you see in a lot of bad books that are trying to save a tiny amount of ink. Try to get out of this bad habit.

C++ program not moving past cin step for string input

I'm obviously not quite getting the 'end-of-file' concept with C++ as the below program just isn't getting past the "while (cin >> x)" step. Whenever I run it from the command line it just sits there mocking me.
Searching through SO and other places gives a lot of mention to hitting ctrl-z then hitting enter to put through an end-of-file character on windows, but that doesn't seem to be working for me. That makes me assume my problem is elsewhere. Maybe defining x as a string is my mistake? Any suggestions about where I'm going wrong here would be great.
Note: sorry for the lack of comments in the code - the program itself is supposed to take in a series of
words and then spit back out the count for each word.
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <iomanip>
using std::cin;
using std::cout; using std::endl;
using std::sort;
using std::string; using std::vector;
int main()
{
cout << "Enter a series of words separated by spaces, "
"followed by end-of-file: ";
vector<string> wordList;
string x;
while (cin >> x)
wordList.push_back(x);
typedef vector<string>::size_type vec_sz;
vec_sz size = wordList.size();
if (size == 0) {
cout << endl << "This list appears empty. "
"Please try again." << endl;
return 1;
}
sort(wordList.begin(), wordList.end());
cout << "Your word count is as follows:" << endl;
int wordCount = 1;
for (int i = 0; i != size; i++) {
if (wordList[i] == wordList[i+1]) {
wordCount++;
}
else {
cout << wordList[i] << " " << wordCount << endl;
wordCount = 1;
}
}
return 0;
}
If you're on windows ^Z has to come as the first character after a newline, if you're on a unixy shell then you want to type ^D.
The input portion of your code works. The only real problem I see is with the loop the tries to count up the words:
for (int i = 0; i != size; i++) {
if (wordList[i] == wordList[i+1]) {
The valid subscripts for wordList run from 0 through size-1. In the last iteration of your loop, i=size-1, but then you try to use wordList[i+1], indexing beyond the end of the vector and getting undefined results. If you used wordList.at(i+1) instead, it would throw an exception, quickly telling you more about the problem.
My guess is that what's happening is that you're hitting Control-Z, and it's exiting the input loop, but crashing when it tries to count the words, so when you fix that things will work better in general. If you really can't get past the input loop after fixing the other problem(s?), and you're running under Windows, you might try using F6 instead of entering control-Z -- it seems to be a bit more dependable.
I pretty much always use getline when using cin (particularly when what I want is a string):
istream& std::getline( istream& is, string& s );
So, you'd call getline(cin, x) and it would grab everything up to the newline. You have to wait for the newline for cin to give you anything anyway. So, in that case, your loop would become:
while(getline(cin, x))
wordList.push_back(x);
cin does not accept blank space or line breaks so execution of cin does not complete unless you enter something , here is a test program that gives you what you want
#include "stdafx.h"
#include<iostream>
#include <string>
#include <sstream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string str = "";
while(std::getline(cin, str) && str!="")
{
cout<<"got "<<str<<endl;
}
cout<<"out"<<endl;
cin>>str;
return 0;
}