I really have no idea how to Google search on this specific topic, so I hope one of you guys can help me out here.
Basically I've got this code:
fp = fopen("ELSO.html", "w");
I also got a variable with a name:
char name[25] = {"JohnShepard"};
What I want is to call fopen so that the name would be JohnShepard.html (i.e the content of the variable). Is such thing even possible?
As an alternative to strcat, you can use snprintf:
char buffer[100];
char name[25] = "JohnShepard";
int i = snprintf(buffer, sizeof buffer, "%s.html", name);
// "i" should now contain the length of string in "buffer"
FILE *fp = fopen(buffer, "w");
// ... etc ...
This method is safer than strcat because it requires you to provide the size of the output buffer. If there isn't enough room, then you won't end up overrunning the buffer (which is dangerous). Also, it doesn't modify the original string, but whether that is important or not is up to you.
Related
I initialize a char array as a global variable in my C program with a default file location/name as
char file[] = "/home/jack/files/data.txt";
Later in the program, if a condition is satisfied I read a file containing a new file name
int read_new_file(char *fname)
{
FILE *inp;
char buffer[255];
char oldFile[127], newFile[127];
inp = fopen(fname, "r");
while ( fgets(buffer, 255, inp) != NULL )
{
sscanf(buffer, "%s %s",oldFile,newFile);
file = newFile; // <---- Is this wrong/unsafe?
}
return 0;
}
I should note that it is assumed file fname only contains one line with 2 strings. This was just to show the general framework of the code. My question, as highlighted in the code, is it wrong or unsafe to simply try and reassign the char file variable with the new string?
The size of the newFile string will likely differ from it's original default size. The default has to be predefined, since the condition may not require a new file to be read. If the assignment is wrong or unsafe, what is a better approach?
You need to declare file so it's large enough to hold newFile.
char file[127] = "/home/jack/files/data.txt";
Then when you want to update it, you use:
strcpy(file, newFile);
file = newFile; // <---- Is this wrong/unsafe?
It is wrong since file is an array. The compiler won't let you do that.
Whether it is safe or not is not relevant since you can't do it.
Use strcpy instead.
strcpy(file, newFile);
I am new to C and came across a Char**, for example in the getline function. I have found several topics regarding this type but none of it explained how to actually use it. I understood the differences between Char[], Char* and Char**, but how can I access the content stored in a Char**?
Could someone explain that to me? Thanks in advance!! :)
So, for example i am trying to use the getline function to extract single lines from a file and to store them:
FILE *fp = fopen(myfile,"r");
size_t fsize;
char **string;
ssize_t bytes_read =0;
while ((bytes_read = getline(string, &fsize, fp))>0) {
// How to handle the content of string now? Is every line from the File stored in the Char** now?
}
Almost always when a function asks for a char** or a ** in general, you're expected to give it the address of a pointer variable. In this case the address of a char*. The address of operator is &, thus you should call getline like this:
char *string = NULL;
size_t size = 0;
while ((bytes_read = getline(&string, &fsize, fp))>0) {
// use string here...
}
free(string);
There are of course exceptions to the rule of ** functions wanting an address of, but getline isn't one of them.
In the case of getline it requires the memory address at which to store the memory address of the first character in the line you've read.
I.e. it needs a pointer to a pointer or a char**.
Your string will be stored in *string.
Of course you can get this information from the documentation :).
I know this question has been asked, but the answers I looked at didn't really apply to my case. At the end of my program, a bunch of files are opened for writing. I've limited the list to just two for simplicity. The variable dirPath is a command line argument passed in at execution.
Here's what I tried first:
FILE *fid_sensory_output;
FILE *fid_msn_output;
fid_sensory_output = fopen(strcat(dirPath,"sensory_output"), "w");
fid_msn_output = fopen(strcat(dirPath,"msn_output"), "w");
This doesn't work because strcat doesn't return a copy of the concatenated strings, but instead appends the 2nd arg to the 1st. When looking up a work around, I found these recommendations, to use strcpy and strcat together, or use sprintf.
I first tried sprintf but was getting an error saying that I was trying to pass an int in where a char * was expected, even though dirPath is declared as a char *. I also tried passing in a string literal with no luck.
I tried using strcat and strcpy in various ways without any success either. Any suggestions?
The only way:
FILE *fid_sensory_output;
char *string;
string=malloc(strlen(dirpath)+strlen("sensory_output")+1);
strcpy(string,dirpath);
strcat(string,"sensory_output");
fid_sensory_output = fopen(string, "w");
free(string);
You can use snprintf for this task. Every string operation should consider buffer size to avoid buffer overflows.
snprintf returns the number of characters written to buffer (not including the string terminator '\0')
FILE *fid_sensory_output;
FILE *fid_msn_output;
char path[MAX_PATH];
snprintf(path, sizeof(path), "%s/%s", dirPath, "sensory_output");
fid_sensory_output = fopen(path, "w");
snprintf(path, sizeof(path), "%s/%s", dirPath, "msn_output");
fid_msn_output = fopen(path, "w");
char temp_dir_path[256];
strcpy(temp_dir_path, dirPath);
fid_sensory_output = fopen(strcat(temp_dir_path, "sensory_output"), "w");
strcpy(temp_dir_path, dirPath);
fid_msn_output = fopen(strcat(temp_dir_path,"msn_output"), "w");
I have a text file called "graphics" which contains the words "deoxyribonucleic acid".
When I run this code it works and it returns the first character. "d"
int main(){
FILE *fileptr;
fileptr = fopen("graphics.txt", "r");
char name;
if(fileptr != NULL){ printf("hey \n"); }
else{ printf("Error"); }
fscanf( fileptr, "%c", &name);
printf("%c\n", name);
fclose( fileptr );
return 0;
}
When I am using the fscanf function the parameters I am sending are the name of the FILE object, the type of data the function will read, and the name of the object it is going to store said data, correct? Also, why is it that I have to put an & in front of name in fscanf but not in printf?
Now, I want to have the program read the file and grab the first word and store it in name.
I understand that this will have to be a string (An array of characters).
So what I did was this:
I made name into an array of characters that can store 20 elements.
char name[20];
And changed the parameters in fscanf and printf to this, respectively:
fscanf( fileptr, "%s", name);
printf("%s\n", name);
Doing so produces no errors from the compiler but the program crashes and I don't understand why. I am letting fscanf know that I want it to read a string and I am also letting printf know that it will output a string. Where did I go wrong? How would I accomplish said task?
This is a very common problem. fscanf reads data and copies it into a location you provide; so first of all, you need the & because you provide the address of the variable (not the value) - that way fscanf knows where to copy TO.
But you really want to use functions that copy "only as many characters as I have space". This is for example fgets(), which includes a "max byte count" parameter:
char * fgets ( char * str, int num, FILE * stream );
Now, if you know that you only allocated 20 bytes to str, you can prevent reading more than 20 bytes and overwriting other memory.
Very important concept!
A couple of other points. A variable declaration like
char myString[20];
results in myString being a pointer to 20 bytes of memory where you can put a string (remember to leave space for the terminating '\0'!). So you can usemyStringas thechar *argument infscanforfgets`. But when you try to read a single character, and that characters was declared as
char myChar;
You must create the pointer to the memory location "manually", which is why you end up with &myChar.
Note - if you want to read up to white space, fscanf is the better function to use; but it will be a problem if you don't make sure you have the right amount of space allocated. As was suggested in a comment, you could do something like this:
char myBuffer[20];
int count = fscanf(fileptr, "%19s ", myBuffer);
if(count != 1) {
printf("failed to read a string - maybe the name is too long?\n");
}
Here you are using the return value of fscanf (the number of arguments correctly converted). You are expecting to convert exactly one; if that doesn't work, it will print the message (and obviously you will want to do more than print a messageā¦)
Not answer of your question but;
for more efficient memory usage use malloc instead of a static declaration.
char *myName // declara as pointer
myName = malloc(20) // same as char[20] above on your example, but it is dynamic allocation
... // do your stuff
free(myName) // lastly free up your allocated memory for myName
So one of the ways to take user-keyboard input in C I know is as follows:
char buffer[LENGTH_KNOWN] = "";
scanf("%s",buffer);
I was wondering if there is any way to take arbitrary length user input. I tried something as follows but I ended up getting a segfault.
char* buffer = "";
scanf("%s",buffer);
printf("%s",buffer);
However this seems to work:
char* buffer = "TEST........keeps going....................."
scanf("%s",buffer);
printf("%s",buffer);
Can anybody explain why I am getting this error and is there any easy way out to scanf arbitrary user input without using malloc and checking buffer overflow?
Thanks in advance!
Actually both are wrong since you can't write to a string literal (in both your examples buffer points to a string literal).
It's impossible to get arbitrarily-long input via a single scanf. You need to get input in a loop and keep adding to a real buffer.
is there any easy way out to scanf arbitrary user input without using
malloc and checking buffer overflow
Use a ready-made function that does it for you. Something like getline(3) (non-standard unfortunately).
ssize_t getline (char **lineptr, size_t *n, FILE *stream)
This function reads an entire line from stream, storing the text
(including the newline and a terminating null character) in a buffer
and storing the buffer address in *lineptr.
char* buffer = "";
scanf("%s",buffer);
printf("%s",buffer);
In the above your code you are not allocating memory for the buffer, so allocate memory for the buffer and read the values into buffer.
char *buffer = "..."; is totally wrong. It is not how you allocate memory because the thing in double quotes is a string literal and it is read-only. You can allocate memory like this:
char buffer[1024];
or dynamically using malloc:
char *buffer = malloc(1024);
/* .... */
free(buffer);
You Never know how much bytes you might read and hence allocate the memory accordingly. So I guess you need to get input in a loop and add in into buffer.
char* buffer;
buffer = malloc(sizeof(char) * 1024); // 1024 is max user input length, or use whatever you want..
scanf("%s", buffer);
buffer = realloc (buffer, strlen(buffer) + 1); // re-allocating the buffer according to user input..( + 1 for counting NULL character)
printf("%s",buffer);