C++ - infinite loop when reading characters of file - c++

I want to read some values from the file and return their codes. for example if I have "if(x=3)" in the file, the output would be something like this:
22 if
12 (
2 x
11 =
1 3
13 )
each number in the left is a code for the value in right side for example for identifier (here is X) it is 2 and so on.
The problem is that when I open the "test.txt" file in the function SCAN and it found the Code then it return it and put the equivalent character to be shown at the output. but from then it goes to infinite loop because the previous returned characters can not be changed. So it returned infinite output of "22 if".
int main () {
int Code;
string Str;
do
{
Code=SCAN(Str);
cout<<Code<<"\t"<<Str<< endl;
}
while(Code !=0);
}
and here is the SCAN function
int SCAN(string& String){
int Code;
ifstream ifs;
ifs.open ("test.txt", ifstream::in);
char c = ifs.get();
String=c;
while (ifs.good()) {
if (isspace(c)){
c = ifs.get();
}
if (isalpha(c)){
string temp;
while(isalpha(c)){
temp.push_back(c);
c = ifs.get();
}
String = temp;
return 2;
}
if(isdigit(c)){
string temp;
while(isdigit(c)){
temp.push_back(c);
c = ifs.get();
}
String=temp;
return 1;
}
if(c=='('){
c = ifs.get();
return 12;
}
c = ifs.get();
}//endwhile
ifs.close();
return 0;
}
I have posted summary of my code to be easy to read which contains the loop for alphabets digits spaces (just ignores the spaces) and "(".

I do want to solve this problem but I wanted to know if there is any
way to fix it without changing the main function. I mean by modifying
just the SCAN function.
bool isOpened = false;
ifstream ifs;
int SCAN(string& String){
int Code;
if (!isOpened) {
ifs.open ("test.txt", ifstream::in);
isOpened = true;
}
...
ifs.close();
isOpened = false;
return 0;
}

Related

Reading in Floats from Text File and Counting the Columns [duplicate]

How can i read data untill end of line?I have a text file "file.txt" with this
1 5 9 2 59 4 6
2 1 2
3 2 30 1 55
I have this code:
ifstream file("file.txt",ios::in);
while(!file.eof())
{
....//my functions(1)
while(?????)//Here i want to write :while (!end of file)
{
...//my functions(2)
}
}
in my functions(2) i use the data from the lines and it need to be Int ,not char
Don't use while(!file.eof()) as eof() will only be set after reading the end of the file. It does not indicate, that the next read will be the end of the file. You can use while(getline(...)) instead and combine with istringstream to read numbers.
#include <fstream>
#include <sstream>
using namespace std;
// ... ...
ifstream file("file.txt",ios::in);
if (file.good())
{
string str;
while(getline(file, str))
{
istringstream ss(str);
int num;
while(ss >> num)
{
// ... you now get a number ...
}
}
}
You need to read Why is iostream::eof inside a loop condition considered wrong?.
As for reading until the end of the line. there's std::getline.
You have another problem though, and that is that you loop while (!file.eof()) which will most likely not work as you expect. The reason is that the eofbit flag is not set until after you try to read from beyond the end of the file. Instead you should do e.g. while (std::getline(...)).
char eoln(fstream &stream) // C++ code Return End of Line
{
if (stream.eof()) return 1; // True end of file
long curpos; char ch;
curpos = stream.tellp(); // Get current position
stream.get(ch); // Get next char
stream.clear(); // Fix bug in VC 6.0
stream.seekp(curpos); // Return to prev position
if ((int)ch != 10) // if (ch) eq 10
return 0; // False not end of row (line)
else // (if have spaces?)
stream.get(ch); // Go to next row
return 1; // True end of row (line)
} // End function
If you want to write it as function in order to call some where, you can use a vector. This is a function which I use to read such file and return integers element wise.
vector<unsigned long long> Hash_file_read(){
int frames_sec = 25;
vector<unsigned long long> numbers;
ifstream my_file("E:\\Sanduni_projects\\testing\\Hash_file.txt", std::ifstream::binary);
if (my_file) {
//ifstream file;
string line;
for (int i = 0; i < frames_sec; i++){
getline(my_file, line);
numbers.push_back(stoull(line));
}
}
else{
cout << "File can not be opened" << endl;
}
return numbers;
}

how to read line by line string in a text file?

this code will only read and calculate the first input in the input.txt file and ignore the rest of the inputs in the input file.I have been trying to solve it so that it can read all the rest of the inputs and calculate them.
this is my code i think there is something wrong with it.
i have tried several looping methods
int main()
{
string inputLine;
ifstream file ("input.txt");// input file to be read
ofstream file1;
file1.open("output.txt");
freopen("output.txt", "w", stdout);// store all the output to this file
while (std::getline (file, inputLine)) // read the strings in the input file
{
if( strncmp( "----", inputLine.c_str(), 4 ) == 0 )
continue;
//calculating binary and hexadecimal values
char *opr = "^+-/%*=,()";
std::string::iterator end_pos = std::remove(inputLine.begin(),
inputLine.end(), ' ');
inputLine.erase(end_pos, inputLine.end());
string str=inputLine;
string str2="";
int length=str.length();
char t[length];
str.copy(t, length);
t[length] = '\0';
char* tok;
char *cop=new char [length];
str.copy(cop,length);
char *w = strtok_fixed( t, opr );
while (w!=NULL)
{
string w2=w;
std::stringstream tr;
tr << w2;
w2.clear();
tr >> w2;
int x=w2.length();
int y=x-3;
string check= w2.substr(0,3);
string check1=w2.substr(0,x);
if(check.find("0x") != std::string::npos)
{
unsigned int x= strtol(w2.c_str(), NULL, 0);
std::ostringstream s;
s << x;
const std::string ii(s.str());
str2=str2+ ii;
}
else if (check1.find("b")!=std::string::npos)
{
w2.pop_back();
long bin=std::strtol(w2.c_str(),0,2);
std::ostringstream s2;
s2<<bin;
const std::string t2(s2.str());
//inputLine.replace(inputLine.find(w2),(w2.length()+1),t2);
str2=str2+t2;
}
else
{
str2=str2+w2;
}
char a =cop[w-t+strlen(w)];
string s1="";
s1=s1+a;
std::stringstream tr1;
tr1 << s1;
s1.clear();
tr1 >> s1;
str2=str2+s1;
w = strtok_fixed (NULL, opr);
}
//str2 should be taken to the parser for final evaluations
Parser p(str2);
double value = p.Evaluate ();
std::cout<<"----------------------"<<endl;
std::cout << "Result = " << value << std::endl;
std::cout<<"----------------------"<<endl;
return 0;
}
}
The problem is at the end
return 0;
}
}
should be
}
return 0;
}
You are returning from inside your while loop instead of after your while loop finishes.
You should spend the time to indent your code correctly. It will help you spot this kind of error. You should also learn to break up your code into smaller functions. Again this will help you understand your own code a bit better.

How to search for words in a string in a text file?

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

Read from file in c++ till end of line?

How can i read data untill end of line?I have a text file "file.txt" with this
1 5 9 2 59 4 6
2 1 2
3 2 30 1 55
I have this code:
ifstream file("file.txt",ios::in);
while(!file.eof())
{
....//my functions(1)
while(?????)//Here i want to write :while (!end of file)
{
...//my functions(2)
}
}
in my functions(2) i use the data from the lines and it need to be Int ,not char
Don't use while(!file.eof()) as eof() will only be set after reading the end of the file. It does not indicate, that the next read will be the end of the file. You can use while(getline(...)) instead and combine with istringstream to read numbers.
#include <fstream>
#include <sstream>
using namespace std;
// ... ...
ifstream file("file.txt",ios::in);
if (file.good())
{
string str;
while(getline(file, str))
{
istringstream ss(str);
int num;
while(ss >> num)
{
// ... you now get a number ...
}
}
}
You need to read Why is iostream::eof inside a loop condition considered wrong?.
As for reading until the end of the line. there's std::getline.
You have another problem though, and that is that you loop while (!file.eof()) which will most likely not work as you expect. The reason is that the eofbit flag is not set until after you try to read from beyond the end of the file. Instead you should do e.g. while (std::getline(...)).
char eoln(fstream &stream) // C++ code Return End of Line
{
if (stream.eof()) return 1; // True end of file
long curpos; char ch;
curpos = stream.tellp(); // Get current position
stream.get(ch); // Get next char
stream.clear(); // Fix bug in VC 6.0
stream.seekp(curpos); // Return to prev position
if ((int)ch != 10) // if (ch) eq 10
return 0; // False not end of row (line)
else // (if have spaces?)
stream.get(ch); // Go to next row
return 1; // True end of row (line)
} // End function
If you want to write it as function in order to call some where, you can use a vector. This is a function which I use to read such file and return integers element wise.
vector<unsigned long long> Hash_file_read(){
int frames_sec = 25;
vector<unsigned long long> numbers;
ifstream my_file("E:\\Sanduni_projects\\testing\\Hash_file.txt", std::ifstream::binary);
if (my_file) {
//ifstream file;
string line;
for (int i = 0; i < frames_sec; i++){
getline(my_file, line);
numbers.push_back(stoull(line));
}
}
else{
cout << "File can not be opened" << endl;
}
return numbers;
}

How to get the last but not empty line in a txt file

I want to get the last but not empty line in a txt file.
This is my code:
string line1, line2;
ifstream myfile(argv[1]);
if(myfile.is_open())
{
while( !myfile.eof() )
{
getline(myfile, line1);
if( line1 != "" || line1 != "\t" || line1 != "\n" || !line1.empty() )
line2 = line1;
}
myfile.close();
}
else
cout << "Unable to open file";
The problem is I cannot check the empty line.
Okay, let's start with the obvious part. This: while( !myfile.eof() ) is essentially always wrong, so you're not going to detect the end of the file correctly. Since you're using getline to read the data, you want to check its return value:
while (getline(myfile, line1)) // ...
Likewise, the logic here:
if( line1 != "" || line1 != "\t" || line1 != "\n" || !line1.empty() )
line2 = line1;
...is clearly wrong. I'm guessing you really want && instead of || for this. As it stands, the result is always true, because no matter what value line1 contains, it must be unequal to at least one of those values (i.e., it can't simultaneously contain only a tab and contain only a new-line and contain nothing at all -- but that would be necessary for the result to be false). Testing for both !line1.empty() and line1 != "" appears redundant as well.
Why not read the file backwards? That way you don't have to scan the entire file to accomplish this. Seems like it ought to be possible.
int main(int argc, char **argv)
{
std::cout<<"Opening "<<fn<<std::endl;
std::fstream fin(fn.c_str(), std::ios_base::in);
//go to end
fin.seekg(0, std::ios_base::end);
int currpos = fin.tellg();
//go to 1 before end of file
if(currpos > 0)
{
//collect the chars here...
std::vector<char> chars;
fin.seekg(currpos - 1);
currpos = fin.tellg();
while(currpos > 0)
{
char c = fin.get();
if(!fin.good())
{
break;
}
chars.push_back(c);
currpos -= 1;
fin.seekg(currpos);
}
//do whatever u want with chars...
//this is the reversed order
for(std::vector<char>::size_type i = 0; i < chars.size(); ++i)
{
std::cout<<chars[i];
}
//this is the forward order...
for(std::vector<char>::size_type i = chars.size(); i != 0; --i)
{
std::cout<<chars[i-1];
}
}
return 0;
}
It wouldn't be enough to change your ||'s to &&'s to check if the line is empty. What if there are seven spaces, a tab character, another 3 spaces and finally a newline? You can't list all the ways of getting only whitespace in a line. Instead, check every character in the line to see if it is whitespace.
In this code, is_empty will be false if any non-space character is found in the line.
bool is_empty = true;
for (int i = 0; i < line.size(); i++) {
char ch = line[i];
is_empty = is_empty && isspace(ch);
}
Full solution:
#include <iostream>
#include <fstream>
#include <cctype>
#include <string>
using namespace std;
int main(int argc, char* argv[]) {
string line;
string last_line;
ifstream myfile(argv[1]);
if(myfile.is_open())
{
while( getline(myfile, line) ) {
bool is_empty = true;
for (int i = 0; i < line.size(); i++) {
char ch = line[i];
is_empty = is_empty && isspace(ch);
}
if (!is_empty) {
last_line = line;
}
}
myfile.close();
cout << "Last line: " << last_line << endl;
}
else {
cout << "Unable to open file";
}
return 0;
}
Additional to what the others said:
You can avoid reading whitespace by doing myfile >> std::ws before you call std::getline(). This will consume all leading whitespaces.
Then your condition reduces to !line1.empty(). This would also work when the line contains nothing but several whitespaces, for which your version fails.
I wasn't able to google an appropriate get_last_line function for my needs and here's what i came up with. You can even read multiple non-empty last lines by recalling the instream get_last_line func without resetting the seeker. It supports a 1 char only file. I added the reset parameter, which can be set to ios_base::end to allow output operations after reading the last line(s)
std::string& get_last_line(
std::istream& in_stream,
std::string& output = std::string(),
std::ios_base::seekdir reset = std::ios_base::cur)
{
output.clear();
std::streambuf& buf = *in_stream.rdbuf();
bool text_found = false;
while(buf.pubseekoff(-1, std::ios_base::cur) >= 0)
{
char c = buf.sgetc();
if(!isspace(c))
text_found = true;
if(text_found)
{
if(c == '\n' || c == -1)
break;
output.insert(0, sizeof c, c);
}
}
buf.pubseekoff(0, reset);
return output;
}
std::string& get_last_line(
const std::string& file_name,
std::string& output = std::string())
{
std::ifstream file_in(
file_name.c_str(),
std::ios_base::in | std::ios_base::ate);
if(!file_in.is_open())
{
output.clear();
return output;
}
get_last_line(file_in, output);
file_in.close();
return output;
}