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.
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] = ...;
Right now, I have a main function that looks like (argv[2] is the file I want to loop over, from the command-line)
int main(int argc, char * argv[]) {
FILE *thisfile;
thisfile = fopen(argv[2], "r");
while ....
}
I want to eventually be able to loop over each line of the file, argv[1] and see if any of the lines contain a string, which is argv[1]. I know of the C operations like fgets, but I am not sure how to use them. So for now, outputting each line of the file is enough, but after I'd like to see if each line contains a string. I am very new to C, any help is appreciated!
the first question is easy,the code just like
#include <stdio.h>
#define MAXLINE 1024
int main(int argn, char *argv[])
{
FILE *fp;
char line[MAXLINE];
fp = fopen(argv[2], "r");
while(fgets(line, MAXLINE, fp) != NULL)
printf("The line is:%s\n", line);
return 0;
}
but your second question(find a string in one line) has many ansower,it's pattern recognize,if you want ,you can google kmp.
I am very new to C and I am having trouble with the most fundamental ideas in C. We are starting structures and basically the assignment we are working on is to read a delimited file and save the contents into a structure. The first line of the file has the number of entries and alls that I am trying to do at the moment is get the program to read and save that number and print it out. Please do not assume I know anything about C I really am very new to this.
This code is giving me a segmentation fault
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct info{
char name[100];
char number[12];
char address[100];
char city[20];
char state[2];
int zip;
};
int strucCount;
char fileText[1];
int main(char *file)
{
FILE *fileStream = fopen(file, "r");
fgets(fileText, 1, fileStream);
printf("\n%s\n",fileText);
fclose(fileStream);
}
Here is the sample file
4
mike|203-376-5555|7 Melba Ave|Milford|CT|06461
jake|203-555-5555|8 Melba Ave|Hartford|CT|65484
snake|203-555-5555|9 Melba Ave|Stamford|CT|06465
liquid|203-777-5555|2 Melba Ave|Barftown|CT|32154
Thanks for everyones comments, they helped a lot, sorry to Jim. I am working on very little sleep and didn't mean to offend anyone, I am sure we have all been there haha.
SUGGESTION:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXLINE 80
#define MAXRECORDS 10
struct info{
char name[100];
char number[12];
char address[100];
char city[20];
char state[2];
int zip;
};
int
main(int argc, char *argv[])
{
FILE *fp = NULL;
int nrecs = 0;
char line[MAXLINE];
struct info input_records[MAXRECORDS];
/* Check for cmd arguments */
if (argc != 2) {
printf ("ERROR: you must specify file name!\n");
return 1;
/* Open file */
fp = fopen(argv[1], "r");
if (!fp) {
perror ("File open error!\n");
return 1;
}
/* Read file and parse text into your data records */
while (!feof (fp)) {
if (fgets(line, sizeof (line), fp) {
printf("next line= %s\n", line);
parse(line, input_records[nrecs]);
nrecs++;
}
}
/* Done */
fclose (fp);
return 0;
}
fclose(fileStream);
}
Key points:
Note use of "argc/argv[]" to read input filename from command line
line, nrecs, etc are all local variables (not globals)
Check for error conditions like "filename not given" or "unable to open file"
Read your data in a loop, until end of input file
Parse the data you've read from the text file into an array of binary records (TBD)
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.