Jump to content
  • Advertisement
Sign in to follow this  
GSide

I need help: reading string from text file in c++

This topic is 4831 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

My text file named “file.txt” Contained this: Computer Science I do this code: #include <stdio.h> #include <conio.h> #include <string.h> #include <fstream.h> #include <iostream.h> const char * filename = "file.txt"; int main () { char *buffer; long size; ifstream file (filename, ios::in|ios::binary|ios::ate); size = file.tellg(); file.seekg (0, ios::beg); buffer = new char [size]; file.read (buffer, size); file.close(); printf("%s",buffer); if( buffer=="Computer Science" ) { printf("OK"); } getch(); delete[] buffer; return 0; } But I have an output like this: Computer Science²²²²½½½½½½½½ε■ε■ And obviously the comparison doesn’t match. I need your help on how to display the text properly and to meet up the condition. Advance thanks!

Share this post


Link to post
Share on other sites
Advertisement
Since you sad that you use c++, use streams!


int main()
{
ifstream file("filename.txt");

string text;
file >> text;

if(text == "text")
cout << "OK\n";

return 0;
}





this will read in only one word ... but I don't know the funktion to read in a complet line ... something like
file.getline( text, 1024, "\n" );

and your comparison will never match because you are comparing pointers!

in C you would habe to use strcmp!

Share this post


Link to post
Share on other sites
If programming in C++, program in C++.

You can use the extraction operator to read whitespace delineated text (ie, it will grab the word "Computer" and return it to you). You can read in an entire line of formatted text using std::getline or std::istream::getline (I prefer the former). You can even read an entire file into a string using the constructor overload that takes two input iterators:

#include <fstream>
#include <iostream>
#include <iterator>
#include <string>

int main()
{
using namespace std;

ifstream fin("file.txt");

//*** NOTE: The following statements are ALTERNATIVES. Reading from an input stream modifies its state,
// such as the extraction point on a file or the contents of the read buffer. Choose ONE of
// these methods as appropriate on an atomic scale.

// 1. read in a single word
string word;
fin >> word;

// 2. read in an entire line
string line;
getline(fin, line);

// 3. read in the whole file
string file(istream_iterator<char>(fin), istream_iterator<char>());

...

return;
}



Using C++ strings, you can perform comparisons using the intuitive equality operator (==), as already demonstrated to you by dragongame. I really suggest finding a modern introduction to and reference for C++, as what you posted is no longer C++, in so many ways. Bruce Eckel's Thinking in C++ is available online for free and quite well recommended. Try that.

Happy hacking!

Share this post


Link to post
Share on other sites
The problem is that buffer isn't getting any '\0', it doesn't even have room for it (it will if you create it with the size "size + 1". I don't know if it will be created automatically if you have room for it, or if you will have to do it manually.

But since this is C++, I would do it something like this

#include <conio.h>
#include <string>
#include <fstream>
#include <iostream>


std::string filename = "file.txt";

int main ()
{
std::string buffer;
std::ifstream file (filename.c_str(), std::ios::in);
std::getline(file, buffer);
file.close();

std::cout << buffer;

if( buffer=="Computer Science" )
{
std::cout << "OK";
}

getch();
return 0;
}





It makes it a bit easier. In addition, it is almost only standard C++ things (conio.h (and getch() isn't).

Share this post


Link to post
Share on other sites
OK I have to modified my post like this Getting info from text file in C/C++.

Actually I’m trying to get into this kind of coding
My file Collision.txt contained this data:

FaceCount: 3
TotalVertices: 9

Face1:
V1( 1.0, 1.0, 1.0 );
V2( 1.5, 1.5, 1.5 );
V3( 2.0, 2.0, 2.0 );

Face2:
V1( 3.0, 3.0, 3.0 );
V2( 3.5, 3.5, 3.5 );
V3( 3.0, 3.0, 3.0 );

Face3:
V1( 4.0, 4.0, 4.0 );
V2( 4.5, 4.5, 4.5 );
V3( 4.0, 4.0, 4.0 );


I’m trying to read the collision.txt to get the information I want

ie:

int iFaceCount = //( Read the collision.txt FaceCount: 3 )
int iTotalVertices = //( Read the collision.txt TotalVertices: 9 )

Share this post


Link to post
Share on other sites
Ok i wrote a small program which read those 2 lines and assigns them to the ints you asked for. I wrote it in MSVC++ 6.0 so if you use something else you may need to tweek it.

NOTE: i've seen many people with code like "ifstream File("blah.txt",ios::in);" and this doesn't seem to work in MSVC++ 6.0 so i added some code to find the application's directory and search for the Collision.txt file in that directory.

THE CODE:
[source code=cpp]
#include "stdafx.h" //for MSVC++ not needed for anything else
#include <iostream> //for cout,cin
#include <fstream> //for file manipulation
#include <string> //for str.find(),strlen(),str.c_str()
#include <afx.h> //for application path funcs (requires "Using MFC in Shared DLL" in project-->settings (alt+f7) if running off MSVC++)

using namespace std;

//TO READ THE APPLICATION'S PATH FOR THE FILE OPEN
wstring get_module_path_wide(void);
string wsts(const wstring &src_string);

int main(int argc, char* argv[])
{
//Function level declarations
char chrLine[2000];
string strTemp, strPath;
int iFaceCount, iTotalVertices;

//set the path for the file to be opened from
strPath=wsts(get_module_path_wide()) + "\\Collision.txt";

//open file for input
fstream inFile(strPath.c_str(),ios::in);

//check if file was found
if(!(inFile.good()))
cout<<"File not found."<<endl;

//loop til end of file
while (!(inFile.eof()))
{
//read the line of the file
inFile.getline(chrLine,2000);
strTemp=chrLine;

//if it's the facecount line
if(strTemp.find("FaceCount:") !=std::string::npos)
//pull only the number out and convert to int
iFaceCount=atoi(strTemp.substr(strTemp.find(" ")+1,strlen(strTemp.c_str())).c_str());

//if it's the facecount line
if(strTemp.find("TotalVertices:") !=std::string::npos)
//pull only the number out and convert to int
iTotalVertices=atoi(strTemp.substr(strTemp.find(" ")+1,strlen(strTemp.c_str())).c_str());
}

//disp results
cout<<"iFaceCount="<<iFaceCount<<endl;
cout<<"iTotalVertices="<<iTotalVertices<<endl;

//pause
cin.get();

return 0;
}

//BELOW IS TO READ THE APPLICATION'S PATH FOR THE FILE OPEN

// use Unicode (wide) version of GetModuleFileName
wstring get_module_path_wide(void)
{
wchar_t wide_buf[65536];
wstring module_name;

if(!GetModuleFileNameW(GetModuleHandle(0), wide_buf, 65535))
return module_name;

wide_buf[65535] = L'\0';

module_name = wide_buf;

size_t pos = module_name.find_last_of(L'\\');

if(pos != string::npos)
module_name = module_name.substr(0, pos);

return module_name;
}

// use this function to convert from wide wstring to ASCII string if need be
string wsts(const wstring &src_string)
{
size_t src_len = src_string.length();

if(src_len == 0)
return "";

char *buf = new(std::nothrow) char[src_len + 1];

if(buf == 0)
return "";

wcstombs(buf, src_string.c_str(), src_len);
buf[src_len] = '\0';

string final_string = buf;

if(buf != 0)
delete [] buf;

return final_string;
}






Hope I helped.
-Lordoftools

Share this post


Link to post
Share on other sites
Like Oluseyi said: "If programming in C++, program in C++!

Do not use printf, fscanf, char* etc... well not by default. You can use them but only when you have considered the default alternative.

You didn't say so but I assume that your ultimate goal is to actually read in the faces and vertices, right? I inlined the code not for performance reasons, but to make it easier to post on the forum. In real life you would want to break it up into header and source files as appropriate.



struct Vertex
{
float x,y,z;
Vertex():x(0.0f),y(0.0f),z(0.0f){}
Vertex(float x_, float y_, float z_):x(x_),y(y_),z(z_){}

//here is the key part
istream& operator>>(istream& stream, Vertex& v)
{
string format;
stream>>format; //strips out the "V1(" part of the file
stream>>v.x; //reads the data straight into v.x! no casting necessary!
stream>>format; //strips out the ","
stream>>v.y;
stream>>format; //strips out the ","
stream>>v.z
stream>>format; //strips the ");"
return stream;
}
};

struct Face
{
Vertex a,b,c;
//put some constructors here too

//ok here is the key part, just like above
istream& operator>>(istream& stream, Face& f)
{
string format;
stream>>format;//strips out "Face1:"
stream>>f.a; //reads in the vertex straight to f.a!
stream>>f.b;
stream>>f.c;
return stream;
}
}

//ok now the result of all the hard work:

int main()
{
ifstream fin("Collision.txt");
vector<Face> faces;
Face f;
while(fin>>f)
faces.push_back(f);
}


unless I made mistakes, the code reads in all of the faces and vertices properly. If you want to know how many faces you have just call faces.size(), if you want to know how many vertices just multiply that number by 3.



[Edited by - Glak on August 25, 2005 7:10:07 PM]

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Very informative post glak!

But going back to the very first post, i noticed 'size' was being created, but not initialized to any value. Therefore, size could be any arbitrary value, and as such, it was reading in from the stream more characters than were there. Though you could easily fix it by simply initializing size to a number, it is much better to use streams.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!