I am new to C and am trying to define an output filename before the program runs. I am getting a Bus error
Here is my code:
#include <stdio.h>
int main (int argc, const char * argv[]) {
char fname[128];
printf("Enter the file name\n");
scanf("%123s",fname);
strcat("/Users/user/Desktop/learn/", fname);
strcat(fname, ".txt");
FILE *fp;
fp=fopen(fname,"a");
fprintf(fp, "Testing... OK I think it worked\n");
return 0;
}
You didn't #include <string.h> for strcat.
The first argument to strcat must be a pointer, not a string literal.
strcat itself isn't safe, use strncat instead.
Don't forget to check the result of scanf and fopen.
And close fp when you're done with it.
The signature of main should be int main(int argc, char * argv[]).
The use of scanf is also generally discouraged, use fscanf & sscanf instead.
You are using a string literal as the destination pointer in the first call to strcat. so you are concatonating "/Users/user/Desktop/learn/" with fname and storing the result where ever "/Users/user/Desktop/learn/" was stored, which might not even be writable.
That's not how strcat() works.
I see two approaches:
Use fname correctly, together with the file name inputting:
char fname[128];
strcpy(fname, "/Users/user/Desktop/learn/"); // ok as long as you don't make the 128 too small
char * input = fname + strlen(fname); // now points after the final /
printf("Enter the file name\n");
scanf("%123s", input); // the 123 is probably not correct
strncat(fname, ".txt", sizeof fname);
and use it.
Currently, this approach is still suffering from the fact that input is limited to 123 bytes, which might be too large, so better forget it for now. It is just for getting the idea.
Maybe fgets() might be better:
fgets(input, sizeof(fname)-strlen(fname), stdin);
Use command line parameters, which would be my favourite approach:
// first check if argc is >= 2, i. e. if the caller has supplied an argument
char fname[128];
strcpy(fname, "/Users/user/Desktop/learn/");
strncat(fname, argv[1], sizeof fname);
strncat(fname, ".txt", sizeof fname);
Try this, this is worked for me..
http://cboard.cprogramming.com/c-programming/124576-whats-mean-char*-const*-argv.html
#include <stdio.h>
#include <string.h>
int main (int argc, const char*const* argv[])
{
char fname[128];
char path[] = "/home/abc/test/";
printf("Enter the file name\n");
scanf("%123s",fname);
strcat(fname,".txt");
strcat(path,fname);
FILE *fp;
fp=fopen(path,"a");
fprintf(fp, "Testing... OK I think it worked\n");
fclose(fp);
return 0;
}
Thanks for everyone's comments. This was working code:
#include <stdio.h>
#include <string.h>
int main (int argc, const char*const* argv[])
{
char fname[128];
strcpy(fname, "/Users/user/Desktop/learn/");
char * input = fname + strlen(fname);
printf("Enter the file name\n");
scanf("%s", input);
strncat(fname, ".txt", sizeof fname);
printf("The output pathway and file will be called %s\n", fname);
FILE *fp;
fp=fopen(fname,"a");
fprintf(fp, "Testing... OK I think it worked\n");
fclose(fp);
return 0;
}
Related
Good afternoon, Old man trying to learn new tricks here,
I have been given an assignment that I am trying to work my way through but I am stuck as I don't fully understand the argv[]
I have 4 files I want to read from and eventually use malloc and realloc but thats further down.
My initial plan was to try read one file and get it onto the command line. I had it opening but made that many changes that now I'm lost.
Think my problem lies with argv[4] as i dont understand it, when I put 4 it goes into theloop and errors but with 1 it just bombs out.
If someone can point me in the direction I am going wrong here it would be great
Thanks
struct Person { char lname[20]; char fname[20]; int id; };
int i, N;
struct Person *student;
int main(int argc, char *argv[])
{
FILE *outputfile;
printf("Please enter the name of the file to open: ");
scanf("%s", argv[4]);
outputfile = fopen(argv[4], "r") ;
if (outputfile==NULL){
perror(argv[1]);
fprintf(stderr,"Error while opeining file\n");
exit(-1);
}
You don't have to use argv[]. Argv is an array of strings that store the arguments passed in when running the executable. If you run the executable like this: ./a.out, then argv only contains one element, which is the path of the executable itself. If you run the program like this, and you try to access argv[4], it does not give you an error, but if you debug it using GDB, it will output the following: warning: Invalid parameter passed to C runtime function.
You could pass in a file on the command line like this: ./a.out yourfile.txt. In this case, argv[0] will be the path of the executable a.out, and argv[1] will be the string "yourfile.txt".
It might be easier to completely drop the use of argv and store the user input for the filename in a string. You can then pass that string as an argument to fopen. This would look something like this:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
char fileName[30];
char ch;
printf("Please enter a file name\n");
scanf("%s", fileName);
FILE *outputFile = fopen(fileName, "r");
if(outputFile == NULL) {
printf("Could not open %s\n", fileName);
exit(-1);
}
}
Use constants (NAME_LEN) instead of hard-coding magic values.
Prefer multiple lines for your struct. It's easier to read and version control systems prefer lines for diffs.
Avoid global variables.
Do a boundary check using argc (count of elements in argv) before you read argv. argv[0] is the name of your program, argv[1] is the first argument.
Treat argv as read-only, i.e. don't do scanf("%s", argv[4]).
Prefer to initialize variables instead of declaring and assigning a value separately. It's easy to forget setting a variable before use which leads ot undefined behavior. Initialization might be faster, too.
Your file handle is called outputfile but with fopen() you use the mode of r for reading. Either mode should be w or you want to change the variable name to inputfile.
#include <stdio.h>
#include <string.h>
#define NAME_LEN 20
struct Person {
char lname[NAME_LEN];
char fname[NAME_LEN];
int id;
};
int main(int argc, char *argv[]) {
char filename[FILENAME_MAX];
if(argc > 4) {
strcpy(filename, argv[4]);
} else {
printf("filename? ");
fgets(filename, FILENAME_MAX, stdin);
filename[strcspn(filename, "\n")] = '\0';
}
FILE *outputfile = fopen(filename, "w");
if(!outputfile) {
// ...
}
fclose(outputfile);
}
and you would run your program with either:
$ ./a.out dummy dummy dummy output.txt
or
$ ./a.out
filename? output.txt
It sounds as if you are expected to provide 4 file names as command line parameters. In which case you should be doing this:
#include <stdio.h>
int main (int argc, char *argv[])
{
const int files = 4;
if(argc != files+1)
{
printf("Usage: myprog file1 file2 file3 file4");
return 0;
}
FILE* fp [files];
for(int i=0; i<files; i++)
{
fp[i] = fopen(argv[i+1], "r");
...
}
...
}
I have created a file called mahmoud.txt in the direceotry: /Users/mahmoudhamra/Desktop/C language/
I want to open it in Xcode.
I created the directory and the name of the file into a string each.
Then I concatenated the file name to the directory and tried to open it to read it but it always gives me an error: "Thread 1: signal SIGBART".
Can someone help me please?
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, const char * argv[]) {
FILE *inFile;
char fileName[13];
printf("enter file name: ");
scanf("%s",fileName);
char new[40]="/Users/mahmoudhamra/Desktop/C language/";
strcat(new, fileName);
inFile=fopen("new", "r");
if (inFile== NULL) {
printf("file %s was not opened!\n", fileName);
printf("check that the file exists!\n");
exit(1);
}
else
printf("the files has successfully been opened!\n");
return 0;
}
First of all this
char new[40]="/Users/mahmoudhamra/Desktop/C language/";
should be at least
char new[41]="/Users/mahmoudhamra/Desktop/C language/";
to leave space for null terminator. A C-string is an array of chars with a null-terminator (0x00, '\0', 0) as last char.
Best would be:
char new[]="/Users/mahmoudhamra/Desktop/C language/";
BTW your problem is that you have no space to add filename chars, so at least you should define it as
char path_and_file[128] = {0};
strncpy(path_and_file, "/Users/mahmoudhamra/Desktop/C language/", sizeof(path_and_file)-1);
If you want to learn something about dynamic allocation you can:
char *directory = "/Users/mahmoudhamra/Desktop/C language/";
char *path_and_file = malloc(strlen(directory)+1);
if (path_and_file != NULL)
{
strcpy(path_and_file, directory);
printf("enter file name: ");
scanf("%s",fileName);
path_and_file = realloc(path_and_file,strlen(directory)+strlen(filename)+1);
if (path_and_file != NULL)
{
strcat(path_and_file, filename);
// YOUR STUFF
}
}
free(path_and_file);
Another way with dynamic allocation is using strdup to create your first string:
char *path_and_file = strdup("/Users/mahmoudhamra/Desktop/C language/");
EDIT
Last thing, as #visibleman pointed out, the call to fopen have to be changed to
inFile=fopen(new, "r");
or according to my examples:
inFile=fopen(path_and_file, "r");
The issue is almost certainly the size of the new character array as it does not have the capacity to hold the complete filename and will cause a stack overflow:
char new[40]="/Users/mahmoudhamra/Desktop/C language/";
strcat(new, fileName);
Change the 40 to 1024:
char new[1024] = ...;
I am new to programming. I want to take one commandline argument which is a filename and open that particular file and copy the contents to another file. I don't know how to convert the commandline argument to a string or file pointer. I checked strcpy and std::string which I found online but it didn't work. Please help me. I have pasted my code below
#include<string.h>
#include <stdio.h>
#include <stdlib.h>
void main(int argc, char *argv[])
{
char *inp;
strcpy(inp,argv[1]);
FILE *fp;
char str[5];
//printf("Enter the file name:");
//scanf("%s",fname);
if ((fp= fopen(inp, "r")) == NULL) {
printf("cannot open file");
exit(1);
}
FILE *fp1;
fp1=fopen("out.txt","w+");
while(!feof(fp)) {
fgets(str,4,fp);
printf("%s",str);
fprintf(fp1,"%s",str);
}
fclose(fp);
fclose(fp1);
}
Why not char *inp = argv[1];?
Or better yet:
fp = fopen(argv[1], "r");
The problem with your code is this:
char *inp;
strcpy(inp,argv[1]);
You're copying argv[1] into inp, but you have no idea what inp points to. If you really want to go that route, you have to allocate memory for inp.
char *inp = malloc(strlen(argv[1]) + 1); /* allocate enough for the string and null-terminator */
strcpy(inp,argv[1]); /* copy the contents */
Just remember to free() afterwards.
P.S. Never use while(!feof(fp)). Just use while(fgets(str,4,fp)).
See this question for more info.
I'm printing this:
char aulaIP2[50];
char aula[50];
printf("Enter the name of classroom: ");
fgets(aula, 49, stdin);
if (fgets(aula, sizeof aula, stdin)){
printf("Enter IP classroom: ");
fgets(aulaIP2, 49, stdin);
FILE *file = fopen("aules.text", "w+");
fprintf(file, "%s:%s", aula, aulaIP2);
fclose(file);
getchar();
}
and the output in the file is:
306
:127
and I want:
306:127
Why isn't fprintf able to print that in the same line? I have already tried doing it with two fprintfs but it's the same result.
From fgets documentation:
A newline character makes fgets stop reading, but it is considered a valid character by the function and included in the string copied to str.
So when you read in your strings, they actually contain the newline character, which is then printed as part of the string. Instead of using fgets() use scanf() which will read until the first whitespace (and not including):
scanf( "%50s", aula );
According to http://www.cplusplus.com/reference/cstdio/fprintf/ fprintf is able to print in one line. See the example on the bottom of that page.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
char* aula = "306";
char* aulaIP2 = "127";
FILE* file = fopen("aules.text", "ab+");
fprintf(file, "%s:%s", aula, aulaIP2);
fclose(file);
return 0;
}
When I read aules.text, I see:
306:127
Are aula and aulaIP2 actually strings, or were you trying to write integers instead (%d)?
I can't seem to work it out. I am using a .c code that opens a file and reads each line. I would like to save in char*substr 4 characters from the line 9 inside the txt file. The line 5 contains
name=Me She; I would like to have in char*substr just Meli.Need help. THX
Here is the c code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *fp;
char str[128];
char str1[128];
if((fp = fopen("/home/folder/file.txt", "r"))==NULL) {
printf("Cannot open file.\n");
exit(1);
}
int lin=0;
while(!feof(fp)) {
if(fgets(str, 126, fp))
printf("%s", str);
if (lin==8)
{
char *c= (char *) malloc(sizeof(char)*strlen(str)+1);
c= strndup(str, strlen(str)-5);?? not working?!!!
printf("d is:",c);
}
lin=lin+1;
}
fclose(fp);
return 0;
}
Your printf is wrong. change it to printf("d is %s\n",c);.
By the way, strdup allocate the memory needed, so you don't have to allocate it yourself. (In fact, you have a memory leak).
You're calling malloc() and then directly overwriting its result with that of calling strndup(), this leaks memory.
Also, the logic in the strndup() call looks wrong. If you want to skip the first 5 characters, you should have str + 5.
If you have strdup(), use:
if (lin==9)
{
char *name = strdup(str + 5);
printf("name is: '%s'\n", name != NULL ? name : "(failed)");
}
Then you should probably break out of the loop. Also note that the pointer name goes out of scope, so it's not available to code outside the loop for instance.