I am using C programming language and am trying to read the first string of every line in a binary File .
Example of data in the binary file (I have written to a txt file in order to show you)
Iliya Iliya Vaitzman 16.00 israel 1 0 1
I want to read to first Iliya in the line (or what ever the first word in the line will be).
I am trying the following code but it keeps returning NULL to the string variable I gave him
The following code:
FILE* ptrMyFile;
char usernameRecieved[31];
boolean isExist = FALSE;
ptrMyFile = fopen(USERS_CRED_FILENAME, "a+b");
if (ptrMyFile)
{
while (!feof(ptrMyFile) && !isExist)
{
fread(usernameRecieved, 1, 1, ptrMyFile);
if (!strcmp(userName, usernameRecieved))
{
isExist = TRUE;
}
}
}
else
{
printf("An error has encountered, Please try again\n");
}
return isExist;
I used typedef and #define to a boolean variable (0 is false, everything else is true (TRUE is true, FALSE is false))
usernameRecieved keeps getting NULL from the fread .
What should I do in order to solve this?
Instead of this:
fread(usernameRecieved, 1, 1, ptrMyFile);
try this:
memset(usernameRecieved, 0, sizeof(usernameRecieved));
fread(usernameRecieved, sizeof(usernameRecieved)-1, 1, ptrMyFile);
As it is, you are reading at most only one byte from the file.
Documentation on fread
A couple things: you're setting the count field in fread to 1, so you'll only ever read 1 byte, at most (assuming you don't hit an EOF or other terminal marker).
It's likely that what you want is:
fread(usernameRecieved, 1, 31, ptrMyFile);
That way you'll copy into your whole char buffer. You'll then want to compare only up to whatever delimiter you're using (space, period, etc).
It's not clear what "usernameRecieved keeps getting NULL" means; usernameRecieved is on the stack (you aren't using malloc). Do you mean that nothing is being read? I highly suggest that you always check the return value from fread to see how much is read; this is helpful in debugging.
Related
I want to manipulate the output of lex. There is only one write to yyout, in the ECHO macro. The macro is surrounded by "#ifndef ECHO", so I am replacing it with my desired action.
However, I want to be sure to correctly replicate the original lex behavior. Lex defines ECHO to this code fragment:
do {
if (fwrite( yytext, yyleng, 1, yyout )) {
}
} while (0)
Can anyone guess why the output is not simply "fwrite(...)"?
do { .. } while (0)
is a convenient way to #define a multi-statement operation as pointed out by this.
By
if (fwrite( yytext, yyleng, 1, yyout ))
I believe you're given an option to deal with fwrite failure.
Here you call fwrite with just 1 element of size yyleng. Considering that fwrite returns the total number of elements written, the possible return values are just 0 and 1 - 0 indicating any failure and 1 indicating success.
Ideally(or actually it is?), it should have been
if (!fwrite( yytext, yyleng, 1, yyout ))
I'm guessing this because, only block is given to write the fallback/logging code.
I'm trying to open this file (final.txt) and read the contents:
c0001
f260
L
D11
H30
R0000
C0040
1X1100000100010B300300003003
181100202900027Part No
181100202900097[PRTNUM]
1e5504002400030B
1X1100002300010L300003
191100202000030Quantity
191100202000080[QUANTY]
1e5504001500040B
1X1100001400010L300003
1X1100001400150L003090
191100202000170P.O.No
191100202000220[PONUMB]
1e5504001500180B
191100201200030Supplier
1e3304000700030B
1X1100000600010L300003
181100200300030Serial
181100200300090[SERIAL]
171100300900190Rev
171100300300190[REV]
171100300900240Units
171100300300240[UNITS]
1X1100000100180L003130
Q0001
E
from which I am reading only [PRTNUM], [QUANTY], [PONUMB], [SERIAL], [UNITS].
I've written the following C program:
char* cStart = strchr(cString, '[');
if (cStart)
{
// open bracket found
*cStart++ = '\0'; // split the string at [
char* cEnd = strchr(cStart, ']');
// you could check here for the close bracket being found
// and throw an exception if not
*cEnd = '\0'; // terminate the keyword
printf("Key: %s, Value: %s",cString, cStart);
}
// continue the loop
but now I want to replace these placeholders with data from the 2nd file:
132424235
004342
L1000
DZ12
234235
234235
I want to replace [PRTNUM] (from the 1st file) with 132424235 and so on... In the end my file should be updated with all this data. Can you tell me what function I should use in the above program?
If you don't mind having an alternate approach, here's an algorithm to do the work in an elegant way
Create one (large enough) temporary buffer. Also, create (open) one output file which will be the modified version.
Read a line from the input file into the buffer using fgets()
Search for the particular "keyword" using strstr()
If a match is found --
4.1. Open the other input file.
4.2. Read the corresponding data (line), using fgets()
4.3. Replace the actual data in the temporary buffer with the newly read value.
4.4. write the modified data to the output file.
If match is not found, write the original data in the output file. Then, go to step 2.
Continue until fgets() returns NULL (indicates the file content has been exhausted).
Finally, the output file will have the data from the first file with those particular "placeholders" substituted with the value read from the second file.
Obviously, you need to polish the algorithm a little bit to make it work with multiple "placeholder" string.
Keep an extra string(name it copy) large enough to hold file 1 + some extra to manage replacement of [PRTNUM] with 132424235.
Start reading first string that has file1 and keep copying into second string (copy) as soon as you encounter [PRTNUM] , in string 2 instead of copying [PRTNUM] you append it with 132424235 and so on for all others.
And finally replace file1.txt with this second (copy) string.
I am using an fscanf to read a sequence of 8 values of zero or one at the end of the line, but it looks like the array is never having a value read to it.
It is reading this from the text file:
Chilli Con Carne,Chilli_Con_Carne.txt, 15, 25, 100,0,0,0,0,0,0,0,0
Spaghetti Bolognese,Spaghetti_Bolognese.txt, 30, 75, 150, 0, 0, 0, 0, 0, 0, 1, 0
Frittata,Frittata.txt, 10, 15, 160, 1, 1, 0, 0, 0, 0, 0, 0
Korean Beef,Korean_Beef.txt, 20, 30, 100, 0, 0, 0, 0, 0, 1, 0, 1
Trawlers Pie, Trawlers_Pie.txt, 20, 30, 100,1,1,0,1,0,0,0,0
This is the loop I am using which contains the fscanf that is not reading the recipeAllergies:
while (!feof (cookBook)){
fscanf(cookBook, "%20[^,], %20[^,], %d, %d, %d", recipeName, recipeFileName, &prepTime, &cookTime, &calories);
printf("%s ", recipeName);
for (i = 0; i < 8; i++){
fscanf(cookBook, "%d,", &recipeAllergies[i]);
printf("%d %d\n", recipeAllergies[i], userAllergies[i]);
if ((userAllergies[i] + recipeAllergies[i]) == 2){
notSuitable = 1;
}
}
fgets(ignore_line, sizeof(ignore_line), cookBook);
if (notSuitable == 0){
(suitableRecipes[totalSuitable]. recipeName, recipeFileName, prepTime, cookTime, calories);
totalSuitable++;
}
}
Any help is greatly appreciated.
The inner loop has a format string "%d," so fscanf() is looking for integers followed by a comma. There is no comma on the end of the input lines, so scanf() will return indicating an error.
Either add commas at the end of the input lines, or change the loop so it doesn't look for a comma the 8th time. The latter is preferable.
Although you didn't ask, a few other concerns you might want to address with your code......
Looping on feof() is a really bad idea, because (among other problems) if no error is detected in the loop body, it will attempt to read one more
line of input from your file than exists.
Always check the return value of functions like fscanf() and fprintf(), since they can fail.
Mixing fgets() with fscanf() on the same file is a bad idea, because
they respond to file contents differently (e.g. in how they respond
to a newline) and using them in combination can result in spurious
loss of data. [More generally, the same goes for mixing styles of
input. Don't mix manners of input for the same file.
Mixing character oriented input (e.g. fgetc()), line oriented input
(e.g. fgets()), and/or formatted input (e.g. fscanf()) can all cause spurious problems if they are used on the same stream.]
The first statement in the if (notSuitable == 0) block doesn't do
anything. I assume you left out the name of the function to be
called.
First, process comma after calorie while using fgetc. After that, read each number.
You are also expecting comma from last digit where as this might not be the case.
Alternatively, you can discard each comma separately by using fgetc.
You can try following code snippets in your for loop.
for (i = 0; i < 8; i++){
fgetc(cookBook); //To discard/read comma
fscanf(cookBook, "%d", &recipeAllergies[i]);
printf("%d %d\n", recipeAllergies[i], userAllergies[i]);
if ((userAllergies[i] + recipeAllergies[i]) == 2){
notSuitable = 1;
}
}
Also see the link mentioned in question's comment. Why is “while ( !feof (file) )” always wrong?
I'm learning to use libcurl in C. To start, I'm using a randomized list of accession names to search for protein sequence files that may be found hosted here. These follow a set format where the first line is a variable length (but which contains no information I'm trying to query) then a series of capitalized letters with a new line every sixty (60) characters (what I want to pull down, but reformat to eighty (80) characters per line).
I have the call itself in a single function:
//finds and saves the fastas for each protein (assuming on exists)
void pullFasta (proteinEntry *entry, char matchType, FILE *outFile) {
//Local variables
URL_FILE *handle;
char buffer[2] = "", url[32] = "http://www.uniprot.org/uniprot/", sequence[2] = "";
//Build full URL
/*printf ("u:%s\nt:%s\n", url, entry->title); /*This line was used for debugging.*/
strcat (url, entry->title);
strcat (url, ".fasta");
//Open URL
/*printf ("u:%s\n", url); /*This line was used for debugging.*/
handle = url_fopen (url, "r");
//If there is data there
if (handle != NULL) {
//Skip the first line as it's got useless info
do {
url_fread(buffer, 1, 1, handle);
} while (buffer[0] != '\n');
//Grab the fasta data, skipping newline characters
while (!url_feof (handle)) {
url_fread(buffer, 1, 1, handle);
if (buffer[0] != '\n') {
strcat (sequence, buffer);
}
}
//Print it
printFastaEntry (entry->title, sequence, matchType, outFile);
}
url_fclose (handle);
return;
}
With proteinEntry being defined as:
//Entry for fasta formatable data
typedef struct proteinEntry {
char title[7];
struct proteinEntry *next;
} proteinEntry;
And the url_fopen, url_fclose, url_feof, url_read, and URL_FILE code found here, they mimic the file functions for which they are named.
As you can see I've been doing some debugging with the URL generator (uniprot URLs follow the same format for different proteins), I got it working properly and can pull down the data from the site and save it to file in the proper format that I want. I set the read buffer to 1 because I wanted to get a program that was very simplistic but functional (if inelegant) before I start playing with things, so I would have a base to return to as I learned.
I've tested the url_<function> calls and they are giving no errors. So I added incremental printf calls after each line to identify exactly where the bus error is occurring and it is happening at return;.
My understanding of bus errors is that it's a memory access issue wherein I'm trying to get at memory that my program doesn't have control over. My confusion comes from the fact that this is happening at the return of a void function. There's nothing being read, written, or passed to trigger the memory error (as far as I understand it, at least).
Can anyone point me in the right direction to fix my mistake please?
EDIT: As #BLUEPIXY pointed out I had a potential url_fclose (NULL). As #deltheil pointed out I had sequence as a static array. This also made me notice I'm repeating my bad memory allocation for url, so I updated it and it now works. Thanks for your help!
If we look at e.g http://www.uniprot.org/uniprot/Q6GZX1.fasta and skip the first line (as you do) we have:
MNAKYDTDQGVGRMLFLGTIGLAVVVGGLMAYGYYYDGKTPSSGTSFHTASPSFSSRYRY
Which is a 60 characters string.
When you try to read this sequence with:
//Grab the fasta data, skipping newline characters
while (!url_feof (handle)) {
url_fread(buffer, 1, 1, handle);
if (buffer[0] != '\n') {
strcat (sequence, buffer);
}
}
The problem is sequence is not expandable and not large enough (it is a fixed length array of size 2).
So make sure to choose a large enough size to hold any sequence, or implement the ability to expand it on-the-fly.
hi guys i have this function to tell me how many records are in a data file.
however whenever i run it it only reads the even records
ex: if i have 0 records it outputs 0
with 1 record it outputs 0
with 2 records it ouputs 1
with 3 it outputs 1
with 4 it outputs 2
(btw its for a customer and products database project
customer is a struct and filep is the pointer to the file customerfile which is defines above this code)
im running on eclipse and can only use the gnu89/90 dialect if that makes a diff
int CusFileNumber(void)
{
customer tempcus;
filep = fopen(customersFile, "r");
fseek (filep,0,SEEK_SET);
int counter =0;
while(!feof(filep))
{
fread(&tempcus,sizeof(customer),1,filep);
printf ("%d",counter);
counter ++;
}
fclose(filep);
return (counter-1);
}
so i updated the code to get rid of the feof
it looks like this
int CusFileNumber(void)
{
customer tempcus;
filep = fopen(customersFile, "r");
fseek (filep,0,SEEK_SET);
int counter =0;
while(fread(&tempcus, sizeof(customer), 1, filep) == 1)
{
printf ("%d",counter);
counter ++;
}
fclose(filep);
return (counter);
}
but im still getting the same problem this time it isnt counting the even numbers
meaning that on every odd number counter increments by 1 but stayed the same when i have an even number of records in the file
(its a .dat file btw)
You can't use feof(3) like that. It only tells you if the stream has already ended, not that it's about to. You need to put the fread call into your loop condition and check its return value:
while (fread(&tempcus, sizeof(customer), 1, filep) == 1)
Get rid of the feof call entirely.
Are you sure sizeof(customer) matches what's really in the file?
Why are you printing counter before you increment it?
Why are you returning counter - 1 instead of counter?