Regarding FOPEN in C - c

I am having a problem regarding FOPEN in C.
I have this code which reads a particular file from a directory
FILE *ifp ;
char directoryname[50];
char result[100];
char *rpath = "/home/kamal/samples/pipe26/divpipe0.f00001";
char *mode = "r";
ifp = fopen("director.in",mode); %director file contains path of directory
while (fscanf(ifp, "%s", directoname) != EOF)
{
strcpy(result,directoname); /* Path of diretory /home/kamal/samples/pipe26 */
strcat(result,"/"); /* front slash for path */
strcat(result,name); /* name of the file divpipe0.f00001*/
}
Till this point my code works perfectly creating a string which looks " /home/kamal/samples/pipe26/divpipe0.f00001 ".
The problem arises when I try to use the 'result' to open a file, It gives me error. Instead if I use 'rpath' it works fine even though both strings contain same information.
if (!(fp=fopen(rpath,"rb"))) /* This one works fine */
{
printf(fopen failure2!\n");
return;
}
if (!(fp=fopen(result,"rb"))) /* This does not work */
{
printf(fopen failure2!\n");
return;
}
Could some one please tell why I am getting this error ?

I think you mean char result[100];; i.e. without the asterisk. (Ditto for directoryname.)
You're currently stack-allocating an array of 100 pointers. This will not end well.
Note that rpath and mode point to read-only memory. Really you should use const char* for those two literals.

The error is the array 'char* result[100]', here you are allocating an array of 100 pointers to strings, not 100 bytes / characters, which was your intent.

Related

Fopen function returns null when given an existing path

When trying to open a file with fopen(path, "2"); i get NULL on an existing path
iv'e tried to enter only the file name and it works but i want the program to write the file in the path...
Yes, i write the path with double backslashes "\\" when it's necesary.
Yes the path without doubt exists.
FILE* log;
char directory_path[PATH_LEN] = { 0 };
char directory_file[PATH_LEN] = { 0 };
//directory_path is the directory, entered by the user
//LOG_NAME is the files name without the path - "log.txt"
//#define PATH_LEN 100
printf("Folder to scan: ");
fgets(directory_path, PATH_LEN, stdin);
directory_path[strlen(directory_path) - 1] = 0;
//this section connects the path with the file name.
strcpy(directory_file, directory_path);
strcat(directory_file, "\\");
strcat(directory_file, LOG_NAME);
if ((log = fopen(directory_file, "w")) == NULL)
{
printf("Error");
}
My program worked until i tried to write into a file in order to create a log file. This means that the path is correct without doubt.
Can anyone tell me the problem here?
You have several issues in your code:
For one, fopen(path, "2"); is not valid.
The mode argument needs to include one of a, r, and w and can optionally include b or +.
As another thing, directory_path[strlen(directory_path) - 1] = 0; may truncate the end of your path (if it's over PATH_LEN characters long).
There also may be a possible issue with buffer overflow due to the fact that you copy a string to a buffer of the same size and then concatenate two other strings to it. Therefore, you should change this line:
char directory_file[PATH_LEN] = { 0 };
to this:
char directory_file[PATH_LEN+sizeof(LOG_NAME)+1] = { 0 };
To debug this issue, you should print the string entered and ask for confirmation before using it (wrap this in #ifdef DEBUG).

Inserting word from a text file into a tree in C

I have been encountering a weird problem for the past 2 days and I can't get to solve it yet. I am trying to get words from 2 texts files and add those words to a tree. The methods I choose to get the words are refereed here:
Splitting a text file into words in C.
The function that I use to insert words into a tree is the following:
void InsertWord(typosWords Words, char * w)
{
int error ;
DataType x ;
x.word = w ;
printf(" Trying to insert word : %s \n",x.word );
Tree_Insert(&(Words->WordsRoot),x, &error) ;
if (error)
{
printf("Error Occured \n");
}
}
As mentioned in the link posted , when I am trying to import the words from a text file into the tree , I am getting "Error Occured". For once again the function:
the text file :
a
aaah
aaahh
char this_word[15];
while (fscanf(wordlist, "%14s", this_word) == 1)
{
printf("Latest word that was read: '%s'\n", this_word);
InsertWord(W,this_word);
}
But when I am inserting the exact same words with the following way , it works just fine.
for (i = 0 ; i <=2 ; i++)
{
if (i==0)
InsertWord(W,"a");
if (i==1)
InsertWord(W,"aaah");
if (i==2)
InsertWord(W,"aaahh");
}
That proves the tree's functions works fine , but I can't understand what's happening then.I am debugging for straight 2 days and still can't figure it. Any ideas ?
When you read the words using
char this_word[15];
while (fscanf(wordlist, "%14s", this_word) == 1)
{
printf("Latest word that was read: '%s'\n", this_word);
InsertWord(W,this_word);
}
you are always reusing the same memory buffer for the strings. This means when you do
x.word = w ;
you are ALWAYS storing the SAME address. And every read redefine ALL already stored words, basically corrupting the data structure.
Try changing the char this_word[15]; to char *this_word; and placing a this_word = malloc(15);in the beggining of thewhile` loop instead, making it allocate a new buffer for each iteration. So looking like
char *this_word;
while (fscanf(wordlist, "%14s", this_word) == 1)
{
this_word = malloc(15);
printf("Latest word that was read: '%s'\n", this_word);
InsertWord(W,this_word);
}
As suggested by Michael Walz a strdup(3) also solves the immediate problem.
Of course you will also have do free up the .word elements when finished with the tree.
Seems like the problem was in the assignment of the strings.Strdup seemed to solve the problem !

Bus Error on void function return

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.

C - Saving to file crashes

FILE *dataScore;
dataScore = fopen(fileName.dat, "w");
fprintf(dataScore,"%s:%d\n",currentUser,score);
fclose(dataScore);
The file crashes on the line printing to file. I believe it is due to the username but I may be wrong. Thanks in advance. Set the currentUser as 02heasam and score as 20.
looks crazy...
try this way:
int score=20;
int main(void){
char* currentUser = "02heasam";
FILE *dataScore;
dataScore = fopen("fileName.dat", "w");
fprintf(dataScore,"%s:%d\n",currentUser,score);
fclose(dataScore);
}
some explanations:
to fill a char array with a string you would need strcpy or so. Not needed here!
the order might be important (declaration before usage)
a strimng literal "xxx" will automatically terminated by a trailing 0-Byte - NEVER miss to have this in mind!

Copying a string from a pointer to a string

I'm developing some code which reads file names from an sd-card (using FatFs) and displays them to the screen. Here's a snipet of what I have working, this prints out the files on the card as expected -
FRESULT result;
char *path = '/'; //look in root of sd card
result = f_opendir(&directory, path); //open directory
if(result==FR_OK){
for(;;){
result = f_readdir(&directory, &fileInfo); //read directory
if(result==FR_OK){
if(fileInfo.fname[0]==0){ //end of dir reached
//LCD_UsrLog("End of directory.\n");
break;
}
if(fileInfo.fname[0]=='.')continue; //ignore '.' files
TCHAR *fn_ptr; //file name, why a pointer?
fn_ptr=&fileInfo.fname; //get file name
LCD_UsrLog("%s\n",fn_ptr);
for(delay=0;delay<0x0FFFFF;delay++){ShortDelay();} //delay to display
}//end result==fr_ok
}//end for
}//end result==fr_ok
Where
typedef char TCHAR
and
typedef struct {
DWORD fsize; /* File size */
WORD fdate; /* Last modified date */
WORD ftime; /* Last modified time */
BYTE fattrib; /* Attribute */
TCHAR fname[13]; /* Short file name (8.3 format) */
} FILINFO;
I need to copy the names of the files into an array for processing however I've tried a few ways but can't seem to get the array working. I have tried creating an arbitrarily large array of TCHARs and dereferencing the file name pointer but this prints garbage.
FRESULT result;
char *path = '/'; //look in root of sd card
TCHAR fileList[50];
u32 index=0;
result = f_opendir(&directory, path); //open directory
if(result==FR_OK){
for(;;){
result = f_readdir(&directory, &fileInfo); //read directory
if(result==FR_OK){
if(fileInfo.fname[0]==0){ //end of dir reached
//LCD_UsrLog("End of directory.\n");
break;
}
if(fileInfo.fname[0]=='.')continue; //ignore '.' files
TCHAR *fn_ptr; //file name, why a pointer?
fn_ptr=&fileInfo.fname; //get file name
fileList[index]=*fn_ptr;
LCD_UsrLog("%s\n",fileList[index]);
for(delay=0;delay<0x0FFFFF;delay++){ShortDelay();} //delay to display
index++;
}//end result==fr_ok
}//end for
}//end result==fr_ok
I suspect this is a simple mistake regarding pointers or the proper usage of an array of chars but it has been 4+ years since I've last touched C and I'm lost!
Any help would be greatly appreciated.
First problem: currently your file list is an array of chars, while it should be an array of strings. So declare it as
TCHAR* fileList[50];
then allocate the strings of proper length for each filename (not forgetting the extra space for the terminating 0 char). You also need to explicitly copy the filenames into your name list, because the contents of fileInfo get overwritten in each loop cycle, so simply storing the pointers would result in your list containing the name of the last file 50 times.
All in all, you need something like this:
if(fileInfo.fname[0]=='.')continue; //ignore '.' files
fileList[index] = malloc(strlen(fileInfo.fname) + 1);
strcpy(fileList[index], fileInfo.fname);
LCD_UsrLog("%s\n",fileList[index]);
(Disclaimer: No guarantee that this works as it is, I have no chance to test it, but hopefully this gives you the idea).
Alternatively, if you know the upper limit of the filename length, you can declare an array of filenames with fixed length, and get rid of dynamic allocation. But then you should use strncpy instead of strcpy to be on the safe side, to prevent buffer overflows. And this also requires the terminating 0 character to be appended, again to be on the safe side:
TCHAR fileList[50][MAX_FILENAME_LENGTH + 1];
...
strncpy(fileList[index], fileInfo.fname, strlen(fileInfo.fname));
fileList[index][MAX_FILENAME_LENGTH] = '\0';
You must use next array definition
TCHAR fileList[50][13];
...
if(fileInfo.fname[0]=='.')continue; //ignore '.' files
strncpy(fileList[index], sizeof(fileList[index]), fileInfo.fname);
LCD_UsrLog("%s\n",fileList[index]);
or for dynamic memory. Don't forget to free memory!
TCHAR* fileList[50];
...
if(fileInfo.fname[0]=='.')continue; //ignore '.' files
fileList[index]=strdup(fileInfo.fname);
LCD_UsrLog("%s\n",fileList[index]);
PS:

Resources