• Welcome to Overclockers Forums! Join us to reply in threads, receive reduced ads, and to customize your site experience!

Code problem

Overclockers is supported by our readers. When you click a link to make a purchase, we may earn a commission. Learn More.

JigPu

Inactive Pokémon Moderator
Joined
Jun 20, 2001
Location
Vancouver, WA
I'm trying to build into one of my programs the ability to save output to file. However, I'm having some problems making it work.

The code below is supposed to check to see if a file with the name entered exists, and then ask if the user would like to append the output (if not, the user must specify a new file). It detects if a file exists correctly, but does not loop through when the user specifies to not append.

Further checking shows that the problem (probably) lies with temp not being equal to the input key. If "n" or "N" is entered at the prompt, (temp=="n") and (temp=="N") both evaluate to FALSE. COUTing temp displays the key though, so I'm really confused... Any ideas?

Code:
	//If File IO is needed, let's do some checking....
	if ((PROGRAM.output==2) || (PROGRAM.output==3))	{
		char *temp;											//Temporary variable (used here to hold Y/N)
		ifstream fout;											//Assign a name for the stream

		do {
			cout << "Output File Name: ";								//Ask for file name
			cin >> PROGRAM.file;									//And store into PROGRAM.file
			fout.open(PROGRAM.file, ios::in);							//And try opening the file
	
			if (fout)	{											//Test for existance (and ask to append if exists)
				cout << "Warning, output file exists! Append (y/n)? ";
				cin >> temp;
			}
		} while ((fout) && ((temp=="n") || (temp=="N")));


JigPu
 
Use char temp and not char *temp; here you want a char and not a char pointer (a.k.a. string). I'm surprised you didn't get a segfault.

Also remember that characters are denoted with single and not double quotes, and thus your line would have to be:

if (temp == 'n' || temp == 'N')

A better way would be to just make it with full-fledged strings. Just remember you can't compare strings with the == operator.
 
OK, I switched the type to char and changed the while appropriatly, but now I get a weirder problem.

The code seems to run fine, except that it ignores the cin's. It will display "Output file name: " on the screen, but not wait for the user to enter the file name (which is char *). Since it dosen't try to get input, the filename dosent exist. This means the IF statement is false, not executing any of that code. Changing the IF to run if false results in the code running, except for it's cin again.


I'm going to try the string type, but I have to find out how to use it :D
JigPu
 
Try a cin.flush() before your if statement to clear any extraneous stuff left in the input stream (such as a carriage return / line feed).
 
JigPu said:

I'm going to try the string type, but I have to find out how to use it :D
JigPu

What string type? char pointers work perfectly well as strings for most uses. Just remember to allocate your mem or declare a char array before putting anything in the string.
 
Cowboy Shane said:
Try a cin.flush() before your if statement to clear any extraneous stuff left in the input stream (such as a carriage return / line feed).
Nope, compliler complains about the cin.flush(). "'flush' is not a member of 'istream'". :confused:



Damian said:
What string type? char pointers work perfectly well as strings for most uses. Just remember to allocate your mem or declare a char array before putting anything in the string.
Say what? Just above you told me to try using "full fledged strings"... I assume (probably where I'm wrong :D) that you were refering to the string data type from string.h. I normally do use charachter pointers for strings, but they're not working here (...or plain old charachters...), so I thought you meant the only other string type left.

BTW, doesen't declaring a variable such as char *BLAH do the alocation for you? I'm a total idiot at that sorta stuff, so I could believe it if I'm wrong :D
JigPu
 
I would just use the STL implementation of strings:

#include <string>
...
string temp;
...
cin >> temp;
if (temp == "n")
{your code}

You could also just do
while(cin.get(temp))
if (temp == 'n')
{exit}

Of course the exit logic would be a little trickier.
 
OK, now I'm royally confused. I decided to get back to the basics and write just a simple program JUST to detect if a file existed. Well, the code has similar bugs but not quite the same.... I think either me or my compiler is going crazy :mad: :confused:

Anybody wanna write a program JUST to test for file existance and ask the user if they want to overwrite if it does? Hopefully I can use it as a background for making my own one work right....
JigPu
 
OK, I hope this clears your confusion.

With regard to strings, I think people are talking about two different implementations of strings. First off, you have your character arrays (these are your C style strings), such as:

Code:
char fileName[256]; /* An array of 256 characters (a "string") */

If you use this style of string and want to use existing functions to compare and manipulate them, you must include the <string.h> header file. For example, the strcmp function allows you to comapre two strings:

Code:
if ( strcmp(string1, string2) == 0) // If its not 0 there not equal
  ...

You cant use == to compare character arrays because this will only compare the address of the arrays (not the contents).


However, as you are using C++ you have an additional option of STL (Standard Template Library) strings. These are a bit different as when you declare them they are objects. Because of this, you CAN use == to compare them, because of a wonder OO (Object Oriented) concept called operator overloading. Basically the designers of the STL string class have provided a definition of == for strings so that when you use this on two STL strings, it doesn't compare the adresses but actually compares the content/value.

Um... I hope that helps, anyhow, I've modified your code slightly and it worked for me, see how you go.

Code:
// Note the use of STL header files (ie. ones without .h)
#include <iostream>						// Required for cout, cin, etc.
#include <string>						// For your STL string
#include <fstream>						// For ifstream


using namespace std;

void main()
{
	const int	FILE_NOT_EXIST = 0;		// Anything other than 0 denotes an open file! See 
										// ifstream::is_open for more information

	string		fileName;				// This is an STL string (as opposed to a character array)
	char		overwrite;				// No pointer is required, just a variable to hold either Y or N
	ifstream	fout;					// As before... a file stream
	bool		exists;					// Not strictly required, but used to store if the file exists


	do 
	{
		cout << "Enter a file name: ";								
		cin >> fileName;									
		fout.open(fileName.c_str(), ios::in);		// STL strings have a method c_str() which returns a C
													// style string (a character array). We do this because 
													// ifstream::open is expecting a *char, not a STL string!

		exists = false;
		if (fout.is_open() != FILE_NOT_EXIST)		// A bit of double negative here, if the file does NOT not 
													// exist, then it must exist :-)						
		{	
			fout.close();							// Dont forget to close it else next loop it will still be 
													// open even if the new file name doesn't exist
			exists = true;
			cout << "Warning, output file exists! Append (y/n)? ";
			cin >> overwrite;						// Its not really temp if its used more than once!
		}
	} 
	while ( exists && (overwrite=='n' || overwrite=='N'));	
}

Stupid formatting :-(

Oh, I forgot to add, if you think your compiler is going crazy and you are using Visual Studio 6.0, your probably right. If you are getting really wierd compiler errors/warnings, create a new workspace/project and re-attach your source files then recompile. 9 times out of 10 problem solved... the other 1 time, is a really late night!
 
Last edited:
Thank you SMP :) I'll try compiling it as soon as I get home. Hopefully that will work, and I can find a way to integrate it into the program.

BTW, I'm using Borland's C++ 5.5 compiler
JigPu
 
Yea! Your code works, now it's off to learning the difference between the two and try to design something for the program :)

Thanks for the help all!
JigPu
 
JigPu said:

BTW, doesen't declaring a variable such as char *BLAH do the alocation for you? I'm a total idiot at that sorta stuff, so I could believe it if I'm wrong :D
JigPu

In that case, the storage for a pointer to char would be allocated. However, that pointer would not point to any valid storage. Therefore, assigning the pointer itself a value is fine, but dereferencing it will cause problems (a segmenation fault, if you're lucky). For example:

Code:
char c = 'A';
char *p; /* p does not point to anything yet, sometimes called a "dangling pointer" */

*p = c; /* not OK. This attempts to change the memory at an address you haven't allocated yet. */

p = NULL; /* This is OK, because you're only changing the pointer, not what it points to. */

p = &c; /* Now p points to c, which has been allocated. Dereferncing p is now ok. */

If you have a pointer and you'd like to allocate some space for it to point to, you'll have to use dynamic memory allocation (or do something like what I did above, but that method is quite limited). Memory is allocated dynamically via malloc() in C, or new in C++.
 
Yeah. Sorry, I was talking about char pointers as strings. My bad for the confusion.

Anyways, to allocate some memory there are several ways to do it:

the very c-ish way:

char *p;
p = malloc(sizeof(char) * 100);
free(p);

c++ syntax:

char *p;
p = new char[100];
delete[] p;

or just declaring a char array (works the easiest)

char p[100];

remember that the name of an array returns the address of the first element. Thus in this case, p is a pointer to the first character in the array and can thus be used in various string functions.


To compare strings, use strcmp(char *p1, char *p2) which returns false if the strings are not equivalent.

Hope that clears things up.
 
A little :) Pointers have allways been a thing of confusion for me, and the lack of (simple) string support in C++ boggles my mind. :D

I think I just need a big guide o' lingo to figure out definitions of cryptic words (such as derefrencing :p) and then a gigantic tutorial to teach me all the weird nuances such as the use of STL libraries (which I've seen but never understood), and why the heck I allways see stuff like std::cout in programs :rolleyes:. But that's a different thread ;)

I r the forums official C++ idiot :D
JigPu
 
One thing I wanted to add (but forgot) was that the solution I posted may not work under all circumstances. I didn't fully test the code, which is why I am saying this.

Because I used the is_open() method, it may be (im not sure) that this will fail if the file is already open. If that is the case, this code will think that the file doesn't exist, but really it does it just couldn't open it because the file is already open, or file permissions aren't set right, or it read only, or some other condition.

Try it out, if it doesn't work correctly under these conditions post back and we will try find another solution.

One thing you might want to look up is the Win32 API (assuming your targeting Windows platforms only). This will have an API function you can use to determine if a file exists, Im just not sure what that function would be called. A Google search will more than likey bring up example which you should be able to get information from.

I think I just need a big guide o' lingo to figure out definitions of cryptic words (such as derefrencing ) and then a gigantic tutorial to teach me all the weird nuances such as the use of STL libraries (which I've seen but never understood), and why the heck I allways see stuff like std::cout in programs .

Dereferencing is to do with pointers and I think the reason why pointers was initially confusing for me (and possibly others) is that the examples used by people are not easy to follow (not "good") examples of when to use pointers.

STL (in my opinion) is not easy to use and not logical.

Th reason why you see std::cout in programs is because of namespaces. I was going to try give a definition of namepspaces but decided against it. But, the reason why you see std::cout is because the coder has not set the default namespace by doing:

Code:
using namespace std;

or they are using a different namespace. To see what I mean comment out the line using namespace std in your code and try to compile. It wont compile, and you will see it complaing on the cout statements. Now append a std:: to the front of all cout statements and try recompiling. :)
 
JigPu said:
[B
I think I just need a big guide o' lingo to figure out definitions of cryptic words (such as derefrencing :p)
[/B]

Dereferencing is just an oversized word for accessing. When you dereference a pointer, you access the memory it is pointing to. This generally involves the usage of the asterisk ( * ). Here's a few examples of how one could dereference a pointer to char:
Code:
*p = 'C';
if (*p == 'n') printf ("No\n");
char tmp = *p;

dict.org includes a number of tech lingo dictionaries. Here's its definition of dereference:
dereference

To access the thing to which a pointer points,
i.e. to follow the pointer. E.g. in C, the declarations

int i;
int *p = &i;

declare i as an integer and p as a pointer to integer. p is
initialised to point at i ("&i" is the address of i - the
inverse of "*"). The expression *p dereferences p to yield i
as an lvalue, i.e. something which can appear either on the
left of an assignment or anywhere an integer expression is
valid. Thus

*p = 17;

would set i to 17. *p++ is not the same as i++ however since
it is parsed as *(p++), i.e. increment p (which would be an
invalid thing to do if it was pointing to a single int, as in
this example) then dereference p's old value.

The C operator "->" also dereferences its left hand argument
which is assumed to point to a structure or union of which
the right hand argument is a member.

At first sight the word "dereference" might be thought to mean
"to cause to stop referring" but its meaning is well
established in jargon.
 
Back