I would like to read a text file and input its contents into an array. Then I would like to show the contents of the array in the command line.
My idea is to open the file using:
inFile.open("pigData.txt")
And then to get the contents of the file using:
inFile >> myarray [size]
And then show the contents using a for loop.
My problem is that the file I am trying to read contain words and I don't know how to get a whole word as an element in the array. Also, let's say that the words are divided by spaces, thus:
hello goodbye
Could be found on the file. I would like to read the whole line "hello goodbye" into an element of a parallel array. How can I do that?
Should be pretty straightforward.
std::vector<std::string> file_contents;
std::string line;
while ( std::getline(inFile,line) )
file_contents.push_back(line);
std::vector<std::string>::iterator it = file_contents.begin();
for(; it!=file_contents.end() ; ++it)
std::cout << *it << "\n";
Edit:
Your comment about having "hello goodbye" as element zero and element one is slightly confusing to me. The above code snip will read each line of the file and store that as an individual entry in the array 'file_contents'. If you want to read it and split it on spaces that is slightly different.
For context, you could have provided a link to your previous question, about storing two lists of words in different languages. There I provided an example of reading the contents of a text file into an array:
const int MaxWords = 100;
std::string piglatin[MaxWords];
int numWords = 0;
std::ifstream input("piglatin.txt");
std::string line;
while (std::getline(input, line) && numWords < MaxWords) {
piglatin[numWords] = line;
++numWords;
}
if (numWords == MaxWords) {
std::cerr << "Too many words" << std::endl;
}
You can't have one parallel array. For something to be parallel, there must be at least two. For parallel arrays of words, you could use a declarations like this:
std::string piglatin[MaxWords];
std::string english[MaxWords];
Then you have two options for filling the arrays from the file:
Read an entire line, and the split the line into two words based on where the first space is:
while (std::getline(input, line) && numWords < MaxWords) {
std::string::size_type space = line.find(' ');
if (space == std::string::npos)
std::cerr << "Only one word" << std::endl;
piglatin[numWords] = line.substr(0, space);
english[numWords] = line.substr(space + 1);
++numWords;
}
Read one word at a time, and assume that each line has exactly two words on it. The >> operator will read a word at a time automatically. (If each line doesn't have exactly two words, then you'll have problems. Try it out to see how things go wrong. Really. Getting experience with a bug when you know what the cause is will help you in the future when you don't know what the cause is.)
while (input && numWords < MaxWords) {
input >> piglatin[numWords];
input >> english[numWords];
++numWords;
}
Now, if you really one one array with two elements, then you need to define another data structure because an array can only have one "thing" in each element. Define something that can hold two strings at once:
struct word_pair {
std::string piglatin;
std::string english;
};
Then you'll have just one array:
word_pair words[MaxWords];
You can fill it like this:
while (std::getline(input, line) && numWords < MaxWords) {
std::string::size_type space = line.find(' ');
if (space == std::string::npos)
std::cerr << "Only one word" << std::endl;
words[numWords].piglatin = line.substr(0, space);
words[numWords].english = line.substr(space + 1);
++numWords;
}
Notice how the code indexes into the words array to find the next word_pair object, and then it uses the . operator to get to the piglatin or english field as necessary.
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
int main()
{
// This will store each word (separated by a space)
vector<string> words;
// Temporary variable
string buff;
// Reads the data
fstream inFile("words.txt");
while(!inFile.eof())
{
inFile>>buff;
words.push_back(buff);
}
inFile.close();
// Display
for(size_t i=0;i<words.size();++i) cout<<words[i]<<" ";
return 0;
}
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main ()
{
vector<string> fileLines;
string line;
ifstream inFile("pigData.txt");
if ( inFile.is_open() ) {
while ( !inFile.eof() ) {
getline(inFile, line);
fileLines.push_back(line);
}
inFile.close();
} else {
cerr << "Error opening file" << endl;
exit(1);
}
for (int i=0; i<fileLines.size(); ++i) {
cout << fileLines[i] << "\n";
}
cout << endl;
return 0;
}
Related
i am trying to get my file to remove the leading and trailing space but it does not work.
this is the txt file contents:
392402 wench
I have tried printing out my code, and this is what is displayed.
first: 392402 wench second:
I want it to display this instead
first: 392402 second: wench
this is my code
void readFile(const string &fileName) {
int limit;
ifstream ifs(fileName);
string::size_type position;
key_type item;
mapped_type count;
string line;
if (ifs.is_open()) {
ifs >> limit;
for (int i = 0; i < limit; i++) {
getline(ifs, line);
position = line.find(" ", 0);
auto c = line.substr(position + 1);
item = line.substr(0, position);
cout << "first: " << c << " second: " << item << endl;
value_type value(item, count);
values.push_back(value);
}
} else {
cout << "Can't open file.";
}
what am i doing wrong? Thank you
The two biggest mistakes you're making are (a) not checking your values for expected output as you go, and (b) not running your code in a debugger to see what is really happening. If you had, the values of position, c, and item would have been blatantly wrong, and you could then surmise where to go from there.
Belaying the highly-likely possibility that the loop iteration is broken from inception because you never consumed the remainder of the entry line containing input, let's look at the actual data and what you're asking of it with your code.
We read this entire line:
392402 wench
You then ask "find the first single-space string in this line" via this code:
position = line.find(" ", 0);
Well, that would be here:
392402 wench
^here
So position is zero (0). You then ask for the sub-string, starting a that position + 1, through the end of the string with this code:
auto c = line.substr(position + 1);
Therefore c now contains (leading space removed via the +1):
392402 wench
Now we build item, which is done with this line:
item = line.substr(0, position);
Remember, position is zero, so you're asking for the string, starting at location 0, length 0. As you can imagine, that isn't going to amount to anything. So now item is an empty string.
Finally, the output statement:
cout << "first: " << c << " second: " << item << endl;
will produce:
first: 392402 wench second:
I.e. exactly what you're seeing. And that's it. Clearly this is wrong.
Alternative
Use better error checking, value checking, and a string stream for per-line extraction. The following code doesn't give two cents about your type aliases (mainly because you didn't include them anyway and I'd rather not loft any guesses as to their origin).
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <limits>
// Expects a file with the following format:
// count
// name1 value1
// name2 value2
// ...
void readFile(const std::string &fileName)
{
std::ifstream ifs(fileName);
if (ifs.is_open())
{
int limit;
if (ifs >> limit && limit > 0)
{
// consume through end of line.
ifs.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// repeat until `limit` iterations or stream error/eof
std::string line;
for (int i = 0; i < limit && std::getline(ifs, line); i++)
{
std::istringstream iss(line);
// extract line values. Note these *can* be formatted
// extraction for things besides just strings
std::string first, second;
if (iss >> first >> second)
{
std::cout << "first: " << first << " second: " << second << '\n';
// TODO: whatever you want to do with first/second
}
}
}
ifs.close();
}
else
{
std::cerr << "Can't open file: " << fileName << '\n';
}
}
Note: The above code will NOT work for remaining-line-content as the expected second value. E.g. It will not process something like this as you may first expect:
10000 this is a multi-word description
will produce this:
first: 10000 second: this
which is considerably different than what you may be expecting:
first: 10000 second: this is a multi-word description
There was no suggestion in the original post such support was mandatory, though adding it wouldn't be terribly difficult to add. If it is a requirement, I leave that task to you.
I'm doing the assignment and I'm at the end of my powers. Right now I can't figure out what's missing or what I could change.
I need the program to read me a file. If it finds the beginning of the search word, it lists the word and its meaning. If he finds it more than once, he writes only that word without meaning.
Right now, if the program finds more words, it writes the meaning for the first word and writes the word for the other words found.
I don't know what other cycle I could use. If you could help me, I would be grateful.
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include<bits/stdc++.h>
using namespace std;
int main()
{
ifstream dictionary("dictionary.txt");
if(!dictionary.is_open()){
cout<< "File failed to open" << endl;
return 0;
}
int option;
cout << "1.<starting>" << endl;
cout << "4.<stop>" << endl;
cin >> option;
string find_word;
string word, meaning;
string line;
string found;
int count = 0;
if (option == 1)
{
cout << "Find the meaning of the word beginning with the characters:";
cin >> find_word;
while (getline(dictionary,line))
{
stringstream ss(line);
getline (ss, word, ';');
getline (ss, meaning, ';');
if (word.rfind(find_word, 0) != string::npos)
{
count++;
if (count <=1)
{
found = word + meaning;
cout << found << endl;
}
if (count >= 2)
{
found = word ;
cout << found << endl;
}
}
}
}
if (option == 4)
{
return 0;
}
dictionary.close();
return 0;
}
EDIT
dictionary.txt looks like this:
attention; attentionmeaning
attention; attentionmeaning2
computer; computermeaning
criminal; criminalmeaning
boat; boatmeaning
alien; alienmeaning
atter; meaning
.
.
etc.
For example input is:
Find the meaning of the word beginning with the characters: att
this is what i get now (output):
attention attentionmeaning
attention
atter
this is what i expect (desire output):
attention
attention
atter
if program find only one searching word it should write this:
Find the meaning of the word beginning with the characters: bo
output:
boat boatmeaning
As it was already suggested, while reading the file, you don't know if there will be more than one entries matching your search term. That being said, you need some intermediate structure to store all the matching entries.
After you have gathered all the results, you can easily check if the data contains more than one result, in which case you only print the "word" without the meaning. In case there is only one result, you can print the "word" together with its meaning.
The code for that could look something like this:
struct Entry {
std::string name;
std::string meaning;
bool startsWith(const std::string& str) {
return name.find(str) != std::string::npos;
}
};
Entry createEntry(const std::string& line) {
Entry entry;
std::stringstream ss(line);
std::getline(ss, entry.name, ';');
std::getline(ss, entry.meaning, ';');
return entry;
}
int main() {
std::string query = "att";
std::ifstream dictionary("dictionary.txt");
std::vector<Entry> entries;
std::string line;
while (std::getline(dictionary, line)) {
Entry entry = createEntry(line);
if (entry.startsWith(query)) {
entries.emplace_back(std::move(entry));
}
}
for (const Entry& entry : entries) {
std::cout << entry.name << (entries.size() > 1 ? "\n" : " " + entry.meaning + '\n');
}
}
This code could definitely be more optimized, but for the sake of simplicity, this should suffice.
Demo
The problem is that at the first time through the loop you do not know if there is one or more valid words that follow from your string. I would suggest you create an empty list outside the loop, and push all the word and meaning pairs that match onto the list. Then after if the size of the list is 1 you can output the word and meaning pair else use a for loop to loop through and just print the words.
I am trying to read a database file (as txt) where I want to skip empty lines and skip the column header line within the file and store each record as an array. I would like to take stop_id and find the stop_name appropriately. i.e.
If i say give me stop 17, the program will get "Jackson & Kolmar".
The file format is as follows:
17,17,"Jackson & Kolmar","Jackson & Kolmar, Eastbound, Southeast Corner",41.87685748,-87.73934698,0,,1
18,18,"Jackson & Kilbourn","Jackson & Kilbourn, Eastbound, Southeast Corner",41.87688572,-87.73761421,0,,1
19,19,"Jackson & Kostner","Jackson & Kostner, Eastbound, Southeast Corner",41.87691497,-87.73515882,0,,1
So far I am able to get the stop_id values but now I want to get the stop name values and am fairly new to c++ string manipulation
mycode.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
string filename;
filename = "test.txt";
string data;
ifstream infile(filename.c_str());
while(!infile.eof())
{
getline(infile,line);
int comma = line.find(",");
data = line.substr(0,comma);
cout << "Line " << count << " "<< "is "<< data << endl;
count++;
}
infile.close();
string sent = "i,am,the,champion";
return 0;
}
You can use string::find 3 times to search for the third occurrence of the comma, and you must store the positions of the last 2 occurrences found in line, then use them as input data with string::substr and get the searched text:
std::string line ("17,17,\"Jackson & Kolmar\",\"Jackson & Kolmar, Eastbound, Southeast Corner\",41.87685748,-87.73934698,0,,1");
std::size_t found=0, foundBack;
int i;
for(i=0;i<3 && found!=std::string::npos;i++){
foundBack = found;
found=line.find(",",found+1);
}
std::cout << line.substr(foundBack+1,found-foundBack-1) << std::endl;
You can read the whole line of the file intoa string and then use stringstream to give you each piece one at a time up until and exluding the commas. Then you can fill up your arrays. I am assuming that you wanted each line in it's own array and that you wanted unlimited arrays. The best way to do that is to have an array of arrays.
std::string Line;
std::array<std::array<string>> Data;
while (std::getline(infile, Line))
{
std::stringstream ss;
ss << Line;
Data.push_back(std::vector<std::string>);
std::string Temp;
while (std::getline(ss, Temp, ','))
{
Data[Data.size() - 1].push_back(Temp);
}
}
This way you will have a vector, full of vectors, each of which conatining strings of all your data in that line. To access the strings as numbers, you can use std::stoi(std::string) which converts a string to an integer.
I'm coding in C++ and I'm trying to read in a file that I'd like to access certain chars at later. As in, what is the char at (line x, char y), at any given point in the file.
My only thought right now is to look for a newline character, and somehow index them so that I can refer back to newline x, check the length of a line, and pull a char at whatever position given the line length.
I'm not sure if that is a good approach or not.
Try this (for character in line "lineNum" and column "columnNum"):
ifstream inf;
inf.open(filename); //filename being c-string
string str;
for (int i = 0; i < lineNum; i++)
{
std::getline(inf, str);
}
This way "str" stores the line you are interested in (automatically checks for newline character and stops).
Then you can use:
char chr = str[columnNum];
to store the character you want in "chr" variable. And don't forget:
inf.close();
Unfortunately, to my knowledge you need to repeat this process every time you want to access a character.
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#define FILENAME "File.txt"
class FileGrid {
public:
typedef std::vector<std::string> Line;
typedef std::vector<std::string>::const_iterator LineIter;
typedef std::vector<std::vector<std::string>> StringMap;
typedef std::vector<std::vector<std::string>>::const_iterator StringMapIter;
void FillGrid(char* fileName) {
grid.clear();
std::ifstream in(FILENAME, std::ifstream::in);
if (!in.is_open()) {
std::cout << "problem reading " << FILENAME << std::endl;
return;
}
std::string words;
std::string word;
std::stringbuf buffer;
while (in.is_open() && std::getline(in, words)) {
std::stringstream ss(words);
Line line;
while (ss >> word) {
line.push_back(word);
}
grid.push_back(line);
}
}
void PrintGrid() {
StringMapIter b = grid.begin();
StringMapIter e = grid.end();
std::cout << "\t\tFile Content:" << std::endl;
while(b != e) {
for (unsigned int i = 0; i < b->size(); ++i) {
std::cout << b->operator[](i) << " ";
}
std::cout << std::endl;
++b;
}
}
char const & GetChar(int lineNo, int charNo) {
// LineNo checks etc
Line const & line = grid[lineNo];
for(std::string const & word : line ) {
if(charNo > word.size() + 1) {
charNo -= word.size() + 1;
}
else {
return word[charNo];
}
}
throw std::exception("charNo higher");
}
private:
StringMap grid;
};
void main() {
FileGrid grid;
grid.FillGrid(FILENAME);
grid.PrintGrid();
std::cout << grid.GetChar(0, 3); // should return first line, 4th character
}
Not the best code I've ever written but pretty much what I could do in a short time.
FileGrid handles reading and accessing the data. It reads the file line by line and stores it in a std::vector. When it finishes reading a line, it pushes that into another std::vector. In the end, we have a (sort of) 2D array of strings.
Again, not the best code and definitely not the most optimized code but the idea is still the same: read from the file line by line, separate each word and put them into an array of strings. If you can't use STL, you can dynamically create a 2D array for each line but since I don't know the specific requirements of your question, I just wrote something simple and bruteforce to show you the main way of storing grid of strings into the memory.
As long as it works. But reading the entire file into memory, if that's an option, would be simpler.
I asked a question yesterday but i didn't manage to do anything. I am using visual studio with marmalade and im already studying c++ but i need to get things done here so i asking for i little help and patience of you guys.
I got a few responses like
std::ifstream inp("restrict_words.txt");
std::istream_iterator<std::string> inp_it(inp), inp_eof;
std::vector<std::string> words(inp_it, inp_eof);
// words now has ever whitespace separated string
// from the input file as a vector entry
for (auto s : words)
std::cout << s << '\n';
and
std::ifstream ist("restrict_words.txt");
std::string word;
std::vector<std::string> readWords;
while(ist >> word)
readWords.push_back(word);
//test
for(unsigned i = 0; i != readWords.size(); ++i)
std::cout << readWords.at(i) << '\n';
Its such a easy thing and im not managing to do this.
I have my KingChatFilter.app and a chat folder inside my game folder. Inside this chat folder i have this txt with 160 words in 160 different lines.
All i need to do is read this txt and after putting it on a array checking if some of this string match with the one i want so i can do other stuff.
Please someone make me understand this thanks :)
I wrote a couple of functions to match your requirements:
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
using namespace std;
// Reads the file line by line and put all lines into words vector.
void read_to_vector(const char* file_name, vector<string> &words)
{
ifstream input(file_name);
string line;
while (getline(input, line))
{
words.push_back(line);
}
}
// Returns true if word is in words. False otherwise.
bool find_word(vector<string> &words, string word)
{
vector<string>::iterator it; // In c++11 you can change this to
// auto it;
// Using std::find from algorithm library.
it = find(words.begin(), words.end(), word);
return it != words.end(); // If the end of vector words was reached, then word was NOT found.
}
int main()
{
vector<string> words;
string target = "level";
read_to_vector("data.txt", words);
if (find_word(words, target))
cout << "Word " << target << " found" << endl;
else
cout << "Word " << target << " not found" << endl;
return 0;
}
following is working code i used to read file content line by line. One difference is maybe that u do not check if opening the file did succeed. If it does not, there come at least two main reasons to mind:
the file cannot be found at the specified path
the file is already opened by someone else
;
std::string fileNameWithPath = "..\\myFolder\\myfile.txt";
std::ifstream inputFile;
std::vector< std::string > fileContent;
inputFile.open( fileNameWithPath.c_str(), std::ios::in | std::ios::binary );
if( inputFile.is_open() )
{
std::string line;
while( std::getline( testDataFile, line ) )
{
inputFile.push_back( line );
}
}
inputFile.close();