So I'm trying to pass and command line argument into an array in my int main
like this $< .\program nums.txt 8 but I'm getting errors and hit a dead-end with my knowledge on C++ code. (I'm relatively a new coder). Any help is greatly appreciated.
int main(int argc,char *argv[])
{
string arg2=" ";
arg2 = argv[2];
int size;
size=stod(arg2);
string arr[size];
string file = argv[1];
ifstream infile;
if (getline infile.open(file))
{
int arr[size],val;
for(int i=0;i<size;i++)
{
getline(file, arr[i]);
}
}
int choice = 5,value,position,target ;
Her is a list of the errors you have (excluding a missing curly brace at the end, missing includes [you probably just didn't post them?] and missing std:: [the use of using namespace std; is considered bad practice ]) and mostly how to fix them:
std::stod parses and returns a dobule, but you assign the result to an int.
size = std::stod(arg2);
you probably meant to use stoi:
size = std::stoi(arg2);
VLAs (Variable length arrays) like
std::string arr[size];
are not part of the C++ standard. Instead use
std::vector<std::string> arr(size);
When opening the file stream, your inention is right, but the syntax is wrong
std::ifstream infile;
if (std::getline infile.open(file))
should be
std::ifstream infile(file);
if (infile)
Inside the if you have
int arr[size],val;
two unused variables, another VLA and most importantly int arr[size] will shadow string arr[size].
That's the reason for the next errors:
std::getline(file, arr[i]);
The first parameter file is a std::string, this should obviosly be infile. Because of the variable shadowing the second parameter arr[i] will refer to int arr[i]. Rename one of them or just remove the two unused variables (see last point).
Always check if reading was successfull. If you want to read a maximum of size lines use
for(int i = 0; i < size && std::getline(infile, arr[i]); i++);
It will terminate the loop, if getline fails for some reason, for example, when the file has less than size lines.
Lastly, you can think about some validation. For example check if there actually are two command line parameters given and add a try-catch-block around the stoi.
And just to mention it: Learning C++ by guessing is no fun. On https://en.cppreference.com/w/ you can find extensive information and many examples for the functions and classes you want to use.
There are lot of typos in your question. Still I think this code may help you:
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
int main(int argc, char *argv[]) {
int size = atoi(argv[2]);
std::vector<std::string> arr(size);
std::ifstream infile(argv[1]);
if (not infile) {
std::cerr << "File not found!" << std::endl;
return -1;
}
for (int i = 0; i < size; i++)
if (infile)
std::getline(infile, arr[i]);
else {
std::cerr << "Not enough lines in the file!" << std::endl;
return -2;
}
// do rest of your things here ...
return 0;
}
Related
I am having trouble with an assignment for my freshman Computer Science class.
I am trying to have PrintAllConcepts print each item of an array, once per line.
For some reason all I get is the last line printed from LIST.txt and a bunch of extra empty lines that usually end up nearly crashing the program. There appears to be no syntactical errors, so I'm afraid I am not reading the concepts into the array correctly. This is where I would like assistance.
Below is my code.
I also apologize if this seems like a noob question, as I am a beginner in C++.
Edit: Also, explaining why the Number parameter is so funky, my assignment seems to be requiring me to do it that way. That is also why PrintAllConcepts and ReadConcepts returns void.
#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <iomanip>
void ReadConcepts(std::string Concepts[100], int &Number) {
std::ifstream fin;
fin.open("LIST.txt");
if (!fin.is_open()) {
std::cerr << "error: file open failed.\n";
}
std::string theConcepts[100];
std::string line;
int i;
for (i = 0; i <= 99; i++) {
while (std::getline(fin, line)) {
theConcepts[i] = line;
Number++;
}
}
}
void PrintAllConcepts(std::string Concepts[100], int Number) {
int i;
std::string line;
for (i = 0; i < Number - 1; i++) {
line = Concepts[i];
std::cout << line << std::endl;
}
std::cout << i;
}
int main() {
// Initiate variables
std::string Concepts[100];
int Number = 100;
// Read concepts
ReadConcepts(Concepts, Number);
// Open file for void function PrintAllConcepts
std::ifstream fin;
fin.open("LIST.txt");
if (!fin.is_open()) {
std::cerr << "error: file open failed.\n";
}
int i;
std::string line;
for (i = 0; i < 99; i++) {
while (std::getline(fin, line)) {
Concepts[i] = line;
}
}
PrintAllConcepts(Concepts, Number);
}
As you commented, the errors are in the ReadConcepts function.
To begin with you should not increment Number in the loop, as it's already the number of elements in the array. Because you increment Number you will pass the value 200 to PrintAllConcepts which will make it go out of bounds of the array.
Secondly you put all strings into the local array theConcepts instead of the array Concepts passed to the function. This means none of the strings in Concepts will be set, giving you the "empty" output. Remove the theConcepts array and use Concepts instead.
Thirdly you should have either the for loop, or the while loop, but not both. Since you have both the first iteration of the for loop will read all lines from the file, putting all of it into theConcepts[0], and leave the rest of the array with empty strings. I recommend a combination of both loops, as in:
for (int i = 0; i < Number && std::getline(fin, line); ++i)
{
Concepts[i] = line;
}
There are also some other "problem" that aren't serious and won't cause any errors. One of them is passing the Number argument by reference. Since Number should not be modified you should pass it by value.
As a perfunctory node to your question, you may want to insert a condition for reading the file in its entirety, i.e., while (fin.good()), etc.
That said, the above hints and tips are second to none. Debugging programs can teach you a lot, and are as good a learning tool as writing the code yourself. I should know; I'm new at this too. Good luck.
p.s.: Don't forget the good practice of closing your file once finished with it.
If I open a text file using fstream is there a simple way to jump to a specific line, such as line 8?
Loop your way there.
#include <fstream>
#include <limits>
std::fstream& GotoLine(std::fstream& file, unsigned int num){
file.seekg(std::ios::beg);
for(int i=0; i < num - 1; ++i){
file.ignore(std::numeric_limits<std::streamsize>::max(),'\n');
}
return file;
}
Sets the seek pointer of file to the beginning of line num.
Testing a file with the following content:
1
2
3
4
5
6
7
8
9
10
Test program:
int main(){
using namespace std;
fstream file("bla.txt");
GotoLine(file, 8);
string line8;
file >> line8;
cout << line8;
cin.get();
return 0;
}
Output: 8
If every line has the same length then you can use istream::seekg() to jump to the location and read from there.
Here is a working and neat example with std::getline() if the lines have the same length:
#include <iostream>
#include <fstream>
#include <string>
const int LINE = 4;
int main() {
std::ifstream f("FILE.txt");
std::string s;
for (int i = 1; i <= LINE; i++)
std::getline(f, s);
std::cout << s;
return 0;
}
In general, no, you have to walk down using a strategy similar to what Xeo shows.
If as netrom says you know the lines have fixed length, yes.
And even if the line lengths are not known in advance, but (1) you're going to want to jump around a lot and (2) you can guaranteed that no one is messing with your file in the mean time you could make one pass to form a index, and use that thereafter.
you can use while loop as well
fstream f;
f.open("bla.txt", ios_base::in);
int i = 1;
int line = 8;
while(i != line){
f.ignore(1000, '\n');
++i;
}
string fContent;
f >> fContent;
cout << fContent;
Note: create the file first
I would really appreciate the help here. I need to fill a vector of string vectors using text from an input file. I really have no idea how to start off.
I have something like this in a function to read in the words, but I keep getting a compiler error saying I can't push back a string, so I know I'm on the wrong track. Any help would be very much appreciated.
ifstream input(filename);
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++)
{
string line;
getline(input, line);
stringstream temp(line);
string tempWord;
temp >> tempWord;
words[i][j].push_back(tempWord);
}
If words is a vector<vector<string>> then words[i][j] is accessing a string. What you might looking to do is is words[i][j] = tempWord;. string also has a function .push_back() but takes a char which is why the error you are getting is that you can't push_back a string, the push_back() for strings is for appending characters to the string. Also depending on how you declared words, if you didn't give sizes, words[i][j] might be accessing out of range and a better approach would be to do words[i].push_back(tempWord). Also looking at your for loops I'm not sure of your intent for which words from the file you want but currently as your code is, it will read in the first 16 lines of the file and place the first "word" from each into your words object. If your intent is instead to have a vector of vectors of string where each subvector is the words in a line then something like below might be better.
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
int main(int argc, char* argv[])
{
std::string filename = "testfile.txt";
std::ifstream input(filename.c_str());
if(!input){
std::cerr << "Error in opening file: " << filename << "\n";
return 1;
}
std::vector<std::vector<std::string> > words;
std::string line;
while(std::getline(input, line)){
std::stringstream ss;
ss << line;
std::vector<std::string> row;
while (!ss.eof()) {
std::string tempStr;
ss >> tempStr;
row.push_back(tempStr);
}
words.push_back(row);
}
//... then do something with words here
return 0;
}
I have attached my full source code of my program that can open a .txt file. It doesn't execute after the cout << length. I am trying to store the .txt file information in memory by using an array.
#include <iostream>
#include <string.h>
#include <fstream>
using namespace std;
char filename[128];
char file[10][250];
int count;
int length;
string line;
int main ()
{
int count = 0;
int length = 0;
cout << "Filename: ";
cin.clear();
cin.getline(filename, sizeof(filename));
string new_inputfile(filename);
ifstream inputfiles (new_inputfile.c_str());
if(!inputfiles.is_open())
{
cout << "File could not be opened. \n ";
}
else
{
for (int i=0; getline(inputfiles,line); i++)
{
length++;
}
cout << length;
// char file[length][250]; <- How can I create the array based on the length variable?
// CODE DOES NOT EXECUTE AFTER THIS.
while(!inputfiles.eof() && (count<10))
{
inputfiles.getline(file[count],250);
count++;
}
for(int i=0; i < count; i++)
{
cout << file[i] << endl;
}
}
inputfiles.close();
return 0;
}
Also, since file[] is char, say for example file[1] contained the char Name=Mike, how do I strip off everything before the =. I want just Mike. I know with string, I can use substr() method, but I don't know for char.
This is horribly wasteful way to count number of lines in a file.
for (int i=0; getline(inputfiles,line); i++) // i is also completely useless here
{
length++;
}
You're reading the whole file only to throw everything away and start again! And after this loop is done, inputfiles.eof() will be true and you'll never enter neither the next while loop nor the last for loop (because i == count). Execution skips directly to inputfiles.close() and then you return from main.
I suggest you work on the line string as you go:
for ( ; getline(inputfiles, line); )
{
// do stuff with line and ditch the global char arrays
}
If you want store the lines for later, well, just save them :) The easiest thing to do is to use a vector:
std::vector<std::string> all_them_lines;
while (getline(file, line) all_them_lines.emplace_back(line);
There, the entire file is now saved in all_them_lines, line by line. You can access them just like you would in an array, like all_them_lines[0]. You also don't need to know the number of lines beforehand - vectors expand automatically when you add stuff to them.
Now to parse a line and extract formatted input from it, check out what stringstream class has to offer.
You asked:
// char file[length][250]; <- How can I create the array based on the length variable?
Declare file as:
char (*file)[250] = NULL;
and then,
file = new char[length][250];
Make sure you call delete [] file before the end of the function.
You said:
// CODE DOES NOT EXECUTE AFTER THIS.
You can rewind the stream and start reading from it again.
inputfiles.seekg(0);
count = 0;
while(!inputfiles.eof())
{
inputfiles.getline(file[count],250);
count++;
}
A novice at C++, i am trying to create a stats program to practice coding. i am hoping to get a text file, read it and store values into arrays on which i can perform mathematical operations. i am stuck here
main ()
{
char output[100];
char *charptr;
int age[100];
ifstream inFile;
inFile.open("data.txt");
if(!inFile)
{
cout<<"didn't work";
cin.get();
exit (1);
}
inFile.getline(output,100);
charptr = strtok(output," ");
for (int x=0;x<105;x++)
{
age[x] = atoi(charptr);
cout<<*age<<endl;
}
cin.get();
}
in the code above, I am trying to store subject ages into the int array 'age', keeping ages in the first line of the file. I intend to use strtok as mentioned, but i am unable to convert the tokens into the array.
As you can obviously see, I am a complete noob please bear with me as I am learning this on my own. :)
Thanks
P.S: I have read similar threads but am unable to follow the detailed code given there.
There are a few issues with the for loop:
Possibility of going out-of-bounds due to age having 100 elements, but terminating condition in for loop is x < 105
No check on charptr being NULL prior to use
No subsequent call to strtok() inside for loop
Printing of age elements is incorrect
The following would be example fix of the for loop:
charptr = strtok(output, " ");
int x = 0;
while (charptr && x < sizeof(age)/sizeof(age[0]))
{
age[x] = atoi(charptr);
cout << age[x] << endl;
charptr = strtok(NULL, " ");
x++;
}
As this is C++, suggest:
using std::vector<int> instead of a fixed size array
use the std::getline() to avoid specifying a fixed size buffer for reading a line
use std::copy() with istream_iterator for parsing the line of integers
For example:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
int main ()
{
std::vector<int> ages;
std::ifstream inFile;
inFile.open("data.txt");
if(!inFile)
{
std::cout<<"didn't work";
std::cin.get();
exit (1);
}
std::string line;
std::getline(inFile, line);
std::istringstream in(line);
std::copy(std::istream_iterator<int>(in),
std::istream_iterator<int>(),
std::back_inserter(ages));
return 0;
}