How to assign pointer to global variable? - c

I have to split up a command line argument in order to determine the file type. In order to do this, I'm using
char fileName; //global variable, just below function prototypes
char *fileType;
fileType= strtok(inputFile, "."); //first string split
fileName= (int) &fileType; //store the file name for further use
fileType= strtok(NULL, "."); //get the file type
The tokenizer function is working, but in the interest of keeping redundant code to a minimum, I want to store the filename, as I will have to create a new file with the same name, but different extension later on.
In the debugger, the the fileName variable never gets used. Why?

About
char fileName; //global variable, just below function prototypes
if fileName is supposed to be a string then it must be a pointer to the first char in that string (i.e. char *fileName).
if fileName is suposed to be a pointer to a string, then it should be declared as char **fileName.
About
char *fileType;
if this is a local variable, and fileName is a pointer to it, then after the function return it will be destroyed and the pointer will point to unknown data.
About
fileName= (int) &fileType; //store the file name for further use
this seem non-sense to me. Why cast the address of fileType to an integer? I guess the compiler complained because fileName is a char and not a char * and you noticed this would fix the error. Don't do this kind of fixes without understanding what you're doing, because programming like that just leads to esoterical code which must probably won't work as intended anyway.
So, if fileName is defined as char * then just do fileName = fileType. Else, if fileName is declared as char ** then do fileName = &fileType;
About
fileType= strtok(NULL, "."); //get the file type
if strtok() can return a pointer to a new string, and fileName is declared as char *, then whatever you stored previously in it wouldn't be meaningful anymore. In this case fileName would need to be a char ** (a pointer to a string) which I proposed in my first comment.

You need to use a char array along with strcpy.
Like this:
#define MAX_FILENAME_SIZE 200
char fileName[MAX_FILENAME_SIZE];
int f()
{
fileType = strtok(inputFule, ".");
// then use strcpy
strcpy(fileName, fileType);
}
A char global would only store one character.

Related

How to read const char * from files

I need to read a filename from a text file.
Then I have to use it as an argument for fopen .
Consequently , I need to read it as a const char* because this is the type fopen accepts as a first argument. How do I do this?
I tried something like:
FILE *a;
a=fopen("a.txt","r");
const char *filename
fgets(filename,100,a);
image=fopen(filename,"rb");
Something is be wrong as I receive a segmentation fault when I do this. I think that the variable filename is not well-received by the fopen function.
You may have seen that fopen() takes an argument of type (const char *), but you need to be able to modify your string before you pass it to the function. Also, you need to allocate space for your string, and you might consider allocating space for more than 100 chars. The stdio.h header file contains the macro FILENAME_MAX, which expands to an integer constant of the correct size for an array that will hold the longest possible file name string on a system. For example, you can use char filename[FILENAME_MAX];. When the identifier filename is encountered in the call to fopen(), it decays to a pointer to char, which is converted to a pointer to const char, as per the function prototype.
Furthermore, fgets() keeps the newline when if fetches a line of text, so you will need to remove that. You should check the result of fgets(), as it returns a NULL pointer in the event of an error or if it is called at end-of-file; otherwise it returns a pointer to the first char in filename[].
FILE *a;
a=fopen("a.txt","r");
char filename[FILENAME_MAX];
char *ch;
ch = fgets(filename,FILENAME_MAX,a);
/* Remove trailing newline */
if (ch) {
while (*ch != '\0' && *ch != '\n') {
++ch;
}
if (*ch == '\n') { // replace '\n' with '\0'
*ch = '\0';
}
image=fopen(filename,"rb");
}
First, your seg fault likely comes from trying to use memory that you do not own. i.e. by creating the variable:
const char *filename;
And not giving it any memory ([c][m]alloc) before trying to use it.
Regarding your statement:
Consequently , i need to read it as a const char*.
Not necessarily.
The first argument of the fopen prototype: "FILE *fopen(const char *filename, const char *mode)" simply guarantees that the argument passed in that position will be treated as a const char * within the fopen function.
The argument can be passed using a simple char *, eg. either of these forms:
char *filename = {"somefilename.txt"};
or
char filename[80];
strcpy(filename, "somefilename.txt");
And, as mentioned in comments, and other answers, remove the newline character, \n before passing as an argument.

unable to get filename from argv[1] in C

I'm trying to make a program which makes a copy of the file you put in, only then with a reversed filename (eg. input.txt = txt.tupni).
I start my program with
int main(int argc, char **argv) {
When I use printf("%s",argv[1]) I can see the file name which has been put in. However, when I try to manipulate it I can't get it to work.
char name = argv[1] doesnt work,
neither does char name[] = argv[1] work
All I want is either a char array or a piece of malloc memory which has all of the characters.
argv is of type char **, so argv[1] is of type char *. So that's the type of the variable you want to assign this to.
char *name = argv[1];
You can't declare name as char [] and initialize it with a char *. Only a string literal may be used for initialization.
If you want to make a copy of the string rather than have another pointer to it, you can use strdup which allocates memory for the copied string and copies it over.
char *name = strdup(argv[1]);
Don't forget to free it when you're done with it.
You need to use a function like strcpy to accomplish this, as well as know the string length.
Here's what you do:
int len = strlen(argv[1])
char *buffer = (char*)malloc(len + 1);
if(buffer != NULL)
{
strcpy(buffer, argv[1]);
// copy the file etc.
}

Strcpy from char* to char[] creating the wrong form

typedef struct Symbol{
char varName[16];
} Symbol;
...............
Symbol *newSymbol = malloc(sizeof(Symbol));
const char space[2] = " ";
char *String = "Name Test";
//break off the first word from String and put it into name
char *name;
name = strtok(String,space);
//convert the char * to char[16]
char nameArray[16];
strcpy(nameArray,name);
//set newSymbol->varName to the newly created char[16]
newSymbol->varName = nameArray
I have a char * called String. In my actual program, it is read from a file using fgets, I am just calling it "Name Test" for the purposes of this example. I want to take the first word of the string and assign it as the varName in a Symbol. So what should happen is newSymbol->varName is set to "Name". Because strtok returns a char * but I need a char[16] for the struct, I must convert the char * to a char[16].
However, I get this error:
"Error: incompatible types when assigning to type 'char[16]' from type 'char*'
newSymbol -> varName = nameArray;
So, it seems like strcpy it not actually converting the char * to a char[16]. Even after declaring a char[16] and telling strcpy to put the contents of the char * into it, I still have a char * instead of a char[16]. I need to make it work without changing the struct, so that is not an option here.
How can I convert a char * into a char[16]?
You cannot assign the contents of an array using the regular assignment operator in C.
You can use strcpy for strings and memcpy/memset for other data types. (You could use memcpy/memset for strings too but strcpy is simpler)
Instead of
newSymbol -> varName = nameArray;
use
strcpy(newSymbol -> varName, nameArray);
So, it seems like strcpy it not actually converting the char* to a char[16].
No, the problem is that C does not provide for assigning to (whole) arrays. newSymbol->varName is an array of 16 char. You can assign to elements of that array, and you can copy into it with strcpy() or a similar function, but you cannot assign to the whole array.
In your particular code, I'd dispense with variable nameArray, changing this ...
strcpy(nameArray,name);
... to this:
strcpy(newSymbol->varName, name);
(Or perhaps to a similar usage of strncpy(), to protect from overrunning the array bounds.)

How to use const char pointer returned from a function in this instance? (mongodb related)

I'm having a bit of trouble with a a function that the mongodb c driver uses. The function in question looks like this:
gridfile_get_field (gridfile *gfile, const char *name) (returns const char *)
I'm attempting to use it in the following manner:
const char * field = "file";
char * filename;
filename = (char *)gridfile_get_field(&gfile, field);
FILE * file;
file = fopen("test.txt", "a+");
fprintf(file, "file contains: %s\n", filename);
fclose(file);
However, after execution, I see this in test.txt:
file contains: ^A
file contains: ^A
file contains: ^A
I'm not sure what I'm doing wrong. The field that I specify exists in all of my files that I store in gridfs, so I don't think that's the case (specifying something that doesn't exist just files in "file contains: " with no character afterwards). I guess I'm doing something wrong in regards to the pointers. If anyone has any suggestions, that'd be awesome.
EDIT:: The real declaration is
const char * gridfile_get_field (gridfile *gfile, const char *name);
If you feel the need to cast the return value of a function, you are most likely doing something wrong.
First, you should declare filename as being char const* since this is what you expect the function to return.
Then, probably you don't have the correct prototype for the function. You should have got an include file that comes with it. As a last resort declare the prototype as
char const * gridfile_get_field (gridfile *gfile, const char *name);
(Your compiler is probably taking the function to return an int, cuts of the high order bits and re-interprets this as a char*)
Turned out to be an issue with the MongoDB C driver- it wasn't returning the correct information. I think that issue will be addressed in an upcoming release.

fread/fwrite string in C

I have a binary file which contains records. The structure of the file is as such:
Structure (see below)
Name String
Address String
The structure in question:
typedef struct{
char * name;
char * address;
short addressLength, nameLength;
int phoneNumber;
}employeeRecord;
employeeRecord record;
I get the name as such:
char name[50];
printf("\nName:");
fgets(name,50,stdin);
record.nameLength = strlen(name)-1;
record.name = malloc(sizeof(char)*record.nameLength);
strcpy(record.name,name);
I write the structure, the the name, then the address (as mentioned above).
fwrite(&record.name,sizeof(char),record.nameLength,fp);
where fp is a file pointer.
Now i close the file.
However, if i then want to read from the file to get this data back, I believe I need to read in the structure, read the nameLength variable, malloc enough memory for the name to sit in, then fread the name into the variable.
Like so:
char *nameString = malloc(sizeof(char)*record.nameLength);
fread(nameString,sizeof(char),record.nameLength,fp);
printf("\nName: %s",nameString);
However, when i attempt this, i do not get valid data.
Example:
Input name is: Joseph (6 characters)
Output data:
Name length is 6 (correct),
Name is �A � (aka garbage)
So obviously im doing something wrong. Could someone give me some help?
I see two problems with the write, you are setting record.nameLength to be too small, and you are passing the wrong pointer to fwrite for the name. record.name is already a pointer.
Change this
record.nameLength = strlen(name)-1;
...
fwrite(&record.name,sizeof(char),record.nameLength,fp);
to this
record.nameLength = strlen(name);
...
fwrite(record.name,sizeof(char),record.nameLength,fp);
You also have a problem on the read, since you aren't writing the terminating \0 from the strings into your file, when you read back, you need to add that terminator explicitly.
char *nameString = malloc(sizeof(char)* (record.nameLength + 1));
fread(nameString,sizeof(char),record.nameLength,fp);
nameString[record.NameLength] = '\0';
The problem is that you pass the pointer to the char* in your fwrite:
fwrite(&record.name,sizeof(char),record.nameLength,fp);
This means that instead of writing the name, you're writing the memory address of the name. Fwrite expects a pointer to the data to write—in your case, that's the pointer to the char data, not the pointer to the pointer of the char data.
Pass it record.name instead of &record.name and you should be set:
fwrite(record.name, sizeof(char), record.nameLength, fp);

Resources