I need to assign values to variables in C file by reading an excel sheet. I have written a code but only the last variable has been assigned a value since I have used for loop.It is overwriting the values assigned to the previous variables as I am creating a different output file after assigning values.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string s1, s2, s3,s4;
string filename, text, line;
string cfilename,funcname, signal, value;
int i , k , m;
cout << "Enter excel filename" << endl;
cin >> filename;
cout << "How many lines of text are in the file?" << endl;
cin >> m;
fstream file(filename);
if (!file) {
cerr << "No such file exists." << endl;
exit(1);
}
if (file.is_open()) {
while (file.eof()==0){
for (k = 0; k < m; k++) { //Loops for as many lines as there are in the file
for (i = 0; i < 4; i++) { //Loops for each comma-separated word in the line
if (i == 0){
getline(file, text, ',');
cfilename=text;
cout << cfilename << '\t';}
else if (i == 1){
getline(file, text, ',');
funcname=text;
cout << funcname << '\t';}
else if (i == 2){
getline(file, text, ',');
signal=text;
cout << signal << '\t';}
else if (i == 3){
getline(file, text, '\n');
value=text;
cout << value << '\n';}
}
string s1=signal,s2=value;
s2 = s2 + "; //";
int offset, inset;
string line;
string search=s1;
fstream cfile(cfilename);
fstream fileOutput;
fileOutput.open("output.c");
if(cfile.is_open() && fileOutput.is_open()) {
while(!cfile.eof()) {
getline(cfile, line);
if ((offset = line.find(funcname)) != string::npos){
cout << "found: " << funcname << endl;
string line1;
fileOutput << line << '\n';
skip:
while(getline(cfile,line1)){
if((inset=line1.find(search, 0)) !=string::npos){
cout<<"found: " << search << endl;
string s3 = s1+ "=" +s2;
//cout<<s3;
line1.replace( inset, inset+s1.size(), s3 );}
fileOutput << line1 << '\n';
goto skip;
}
getchar(); }
fileOutput << line << '\n'; }
cfile.close();
fileOutput.close();
}
}
}
}
file.close();
getchar();
return 0;
}
I am trying to search a function first and then variables inside that function.
Need some help here.
I'm not sure it's this the problem but... I thing the while () is too much.
when you have readed the m lines of the file, your
while (file.eof()==0)
result true because you haven't read nothing past the end of file.
So you read other m lines (failing but without controls about the success of the reading).
EDIT: I think you should write something like
cout << "Enter excel filename" << endl;
cin >> filename;
fstream file(filename);
if (!file) {
cerr << "No such file exists." << endl;
exit(1);
}
while ( getline(file, cfilename, ',') && getline(file, funcname, ',')
&& getline(file, signal, ',') && getline(file, value, '\n')) {
cout << cfilename << '\t' << funcname << '\t' << signal << '\t'
<< value << '\n';
string s1=signal,s2=value;
[...]
The program does exactly what you asked it to do:
you read a CSV file (excel format is binary!) line by line
for each line in csv:
you erase the output file because you open a fstream without specifying ios::ate
search something in a source file and write to the output file.
As you erase the output file at every new line from the input CSV file, you cannot get more than the last operation.
It would be much simpler if you opened the output file once outside of the loop.
And... while (file.eof() == 0) is an anti-pattern. You look whether you have reached end of file before trying to read a line, and then read 4 values when the first getline have set the eof flag. You must test for eof immediately after a read and not before...
Related
i was trying to find a way to check two different files and get, from the second, all lines that aren't in the first.. but does all the opposite.
I tried the possible to solve this but nothing...
This is the code:
int main(int argc, char *argv[])
{
setlocale(LC_ALL, "");
char username[UNLEN+1];
DWORD username_len = UNLEN+1;
GetUserName(username, &username_len);
stringstream buffer;
buffer << "C:\\Users\\" << username << "\\Desktop\\";
stringstream buffer2;
buffer2 << "C:\\Users\\" << username << "\\Desktop\\Legit.txt";
stringstream buffer3;
buffer3 << "C:\\Users\\" << username << "\\Desktop\\Unlegit.txt";
stringstream buffer4;
buffer4 << "C:\\Users\\" << username << "\\Desktop\\result.txt";
string results = buffer4.str();
int offset;
int num;
num = 1;
string search;
string linea;
string legit;
string unlegit;
string line;
cout << "Is the Legit.txt file at '" << buffer.str() << "'? [Y/N]: ";
cin >> legit;
if (legit == "Y" || legit == "y"){
}else if(legit == "N" || legit == "n"){
return 0;
}else{
cout << "\n.";
return 0;
}
string legitfile = buffer2.str();
cout << "\nIs the Unlegit.txt file at '" << buffer.str() << "'? [Y/N]: ";
cin >> unlegit;
if (unlegit == "Y" || unlegit == "y"){
}else if(unlegit == "N" || unlegit == "n"){
return 0;
}else{
cout << "\n";
return 0;
}
string unlegitfile = buffer3.str();
ifstream file(legitfile.c_str());
if(file.is_open()){
while(getline(file, line)){
ifstream MyFile(unlegitfile.c_str());
if(MyFile.is_open()){
while(!MyFile.eof()){
getline(MyFile,linea);
if((offset = linea.find(line, 0)) != string::npos) {
cout << "\n[" << num << "]" << " Word Found: " << line << "\n";
num++;
fstream result(results.c_str());
result << line << "\n";
result.close();
}
}
MyFile.close();
}
}
file.close();
return 0;
}else{
cout << "\nThe file '" << legitfile << "' does not exist.";
cout << "\nThe file '" << unlegitfile << "' does not exist.";
}
}
As i said, This code checks which words are equals in both (first & second) files and, once found, writes them to a third file, there is a way to do the opposite (check the two files and get the words that aren't equals)? Thank you so much!
I'm new, both in the forum and in C++, sorry if I make any mistakes. (sorry for my bad english too).
The classic solution to this sort of problem is to use a hash table collection to represent all the words in the first file. Then while iterating items from the second file, consult the set constructed of the first file. In C++, the std::unordered_set will do fine.
#include <unordered_set>
using namespace std;
unordered_set<string> firstFileSet;
unordered_set<string> missingFromSecondFileSet;
string line;
while(!firstfile.eof())
{
getline(firstfile,line);
firstFileSet.insert(line);
}
Then for each word in the second file, use a second set collection to keep track of what words are missing.
while(!secondfile.eof())
{
getline(secondfile,line);
if (firstFileSet.find(line) != firstFileSet.end())
{
missingFromSecondFileSet.insert(line);
}
else
{
firstFileSet.erase(line);
}
}
After the above runs, firstFileSet contains all the lines in the first file that were not present in the second. missingFromSecondFileSet contains all the lines in the second file that were not in the first:
for (auto &s : firstFileSet)
{
cout << s << " was in the first file, but not the second" << endl;
}
for (auto &s : missingFromSecondFileSet)
{
cout << s << " was in the second file, but not the first" << endl;
}
There is a program called diff on linux which does just what you are looking to do in C++.
It is written in C so you can just copy its source code =P
for (;; cmp->file[0].buffered = cmp->file[1].buffered = 0)
{
/* Read a buffer's worth from both files. */
for (f = 0; f < 2; f++)
if (0 <= cmp->file[f].desc)
file_block_read (&cmp->file[f],
buffer_size - cmp->file[f].buffered);
/* If the buffers differ, the files differ. */
if (cmp->file[0].buffered != cmp->file[1].buffered
|| memcmp (cmp->file[0].buffer,
cmp->file[1].buffer,
cmp->file[0].buffered))
{
changes = 1;
break;
}
/* If we reach end of file, the files are the same. */
if (cmp->file[0].buffered != buffer_size)
{
changes = 0;
break;
}
}
Taken from ftp://mirrors.kernel.org/gnu/diffutils/diffutils-3.0.tar.gz > src/analyze.c
I'm working on the following problem:
I need to write a prgoram that reads an ASCII text file from the hard drive and allows the user to display and edit the contents of the file line-by-line.
It must have the following features:
It reads the file name from the standard output and opens the text file using a file stream.
When the file is loaded, the user enters the text line number.
If the line exists, it is displayed in the standard output.
If the line does not exist (the user has entered a line number
that is greater than the number of lines in the file), an error message is displayed,
for example: The line 82 does not exist. When the line is displayed the user is given
an option to enter a new string in the standard input that will become the contents of
the line. The string can contain blank spaces. Then the user is asked to enter another line number.
Finally, the user is asked whether he wants to save the changes in the file or not.
Technical requirements: The program must be composed by more than one function
This is my code so far:
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
void printErrorMessage(int lineNumber)
{
cout << endl << " ERROR: The line " << lineNumber << " does not exist"
<< endl;
}
int main()
{
int line_number;
vector<string> TextVector;
int loop = 1;
fstream myfile;
myfile.open("test.txt", std::fstream::in | std::fstream::out);
while(loop == 1)
{
if (myfile.is_open())
{
// get end line of file.
cout << "File has opened successfully." << endl;
}
else
{
cout << "File hasn't opened successfully.";
return 0;
}
cout << "Enter the text line number:" << endl;
cin >> line_number;
size_t lines_count = 0;
string line;
while(getline(myfile, line))
{
TextVector.push_back(line); // push to text file
}
if(line_number > TextVector.size() + 1)
{
printErrorMessage(line_number);
return 0;
}
cout << TextVector[line_number] << endl;
cout << "If you'd like to change the line, please enter it, otherwise enter n to exit" << endl;
string changeLine;
getline(cin, changeLine);
if (changeLine == "n")
{
myfile.close();
return 0;
}
TextVector[line_number] = changeLine; // changes the line with the new string
cout << "Would you like to enter a new line to edit? (Y/n)" << endl;
string newLine;
cin >> newLine;
if (newLine != "y" && newLine != "Y")
{
cout << "Would you like to save all your changes to the file? (Y/n)" << endl;
string saveChanges;
cin >> saveChanges;
if (saveChanges != "y" && saveChanges != "Y")
{
myfile.close();
return 0;
}
for (int i = 0; i < TextVector.size() + 1; i++)
{
cout << TextVector[i] << endl;
myfile << TextVector[i] << endl;
myfile.flush();
}
myfile.close();
return 0;
}
}
return 0;
}
Technically I do save the changes to the vector, but for some reason I cannot get to overwrite the vector into the text file that already is full.
Also, any idea why the
getline(cin, changeLine);
Still acts as if it's a normal string? shouldn't it get the whole line entered togethe with the spaces?
Some guidance would really be appreciated!
The following code is supposed to get a text file and read all its lines and print them put on console but although it properly saves the fname, it won't do anything after that. I appreciate if you could let me know what the problem is.
EDIT: To be more accurate, I will eventually want to call a few functions inside the else block but I first need to figure out why my program doesn't get to that point.
int main()
{
string fname = "", line, content;
ifstream ifs; // input file stream
string command = "";
int k;
cout << "---- Enter your command and the file name : ";
while (getline(cin, line)){
int i = 0;
for (i = 0; i<line.length(); i++) {
command += line[i];
if (line[i] == ' ')
{
break;
}
}
for (int j = i + 1; j<line.length(); j++)
{
fname += line[j];
}
cout << command;
}
if (command == "exit ")
{
exit(EXIT_SUCCESS);
}
// tries to open the file whose name is in string fname
ifs.open(fname.c_str());
if (ifs.fail()) {
cerr << "ERROR: Failed to open file " << fname << endl;
ifs.clear();
}
else { //do getline here to read content
while (getline(ifs, content))
{
cout << "Content " << k++ << " : " << content << endl;
//Call functions here later
}
}
ifs.close(); // always remember to close it
cout << "---- Enter another file and command name : ";
}
Got it sorted out myself. I was closing the while loop too early. It has to be closed after ifs.close(); instead.
Something is definitely wrong with my loop because after reading and executing the first line the programs ends.
if (infile.is_open())
{
cout << "Input filename: ";
cin>>filename;
infile.open(filename.c_str());
cout<< "Output filename: ";
cin>>filename;
outfile.open(filename.c_str());
while(getline(infile,input))
{
string output = "";
for(int x = 0; x < input.length(); x++)
output += cipher(input[x]);
cout<<output<<endl;
outfile<<output;
}
}
Any suggestions on how to make this work?
EDIT
Followed the suggestions and got this:
if (infile.is_open()) {
cout << "Input filename: ";
cin>>filename;
infile.open(filename.c_str());
if (!infile.is_open())
{
std::cout << "Failed to open the input file." << std::endl;
return -1;
}
cout<< "Output filename: ";
cin>>filename;
outfile.open(ofilename.c_str());
if (!outfile.is_open())
{
std::cout << "Failed to open the output file." << std::endl;
return -1;
}
while(getline(infile,line)){
string output = "";
for(int x = 0; x < input.length(); x++) {
output += cipher(input[x]);
}
}
BUT it still reads only the first line...everything else is working perfectly fine....just can't read anything beyond the first line..
It seems that you misunderstood the point of the fstream's is_open() method, since this code:
if (infile.is_open())
{
cout << "Input filename: ";
cin>>filename;
infile.open(filename.c_str());
...
}
checks whether the infile has been successfully opened (i.e. if either a previous call to member open succeeded or if the object was successfully constructed using the parameterized constructor,
and close has not been called since) and in case it is open it retrieves the name of the input file from cin and opens the file.
Good start would be the program that reads from the input file line by line and writes these lines to the output file without processing them:
// retrieve the name of the input file and open it:
cout << "Input filename: ";
cin>>filename;
infile.open(filename.c_str());
if (!infile.is_open())
{
std::cout << "Failed to open the input file." << std::endl;
return -1;
}
// retrieve the name of the output file and open it:
cout << "Output filename: ";
cin >> filename;
outfile.open(filename.c_str());
if (!outfile.is_open())
{
std::cout << "Failed to open the output file." << std::endl;
return -1;
}
std::string line;
while(getline(infile,line))
{
std::cout << line << std::endl;
outfile << line;
}
So I suggest this.
Write char cipher(char ch) to return enciphered input for anything. if you don't want to encipher whitespace, then don't. But always return the enciphered character or unmodifed character.
Use std::transform , std::istream_iterator , and std::ostream_iterator to transform your input and output files.
Check your file states at the correct times.
An example appears below:
#include <iostream>
#include <fstream>
#include <iteraor>
#include <string>
using namespace std;
char cipher(char ch)
{
if (std::isalpha(ch))
{
// TODO: change ch to whatever you want here.
}
// but always return it, whether you changed it or not.
return ch;
}
int main()
{
int res = EXIT_SUCCESS;
string in_filename, out_filename;
cout << "Input filename: ";
cin >> in_filename;
cout << "Output filename: ";
cin >> out_filename;
// don't skip whitespace
ifstream infile(in_filename);
ofstream outfile(out_filename);
if ((infile >> noskipws) && outfile)
{
std::transform(istream_iterator<char>(infile),
istream_iterator<char>(),
ostream_iterator<char>(outfile),
cipher);
}
else
{
perror("Failed to open files.");
res = EXIT_FAILURE;
}
return res;
}
Here's my code so far:
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
int main()
{
int count = 0;
string fileName;
string keyWord;
string word;
cout << "Please make sure the document is in the same file as the program, thank you!"
<< endl << "Please input document name: " ;
getline(cin, fileName);
cout << endl;
cout << "Please input the word you'd like to search for: " << endl;
cin >> keyWord;
cout << endl;
ifstream infile(fileName.c_str());
while(infile.is_open())
{
getline(cin,word);
if(word == keyWord)
{
cout << word << endl;
count++;
}
if(infile.eof())
{
infile.close();
}
}
cout << count;
}
I'm not sure how to go to the next word, currently this infinite loops...any recommendation?
Also...how do I tell it to print out the line that that word was on?
Thanks in advance!
while(infile >> word)
{
if(word == keyWord)
{
cout << word << endl;
count++;
}
}
This would do the job. Please read about streams more.
If all you want to do is count the number of keywords in a file then:
int count = std::count(std::istream_iterator<std::string>(infile),
std::istream_iterator<std::string>(),
keyword);
If you want to read words.
But also want to print the line numbers then somthing like this should work:
std::string line;
std::ifstream infile("plop");
int lineNumber = 0;
while(std::getline(infile, line))
{
++lineNumber ;
std::stringstream linestream(line);
int hits = std::count(std::istream_iterator<std::string>(linestream),
std::istream_iterator<std::string>(),
keyword);
if (hits != 0)
{
std::cout << "Line: " << lineNumber << " Matches(" << hits << ")\n";
}
count += hits;
}
The problem comes in this part of the source code:
getline(cin,word);
if(word == keyWord)
{
cout << word << endl;
count++;
}
First of all, you don't want to read lines from cin. You want to read words from infile. So you should replace the first line of your code inside the loop by:
infile >> word;
if(word == keyWord)
{
cout << word << endl;
count++;
}
Also, you should change the condition of the loop. You don't need to check if the infile is open here. You should check for that before the loop starts. For the loop, you need to check whether the eof state has been reached or not:
if ( !infile.is_open() ) {
cerr << "Error while opening file." << endl;
exit( EXIT_FAILURE );
}
while( !infile.eof() ) {
infile >> word;
if(word == keyWord)
{
cout << word << endl;
count++;
}
}
And as you can see, now you can get rid off that strange second if you put inside the loop.
Last step is to introduce the "reading ahead" technique: it does not make sense to test for eof when we haven't read anything.
if ( !infile.is_open() ) {
cerr << "Error while opening file." << endl;
exit( EXIT_FAILURE );
}
infile >> word;
while( !infile.eof() ) {
if( word == keyWord )
{
cout << word << endl;
count++;
}
infile >> word;
}
Hope this helps.
Change while(infile.is_open()) to while(infile). Then you can remove the redundant eof test at the end.
It's still open even if you've encountered an error or reached the end of file. It's likely you are in a scenario where failbit is getting set (getline returns nothing), but eof has not been encountered, so the file never gets closed, so your loop never exits. Using the operator bool of the stream gets around all these problems for you.