• Welcome to Valhalla Legends Archive.
 

Question Refering to Databases

Started by AC_Drkan, June 08, 2004, 03:16 PM

Previous topic - Next topic

AC_Drkan

I was wondering,
How in the world do you read a file for something like "username = "
then assign the variable following that to something?

ex:


username = blah

szUsername="blah"
"The Arguments of Today Result in the Wars of Tomorrow" - Quote By Muah.
<@Logan> I spent a minute looking at my own code by accident.
<@Logan> I was thinking "What the hell is this guy doing?"

<kow`> "There are 10 types of people in the world... those who understand binary and those who don't."
<SpaceRain> That's only 2 types of people, kow.
<SpaceRain> STUPID


<[TN]FBMachine> i got kicked out of barnes and noble once for moving all the bibles into the fiction section

God i love Bash.org.

Moonshine

Read the file into a buffer, then parse the data accordingly.  These functions will help you:
strchr(), strrchr(), strtok(), strstr(), strcmp(), stricmp()

Note that stricmp is windows specific, it's strcasecmp() on *nix.

Mephisto

#2
If it's just a username, and there will be no spaces, and you aren't concerned about buffer overflows (though for the most part, it's your fault if it occurs if you are directly handling the file/program yourself):

#include <stdlib.h>
int main(void) {
   FILE *fp = fopen("database.txt", "r");
   char username[512] = '\0';
   fscanf(fp, "Username = %s", username);
   printf("The username is %s", username); // should print whatever was following Username =
   return (0);
}


Note: fscanf is vulnerable to buffer overflows if used improperly, so keep this in mind.  Additionally, fscanf will discontinue reading after the line has ended or has encountered a whitespace.  If you wish to solve these problems, you'll need to invoke other methods using some of the provided functions in the stdio.h and fstream libraries, or even windows.h.  Moonshine has provided some of these.  Additionally, when your database contains more than one user, such as 50, and each user has one line (50 lines) you'll often find you'll need to have some sort of loop structure to iterate through the file until you reach EOF (end of file).  So something such as while (fgets(buffer, sizeof(buffer), fp) != EOF) { ... }.

Zeller

He might not be using vc++. This should cover what you need to know.

http://www.cplusplus.com/doc/tutorial/tut6-1.html

Moonshine

#4
Quote from: Zeller on June 08, 2004, 06:43 PM
He might not be using vc++. This should cover what you need to know.

http://www.cplusplus.com/doc/tutorial/tut6-1.html

Neither what Mephisto or I wrote was VC++ specific.

Mephisto

Quote from: Zeller on June 08, 2004, 06:43 PM
He might not be using vc++. This should cover what you need to know.

http://www.cplusplus.com/doc/tutorial/tut6-1.html

Visual C++ is nothing but C++ with some Microsoft extensions.  It's all backwards compatable, so ANSI-C++ and Microsoft standards will compile in VC++.  I don't believe anything in C/C++ FILE I/O has any Microsoft extensions in Visual C++.  Even the FILE I/O functions and handles in the Win32 API (or windows.h rather) don't fit in the extensions of Visual C++...

Zeller

yea, your right. I just quickly assumed it was vc++ when I saw fopen for some reason. dont know why though  :-[

UserLoser.

#7
Quote from: Mephisto on June 08, 2004, 05:34 PM
If it's just a username, and there will be no spaces, and you aren't concerned about buffer overflows (though for the most part, it's your fault if it occurs if you are directly handling the file/program yourself):

#include <stdlib.h>
int main(void) {
   FILE *fp = fopen("database.txt", "r");
   char username[512] = '\0';
   fscanf(fp, "Username = %s", username);
   printf("The username is %s", username); // should print whatever was following Username =
   return (0);
}


Note: fscanf is vulnerable to buffer overflows if used improperly, so keep this in mind.  Additionally, fscanf() will discontinue reading after the line has ended or has encountered a whitespace.  If you wish to solve these problems, you'll need to invoke other methods using some of the provided functions in the stdio.h and fstream libraries, or even windows.h.  Moonshine has provided some of these.  Additionally, when your database contains more than one user, such as 50, and each user has one line (50 lines) you'll often find you'll need to have some sort of loop structure to iterate through the file until you reach EOF (end of file).  So something such as while (fgets(buffer, sizeof(buffer), fp) != EOF) { ... }.

I'm no expert, yet, but you should also check if the file was opened without any errors, and close it after you're done with it

Maddox

He was just giving an example. ::) It should also be %511s as well.
asdf.

Skywing

Remember that you won't be able to have spaces in the strings scanned in.  This can lead to unexpected results in some cases if you aren't aware of it.

Mephisto

#10
Quote from: Skywing on June 09, 2004, 01:04 AM
Remember that you won't be able to have spaces in the strings scanned in.  This can lead to unexpected results in some cases if you aren't aware of it.
I already noted that scanning in variables (even though I specifically addressed fscanf) would be disastrous at runtime if you were expecting it to scan in the whitespace, which it will not).

Quote from: UserLoser. on June 08, 2004, 11:29 PM
I'm no expert, yet, but you should also check if the file was opened without any errors, and close it after you're done with it
Checking to see if a file was successfully opened to me is pointless.  I've never once with FILE I/O usage had a failure in opening the file successfully.  Granted though, you have a point because you're reading from the file, the file may not even exist, and there would be nothing to read into a buffer if you made it, so go figure...It's not really as necessary when writing to the file because it will automatically make the file and open it for you if it doesn't exist.  Additionally, if you're not using the file pointer for anything else (even if you were it's not necessarily necessary) calling fclose isn't really necessary, especially in such a small example because the ending of the program takes care of everything.

Quote from: Maddox on June 09, 2004, 12:31 AM
He was just giving an example. ::) It should also be %511s as well.
%s is fine, as long as you're careful about your buffers you should be fine without specifying a scan length into the buffer.  I've never had problems.  Though if you find it necessary to make sure your buffers are not going to overflow, you can use %511s; or whatever number you wish your buffer to hold (what it's specified to).

Adron

#11
Quote from: Mephisto on June 09, 2004, 02:17 AM
I already noted that scanning in variables (even though I specifically addressed fscanf) would be disastrous at runtime if you were expecting it to scan in the whitespace, which it will not).

I'd like to point out that for those of us who know the language and how to use the functions, fscanf will scan in whitespace just fine if we want it to.



Quote from: Mephisto on June 09, 2004, 02:17 AM
Checking to see if a file was successfully opened to me is pointless.  I've never once with FILE I/O usage had a failure in opening the file successfully.

This shows that you are a very inexperienced programmer. I can't count the number of failures to open files I've had. And most have been properly handled, which is critical to do.


Quote from: Mephisto on June 09, 2004, 02:17 AM
Granted though, you have a point because you're reading from the file, the file may not even exist, and there would be nothing to read into a buffer if you made it, so go figure...It's not really as necessary when writing to the file because it will automatically make the file and open it for you if it doesn't exist.  

It's necessary when opening a file for writing as well. There are many reasons that an open for writing could fail.

Quote from: Mephisto on June 09, 2004, 02:17 AM
Additionally, if you're not using the file pointer for anything else (even if you were it's not necessarily necessary) calling fclose isn't really necessary, especially in such a small example because the ending of the program takes care of everything.

Whether you're using the file pointer for something else or not doesn't seem relevant to the calling of fclose. You can reuse a variable without closing the file. And you don't reuse the actual storage area, since that's allocated for you by fopen.

Yes, in a small program, you can skip it, but it's a good habit always to close what you open. If you make instead make it a habit not to close files, you'll end up debugging weird errors in large programs.

Mephisto

#12
Thanks.  Anyways, Adron, how do you scan in the whitespace, because I've been curious to know if you could...

And just for the record, I do check to see if the file was successfully opened and I do close it in programs I make that are useful.  As you've noted it's not really necessary in a small example program.  But I haven't experienced a file opening error before...So I find it hard to relate to getting file opening errors a lot.

And I apologize for presenting my "inexperience" to the forums...

Adron

Quote from: Mephisto on June 09, 2004, 02:18 PM
Thanks.  Anyways, Adron, how do you scan in the whitespace, because I've been curious to know if you could...

You use the %[] format specifier, putting the acceptable character specification between the brackets. To read a line consisting of three columns, separated by = and a tab:


char line[] = "column number 1\tcolumn number 2=last column\n";
char val1[101], val2[101], val3[101];
if(sscanf(line, "%100[^\t]\t%100[^=]=%100[^\n]\n", val1, val2, val3) == 3)
 printf("Value 1: %s\nValue 2: %s\nValue 3: %s\n", val1, val2, val3);
else
 printf("Error!\n");


I would suggest that you read lines from the file using fgets, and then process them with sscanf instead of reading with fscanf, if there's a risk of errors in the file. It's much easier to handle bad lines that way. Any line that doesn't pass the scanf can be simply ignored, without you having to manually skip forward to the next linefeed.


Quote from: Mephisto on June 09, 2004, 02:18 PM
And just for the record, I do check to see if the file was successfully opened and I do close it in programs I make that are useful.  As you've noted it's not really necessary in a small example program.  But I haven't experienced a file opening error before...So I find it hard to relate to getting file opening errors a lot.

I get it often enough. Things that can go wrong include being in the wrong current directory, misspelling the file name, missing a double \ in a path, files on a network drive that isn't there, someone removing the file, read-only files (happens when you copy your program + files from a cd-rom), sharing violations, ntfs acls or file modes limiting access, ....


Quote from: Mephisto on June 09, 2004, 02:18 PM
And I apologize for presenting my "inexperience" to the forums...

I don't mind that you post examples without error handling, leaving that out is normal to make the code clearer. Saying that error handling is "pointless" is wrong though.

In an application you're giving out to people, or using yourself more than very briefly, you should always add error handling for errors that can be expected. A file failing to open should be an expected error - it will happen sooner or later in a changing environment.