I search for my problem but haven't found an answer.
I try to read a table of double values from a file into an 2d-array of doubles in C++, but i can't get it to work.
The file is full of other junk i don't need and the table is parenthesized by "BEGIN TABLE" and "END TABLE". The Table has 5 doubles in a row with space delimiter and an unknown number of rows. So the File looks like this
junk
.
.
.
BEGIN TABLE
0.12145 0.23234 2.32423 1.32422 0.12345
1.34534 1.23423 5.21323 3.12313 1.22231
.
.
.
2.32422 3.23423 1.12345 4.34532 2.23423
END TABLE
So first I go through the file, search for the start and end of table and allocate memory for my array:
char sBuffer[100];
double** darrTable;
int iRes = -1;
iRes = fopen_s(&pFile, strFile, "rb");
if (iRes==0)
{
int ilines = 0;
bool beof = false;
bool bfound = false;
//get number of lines for array allocation
while(!beof)
{
fgets(sBuffer,100,pFile);
if(strstr(sBuffer,"END TABLE"))
{
bfound = false;
beof = true;
}
if(bfound) ilines++;
if(strstr(sBuffer,"BEGIN TABLE"))bfound = true;
}
darrTable = new double*[ilines+1];
for(int i = 0; i < (ilines+1); ++i) darrTable [i] = new double[5];
}
in an other code block i go through the lines again and want to readout the string, but it won't work
int ilines = 0;
bool beof = false;
bool bfound = false;
while(!beof)
{
fgets(sBuffer,100,pFile);
if(strstr(sBuffer,"END TABLE"))
{
bfound = false;
beof = true;
}
if(bfound)
{
sscanf_s(sBuffer,"%d %d %d %d %d",&darrTable [ilines][0],&darrTable [ilines][1],&darrTable [ilines][2],&darrTable [ilines][3],&darrTable [ilines][4]);
ilines++;
}
if(strstr(sBuffer,"BEGIN TABLE"))bfound = true;
}
it compiles and runs without error but all i get is an array full of 0.000000000 for darrTable. sscanf_s returs 1 witch suggest that 1 value was found, but thats all values are 0.
I use VisualStudio 2005 SP0.
Sorry for my english and thanks for your help in advance.
Use C++ style
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <fstream>
std::vector<std::vector<double>> ParseFile(const std::string& filename)
{
std::vector<std::vector<double>> data;
std::ifstream file(filename.c_str());
std::string line;
while (std::getline(file, line))
{
if (line == "BEGIN TABLE")
{
while (std::getline(file, line))
{
if (line == "END TABLE")
{
break;
}
else
{
data.push_back(std::vector<double>());
std::istringstream ss(line);
double temp;
while (ss >> temp)
{
data.back().push_back(temp);
}
if (data.back().size() != 5)
{
// missing or extra data
}
}
}
break; // END TABLE missing
}
}
if (data.empty())
{
// BEGIN TABLE missing or there was no data lines
}
return data;
}
Related
I admittedly am an extreme C++ novice, so please forgive me for my probably very naive question.
I am writing code that should parse an assembly language file in its fundamental parts, to be translated into machine language at a second stage.
I have built a parser class, but I am not having success in opening the external assembly .asm textfile, and in feeding it to the various functions that compose my parser class.
More in particular, there are problems with the constructor.
I attach the full code I wrote below:
// parses .asm assembly files
#include <iostream>
#include <fstream>
#include <varargs.h>
#include <string>
using namespace std;
class parser
{
private:
istream inputfile;
char inputname[30];
string line;
bool endfile;
bool a_command, l_command, c_command;
string parsedLine, destParsedLine, compParsedLine, jumpParsedLine;
public:
// default parser constructor
parser()
{
}
//parser(char* argv[])
//{
// reader(argv[]);
//}
// opens input file
string reader(char* argv[])
{
strcpy(inputname,argv[1]);
strcat(inputname,".asm");
// opens input .asm file
ifstream inputfile(inputname);
// reads first line
getline(inputfile,line);
if (line[0] == '/' || line.empty())
inputfile.ignore(line.length(),'\n');
return line;
}
// checks if at end file
bool hasMoreCommands()
{
a_command = false;
l_command = false;
c_command = false;
endfile = false;
if (inputfile.eof())
endfile = true;
return endfile;
}
// advances read of inputfile
void advance()
{
if (line[0] == '/' || line.length() == 0)
inputfile.ignore(line.length(),'\n');
getline(inputfile,line);
}
/* function for labelling the type of command (address,computation,label) */
bool commandType()
{
if (line[0] == '#')
a_command = true;
else if (line[0] == '(')
l_command = true;
else
c_command = true;
return a_command, l_command, c_command;
}
// function to select parsing function
string selector()
{
if (a_command || l_command)
symbol();
else if (c_command)
{
dest();
comp();
jump();
string parsedLine = destParsedLine + compParsedLine + jumpParsedLine;
}
return parsedLine;
}
// function returning address or label symbol
string symbol()
{
if (a_command)
string parsedLine = line.substr(1);
else if (l_command)
string parsedLine = line.substr(1,line.length()-1);
return parsedLine;
}
// functions returning computation destination
string dest()
{
size_t equal = line.find('='); //no '=' found = returns 'npos'
string destParsedLine = line.substr(0,equal);
return destParsedLine;
}
string comp()
{
size_t equal = line.find('=');
size_t semicolon = line.find(';');
string compParsedLine = line.substr(equal,semicolon);
return compParsedLine;
}
string jump()
{
size_t semicolon = line.find(';');
string jumpParsedLine = line.substr(semicolon);
return jumpParsedLine;
}
};
// main program
int main (int argc, char *argv[])
{
bool endfile = false;
string parsedLine;
int count = 0;
if ((argc != 2) || (strchr(argv[1],'.') != NULL))
{
cout << argv[0] << ": assembly .asm file argument should be supplied, without .asm extension\n";
return 1;
}
parser attempt1 = parser();
attempt1.reader(argv[]);
while (!endfile)
{
attempt1.hasMoreCommands();
if (endfile)
return 0;
if (count > 0)
attempt1.advance();
attempt1.commandType();
attempt1.selector();
cout << parsedLine << endl; //debugging purposes
count++;
}
}
I provide the name of the .asm textfile to be opened, from the command line (.asm file located in the same folder of this cpp file).
Hence I need to use varargs.h which I suppose may be part of the problem.
When I try to build this, visual studio 2008 gives me the following 2 errors:
1 error C2512: 'std::basic_istream<_Elem,_Traits>' : no appropriate default constructor available line 21
2 error C2059: syntax error : ']' line 137
Help appreciated, and insults tolerated, thanks :)
Your class uses std::istream for the inputfile member, but does not initialize it. That will not work.
In this situation, your class would need to use std::ifstream instead for its inputfile member, and then call its open() method before trying to read from it.
Also, your reader() method is ignoring the inputfile member, instead creating a local variable of the same name to read from. You need to get rid of that local variable, and instead call open() on your class member.
Following #Remy Lebeau suggestions, the modified code below at least compiles correctly (still does not do what it is supposed to do though)
// parses .asm assembly files
#include <iostream>
#include <fstream>
#include <varargs.h>
#include <string>
using namespace std;
class parser
{
private:
istream inputfile;
char inputname[30];
string line;
bool endfile;
bool a_command, l_command, c_command;
string parsedLine, destParsedLine, compParsedLine, jumpParsedLine;
public:
// default parser constructor
parser()
{
}
// ignores inputfile line if comment or empty
void ignoreline()
{
if (line[0] == '/' || line.empty())
inputfile.ignore(line.length(),'\n');
}
// composes inputfile name and opens input file
void reader(char* argv[])
{
strcpy(inputname,argv[1]);
strcat(inputname,".asm");
// opens input .asm file
inputfile.open(inputname, fstream::in);
// reads first line
getline(inputfile,line);
ignoreline();
}
// checks if at end file
bool hasMoreCommands()
{
a_command = false;
l_command = false;
c_command = false;
endfile = false;
if (inputfile.eof())
endfile = true;
return endfile;
}
// advances read of inputfile
void advance()
{
ignoreline();
getline(inputfile,line);
}
/* function for labelling the type of command (address,computation,label) */
bool commandType()
{
if (line[0] == '#')
a_command = true;
else if (line[0] == '(')
l_command = true;
else
c_command = true;
return a_command, l_command, c_command;
}
// function to select parsing function
string selector()
{
if (a_command || l_command)
symbol();
else if (c_command)
{
dest();
comp();
jump();
string parsedLine = destParsedLine + compParsedLine + jumpParsedLine;
}
return parsedLine;
}
// function returning address or label symbol
string symbol()
{
if (a_command)
string parsedLine = line.substr(1);
else if (l_command)
string parsedLine = line.substr(1,line.length()-1);
return parsedLine;
}
// functions returning computation destination
string dest()
{
size_t equal = line.find('='); //no '=' found = returns 'npos'
string destParsedLine = line.substr(0,equal);
return destParsedLine;
}
string comp()
{
size_t equal = line.find('=');
size_t semicolon = line.find(';');
string compParsedLine = line.substr(equal,semicolon);
return compParsedLine;
}
string jump()
{
size_t semicolon = line.find(';');
string jumpParsedLine = line.substr(semicolon);
return jumpParsedLine;
}
};
// main program
int main (int argc, char *argv[])
{
bool endfile = false;
string parsedLine;
int count = 0;
if ((argc != 2) || (strchr(argv[1],'.') != NULL))
{
cout << argv[0] << ": assembly .asm file argument should be supplied, without .asm extension\n";
return 1;
}
parser attempt1 = parser();
attempt1.reader(argv);
while (!endfile)
{
attempt1.hasMoreCommands();
if (endfile)
return 0;
if (count > 0)
attempt1.advance();
attempt1.commandType();
attempt1.selector();
cout << parsedLine << endl;
count++;
}
return 0;
}
I am quite new to c++ programming and data structures and really need some help. I am working on an assignment where I have a text file with 100 lines and on each line there is an item, a status(for sale or wanted), and a price. I need to go through the text file and add lines to an array of structs and as I add lines I need to compare the new information with the previously submitted information. If there is a line that is wanted and has a price higher than a previously input item that is for sale then the item would be removed from the struct and the array of structs shifted.
The place that I am having trouble is in actually shifting all the structs once a line that satisfies the condition is found.
My issue is that when I try to shift the array of structs using the second for loop nothing happens and I just get null structs and nothing seems to move.
Please if you guys can offer any help it would be greatly appreciated.
Below is the code of the text file and my current code.
#include<iostream>
#include<fstream>
#include <string>
#include <algorithm>
#include <sstream>
using namespace std;
struct items
{
string type;
int status;
int price;
} itemArray [100];
int main(int argc, char *argv[]) {
int x = -1;
//int chickenCount = 0;
int counter = 0;
int itemsSold = 0;
int itemsRemoved = 0;
int itemsForSale = 0;
int itemsWanted = 0;
string itemType;
int itemStatus = 0;
int itemPrice = 0;
int match = 0;
ifstream myReadFile( "messageBoard.txt" ) ;
std::string line;
//char output[100];
if (myReadFile.is_open()) {
while (!myReadFile.eof()) {
getline(myReadFile,line); // Saves the line in STRING.
line.erase(std::remove(line.begin(), line.end(), ' '), line.end());
//cout<<line<<endl; // Prints our STRING.
x++;
std::string input = line;
std::istringstream ss(input);
std::string token;
while(std::getline(ss, token, ',')) {
counter++;
//std::cout << token << '\n';
if (counter>3){
counter =1;
}
//cout << x << endl;
if (counter == 1){
itemType = token;
//cout<< itemType<<endl;
}
if (counter == 2){
if (token == "forsale"){
itemStatus = 1;
//itemsForSale++;
}
if (token == "wanted"){
itemStatus = 0;
//itemsWanted++;
}
//cout<< itemStatus<<endl;
}
if (counter == 3){
itemPrice = atoi(token.c_str());
//cout<< itemPrice<<endl;
}
//cout<<"yo"<<endl;
}
if (x >= 0){
for (int i = 0; i<100;i++){
if (itemArray[i].type == itemType){
//cout<<itemType<<endl;
if(itemArray[i].status != itemStatus){
if (itemArray[i].status == 1){
if(itemPrice>=itemArray[i].price){
itemsSold++;
match =1;
//itemArray[i].type = "sold";
for (int j=i; j<100-1;j++){
//cout<<j<<endl;
itemArray[j].type = itemArray[j+1].type;
itemArray[j].status = itemArray[j+1].status;
itemArray[j].price = itemArray[j+1].price;
}
i =i-1;
break;
}
}
if (itemArray[i].status == 0){
if(itemArray[i].price>=itemPrice){
itemsSold++;
match = 1;
//itemArray[i].type = "sold";
for (int j=i; j<100-1;j++){
//cout<<j<<endl;
itemArray[j].type = itemArray[j+1].type;
itemArray[j].status = itemArray[j+1].status;
itemArray[j].price = itemArray[j+1].price;
}
i=i-1;
break;
}
}
}
}
}
}
if (counter == 3 && match == 0){
itemArray[(x)].type = itemType;
itemArray[(x)].status = itemStatus;
itemArray[(x)].price = itemPrice;
}
match = 0;
// cout << itemArray[x].type << " " << itemArray[x].status<<" "<<itemArray[x].price<<endl;
}
for(int i=0;i<100;i++){
cout<<itemArray[i].type<< " "<<itemArray[i].status<<" "<<itemArray[i].price<<endl;
}
//cout<<itemArray[1].price<<endl;
cout << itemsSold<<endl;
}
myReadFile.close();
return 0;
}
text file: https://drive.google.com/file/d/0B8O3izVcHJBzem0wMzA3VHoxNk0/view?usp=sharing
Thanks for the help
I see several issues in the code, but without being able to test it, I think the main problem is that you always insert new elements at position 'x' which correspond to the currently line read from the file, without taking into account any shift of elements done. You should insert the new element at the first empty slot (or just overwrite the old element instead of shifting everything).
An other issue is that you do not initialize the status and price in your array.
The best way would be to rewrite the code by using more standard C++ features, for example:
replace the items structure by a class with a constructor defining default values
use object copy (there is no need to copy a struct element by element)
use standard C++ containers like a list (see http://www.cplusplus.com/reference/list/list/) which has insert and erase methods
I am trying to match words from user input with a string from a text file.
When this code runs, it crashes after the file is opened. (marked by ****)
How can I change it to properly match the strings from user input with strings from the text file.
Any help would be appreciated, thank you.
const int Size = 81; // 80 characters for the line + 1 for the '\0'
const int MaxNumberOfWords = 10;
int main() {
char input[81], temp[81], fin[81];
printf("Input a string\n");
fgets(input, 81, stdin);
int len = strlen(input);
char *div;
div = strtok(input, " ");
while (div != NULL) {
printf("%s\n",div);
div = strtok(NULL, " ");
ifstream inStream; // declare an input stream for my use
char theWords[ MaxNumberOfWords][ Size]; // Array to store words from input line
int wordRow = 0; // Row for the current word
char wordToLookup[ Size]; // word to lookup
bool wordWasFound = false; // flag to track whether or not word is found
char c; // stores return character after input
inStream.open( "C:\\Users\\dqiao4\\Desktop\\Dev-Cpp\\dictionaryMax6.txt");
assert( ! inStream.fail() ); // make sure file open was OK
//*****this is where the code crashes
while ( inStream >> theWords[ wordRow]) {
wordRow++;
}
for (int i=0; i<wordRow; i++) {
// See if this word matches
if ( strcmp( div, theWords[ i]) == 0 ){
wordWasFound = true;
break; // quit looking
}
}
}
}
int main() {
char input[81];int i=0,j=0,k=0;
cout<<"Input a string ";
while(i<=80){
input[i]=getch();
cout<<input[i];
if(input[i]=='.')
break;
i++;
}
ifstream File("C:\\User\\New.txt");
string line;
if(File)
{
while(getline(File, line))
{
char buff[1024];
strcpy(buff, line.c_str());
while(j<35){
k=0;
while(k<i){
if(buff[j]==input[k])
{
int j1=j,k1=k;
while(true){
if(buff[j1]==input[k1])
{
if(input[j1]=='.'){
cout<<"match";
return 0;
}
j1++;k1++;
}
else
break;
}
}k++;
}j++;
cout<<endl;
}
}
}
}
#inlude <sstream>
#include <string>
in your source and read the text file in string stream buffer, convert it to string and do
auto pos = file_in_str.find("word_to_find");
That pos is the the starting index of word in file
I am trying to write a program that will compare an input file to a dictionary file filled with tons of words. After comparing the words, I want to output the words that are spelled incorrectly. Here is my code:
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <vector>
using namespace std;
void trim(string s)
{
size_t p = s.find_first_not_of(" \t");
s.erase(0, p);
p = s.find_last_not_of(" \t");
if (string::npos != p)
s.erase(p+1);
}
int main()
{
ifstream input;
ifstream words;
input.open("/Users/jordan/Desktop/CS60/Word_dictionary_check/input.txt");
if(input.fail())
{
cout<<"Input file opening failed";
exit(1);
}
words.open("/Users/jordan/Desktop/CS60/Word_dictionary_check/words.txt");
if(words.fail())
{
cout<<"Words file opening failed";
}
vector <string> wordCheck;
vector <string> misspelledWord;
string temp = "";
while(!input.eof())
{
input>>temp;
wordCheck.push_back(temp);
}
ofstream output;
output.open("/Users/jordan/Desktop/CS60/Word_dictionary_check/output.txt");
if(output.fail())
{
cout<<"Output file opening failed";
exit(1);
}
for(int j = 0; j < wordCheck.size(); j++)
{
bool dontprint = false;
while(!words.eof())
{
words>>temp;
if(temp == wordCheck[j])
{
dontprint = true;
}
}
if(dontprint == false)
{
misspelledWord.push_back(wordCheck[j]);
}
}
for(int i = 0; i < misspelledWord.size() ; i++)
{
output<<misspelledWord[i]<<endl;
}
return 0;
}
I believe something with whitespace or with the comparing of strings is a problem. Thanks for helping me out!
I can see few obvious problems. I have added comments. This should solve your problem but I am not going to write code for you.
for(int j = 0; j < wordCheck.size(); j++)
{
bool dontprint = false;
//Make your words file pointer to point to start of file. USe seek function
while(!words.eof())
{
words>>temp;
if(temp == wordCheck[j])
{
dontprint = true;
//You can break here. As once word is found, you don't need to check the word file further
}
}
if(dontprint == false)
{
misspelledWord.push_back(wordCheck[j]);
}
}
I've spent like 2 hours trying to parse the following bytes from a file :
>Rosalind_6404
CCTGCGGAAGATCGGCACTAGAATAGCCAGAACCGTTTCTCTGAGGCTTCCGGCCTTCCC
TCCCACTAATAATTCTGAGG
>Rosalind_5959
CCATCGGTAGCGCATCCTTAGTCCAATTAAGTCCCTATCCAGGCGCTCCGCCGAAGGTCT
ATATCCATTTGTCAGCAGACACGC
>Rosalind_0808
CCACCCTCGTGGTATGGCTAGGCATTCAGGAACCGGAGAACGCTTCAGACCAGCCCGGAC
TGGGAACCTGCGGGCAGTAGGTGGAAT
I would like to store the word Rosalind_, and store every line, concatenate all, and have just one string having all the lines.
I tried the following code, but it still doesn't work probably, I always miss the last line.
int main()
{
std::ifstream infile("data_set.txt");
map < int, string > ID;
map < int, string > dataSetMap;
int idNumber= 0;
int idDataSetNumber = 0;
std::string line;
std::vector<string> dataSetString;
std::string seqid;
while (!infile.eof() )
{
while(std::getline(infile, line))
{
if ( line.substr(0,1)== ">")
{
conct = "";
seqid = line.substr(1,line.length() - 1);
ID.insert(make_pair( idNumber++, seqid));
lineNumber = 0;
line.clear();
std::string data= "";
if(dataSetString.size()>0)
{
for (int i = 0; i<dataSetString.size(); i++)
{
data+=dataSetString[i];
}
dataSetMap.insert(make_pair(idDataSetNumber++, data));
}
dataSetString.clear();
}
if(!line.empty() )
{
dataSetString.push_back(line);
}
}
}
I'm trying to practice problems solving approaches, and that really gave me headache.
I'm looking for a better approach also.
This code does what you want:
#include <map>
#include <vector>
#include <string>
#include <iostream>
#include <fstream>
int main()
{
std::istream& infile = std::cin;
std::map < int, std::string > ID;
std::map < int, std::string > dataSetMap;
int idNumber= 0;
int idDataSetNumber = 0;
std::string line;
std::vector<std::string> dataSetString;
std::string seqid;
bool success = std::getline(infile, line);
while(success) {
if( line.substr(0,1) == ">" ) {
seqid = line.substr(1,line.length() - 1);
ID.insert(make_pair( idNumber++, seqid));
std::string data;
while(success = std::getline(infile, line)) {
if(line.substr(0,1) == ">") break;
data += line;
}
dataSetMap.insert(make_pair(idDataSetNumber++, data));
} else {
std::cout << "Invalid input file. It needs to start with >SOME_ID" << std::endl;
return 1;
}
}
std::cout << "Parsed data ----------------" << std::endl;
for(std::map<int,std::string>::const_iterator it = dataSetMap.begin(); it != dataSetMap.end(); ++it) {
std::cout << "Id: " << ID[it->first] << std::endl;
std::cout << (it->second) << std::endl;
}
}
It first reads a line from the input file and tries to parse it as an ID. If that fails, it returns an error. Then it reads the data until it finds another ID or EOF. It inserts the data and continues to parse the ID it found if it didn't encounter EOF.
Working demo: http://ideone.com/F4mcrc
Note: This fails when the file is empty, you might want to check for the empty string or a string containing only whitespaces in the else of the ID check and skip it.
EDITED I have corrected my answer and tested it. So no more downvote please!
int main()
{
using namespace std;
ifstream infile("data_set.txt");
map < int, string > ID;
map < int, string > dataSetMap;
int idNumber= 0;
int idDataSetNumber = 0;
string line;
vector<string> dataSetString;
string seqid;
while ( true)
{
bool b=infile.eof();
if(!b)
std::getline(infile, line);
if ( line.substr(0,1)== ">" || b)
{
if(!b)
{
seqid = line.substr(1,line.length() - 1);
ID.insert(make_pair( idNumber++, seqid));
}
line.clear();
string data= "";
if(dataSetString.size()>0)
{
for (unsigned int i = 0; i<dataSetString.size(); i++)
{
data+=dataSetString[i];
}
dataSetMap.insert(make_pair(idDataSetNumber++, data));
}
dataSetString.clear();
if(b)
break;
}
if(!line.empty() )
{
dataSetString.push_back(line);
}
}
return 0;
}