Save command line argument as global variable in C - c

I'm trying to read in two filenames and save them as a global variable in C.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char infilename;
char outfilename;
int main(int argc, const char* argv[]){
strcopy(infilename, argv[1]);
return 0;
}
However this does not work. Can someone help me with a really simple problem like this?

You are trying to copy a string (const char *) to a character (char). You need to either declare infilename as a string:
char *infilename;
infilename = malloc(...
or make a static array:
char infilename[NUM_OF_CHARS];
Read up on c strings here.
Also choose your language, if you are really using c++ you need to start using std::string

A better way to do it.
char infilename[50];
char outfilename[50];
int main(int argc, const char* argv[]){
if(argc == 3)
{
strcpy (infilename,argv[1]);
strcpy (outfilename,argv[2]);
}
else
{
//do something else
}
return 0;
}
You need array of char and not only char. A string in C is an array of char. And you must always verify (if(argc == 3) if the user entered the quantity of argument you want, because if it's not the case your applicatin can crash.

That's not going to work.
These:
char infilename;
char outfilename;
declare a variables that store a single char, not an entire string.
You either need to make those char arrays:
char infilename[MAX_PATH];
char outfilename[MAX_PATH];
or pointers that you plan to initialize with malloced memory. You have to pick which one you mean.
P.s. there's no function called strcopy, it's strcpy.

The main problem is that you made your global variables single characters not an array of characters which is needed for a string.
Assuming you don't want to change the contents of the string then the easiest thing is to simply set a global to point to the same string rather than copying it. Because the program will end when main returns there is no worry about the parameters argv going out of scope.
Note you would have to worry about this if you create a new thread and terminate the thread running main without terminating the program.
#include <stdio.h>
#include <stdlib.h>
static char* gInFilenamePtr;
static char* gOutFilenamePtr;
int main(int argc, const char* argv[])
{
if( argc > 2 )
{
gInFilenamePtr = argv[1];
gOutFilenamePtr = argv[2];
}
return 0;
}

Related

How to concatenate char pointers using strcat in c? [duplicate]

This question already has answers here:
Why do I get a segmentation fault when writing to a "char *s" initialized with a string literal, but not "char s[]"?
(19 answers)
Closed 3 years ago.
I'm learning pointers in C, using Linux. I'm trying to use the strcat function, but it doesn't work and I don't understand why.
I'm passing a username to the main as an argument because I need to concatenate and put a number 1 in the first position of this username. For example if the I got as argument username123 I need to convert this to 1username123
I got this code:
#include <stdio.h>
#include <string.h>
int main(int argc, char *arg[]){
const char *userTemp;
char *finalUser;
userTemp = argv[1]; //I got the argument passed from terminal
finalUser = "1";
strcat(finalUser, userTemp); //To concatenate userTemp to finalUser
printf("User: %s\n",finalUser);
return 0;
}
The code compiles, but I got a segmentation fault error and doesn't know why. Can you please help me going to the right direction?
It is undefined behaviour in C to attempt to modify a string literal (like "1"). Often, these are stored in non-modifiable memory to allow for certain optimisations.
Let's leave aside for the moment the fact that your entire program can be replaced with:
#include <stdio.h>
int main(int argc, char *argv[]){
printf("User: 1%s\n", (argc > 1) ? argv[1] : "");
return 0;
}
The way you ensure you have enough space is to create a buffer big enough to hold whatever you want to do. For example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]){
// Check args provded.
if (argc < 2) {
puts("User: 1");
return 0;
}
// Allocate enough memory ('1' + arg + '\0') and check it worked.
char *buff = malloc(strlen(argv[1]) + 2);
if (buff == NULL) {
fprintf(stderr, "No memory\n");
return 1;
}
// Place data into memory and print.
strcpy(buff, "1");
strcat(buff, argv[1]);
printf("User: %s\n", buff);
// Free memory and return.
free(buff);
return 0;
}
What you shouldn't do is to allocate a fixed size buffer and blindly copy in the data provided by a user. That's how the vast majority of security problems occur, by people overwriting buffers with unexpected data.
I'm trying to use the strcat function, but it doesn't work and I don't understand why.
For starters, you really shouldn't use strcat(). Use strlcat() instead. The "l" version of this and other functions take an extra parameter that let you tell the function how large the destination buffer is, so that the function can avoid writing past the end of the buffer. strcat() doesn't have that parameter, so it relies on you to make sure the buffer is large enough to contain both strings. This is a common source of security problems in C code. The "l" version also makes sure that the resulting string is null-terminated.
The code compiles, but I got a segmentation fault error and doesn't know why.
Here's the prototype for the function: char *strcat( char *dest, const char *src );
Now, you're calling that essentially like this: strcat("1", someString);. That is, you're trying to append someString to "1", which is a string constant. There's no extra room in "1" for whatever string is in someString, and because you're using a function that will happily write past the end of the destination buffer, your code is effectively writing over whatever happens to be in memory next to that string constant.
To fix the problem, you should:
Switch to strlcat().
Use malloc() or some other means to allocate a destination buffer large enough to hold both strings.
Unlike in other languages there is no real string type in C.
You want this:
#include <stdio.h>
#include <string.h>
int main(int argc, char *arg[]){
const char *userTemp;
char finalUser[100]; // finalUser can contain at most 99 characters
userTemp = argv[1]; //I got the argument passed from terminal
strcpy(finalUser, "1"); // copy "1" into the finalUser buffer
strcat(finalUser, userTemp); //To concatenate userTemp to finalUser
printf("User: %s\n",finalUser);
return 0;
}
or even simpler:
#include <stdio.h>
#include <string.h>
int main(int argc, char *arg[]){
char finalUser[100]; // finalUser can contain at most 99 characters
strcpy(finalUser, "1"); // copy "1" into the finalUser buffer
strcat(finalUser, argv[1]); //To concatenate argv[1] to finalUser
printf("User: %s\n",finalUser);
return 0;
}
Disclaimer: for the sake of brevity this code contains a fixed size buffer and no check for buffer overflow is done here.
The chapter dealing with strings in your C text book should cover this.
BTW you also should check if the program is invoked with an argument:
int main(int argc, char *arg[]){
if (argc != 2)
{
printf("you need to provide a command line argument\n");
return 1;
}
...
You're missing some fundamentals about C.
finalUser = "1";
This is created in "read-only" memory. You cannot mutate this. The first argument of strcat requires memory allocated for mutation, e.g.
char finalUser[32];
finalUser[0] = '1';

How do I pass a string array from a function to main [duplicate]

This question already has answers here:
pass strings by reference in C
(8 answers)
Closed 7 years ago.
I'm trying to Initialize a string in Initialize then pass it to int main() for screen output, but it seems that the strings that are initialized have become corrupted.
Headers
#include<stdio.h>
#include<stdlib.h>
Initialize
void
Initialize(char* STRINGs)
{
STRINGs = malloc(sizeof(char)*5);
STRINGs = "hello" ;
printf("1: %s\n",STRING);
}
Main
int
main (char* STRINGs)
{
Initialize(STRINGs);
//The program stops working when it reaches this section
printf("2: %s",STRINGs);
return 0;
}
You can use this code to initialize the string variable
char * Initialize()
{
char* STRINGs="HELLO";
printf("1: %s\n",STRINGs);
return STRINGs;
}
int main ()
{
char *strings =Initialize();
//The program stops working when it reaches this section
printf("2: %s",strings);
return 0;
}
First, you have wrong prototype for int main (char* STRINGs), which must be either:
int main(), or
int main( int argc, char *argv[] )
How do I pass a string array from a function to main
As it stands, you can create a string inside your Initialize() then return a pointer to that string.
There are several issues in your Initialize() though.
Here's a suggestion to change:
char *
Initialize()
{
char *STRINGs = malloc(strlen("hello") + 1); // <-- malloc must include an additional space for the NULL terminator.
strcpy( STRINGs, "hello" ); // <-- NEVER use assignment for string type.
printf("1: %s\n",STRINGs);
return STRINGs;
}
Then your main() can be like this:
int main()
{
char *str = Initialize();
printf( "str = %s\n", str );
return 0;
}
NOTE: do not forget to add #include <string.h>
Here's an answer. First, when allocating memory for any variable, it must be freed or you'll get some nasty system errors at some point or at the very least, a memory leak.
In the int main(), the declaration should ideally be int main(int argc, char* argv[]).
I also recommend allocating at least one more byte of memory just in case you create a string and a function you use later on requires a null character appended to it.
I fixed your code to make it work at its bare minimum.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* Initialize(){
char* string = malloc(sizeof(char)*6);
strcpy(string,"hello");
printf("1: %s\n",string);
return string;
}
int main (int argc, char* argv[]){
char *strings=Initialize();
printf("2: %s\n",strings);
free(strings);
return 0;
}
For a shorter version of your code, I suggest this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char* argv[]){
char* strings=malloc(6);
strcpy(string,"hello");
printf("2: %s\n",strings);
free(strings);
return 0;
}
For the sake of understanding, let us suppose STRINGs of main function is a.
And STRINGs of initialize function is b.
At first, in main a is pointing to some unknown location say u. When you pass this to the initialize function then b also starts pointing to the location u.
But, after the allocation of memory, b starts pointing to some other memory that was allocated by malloc say m.
Now you change the contents of memory m by use of b. But a is still pointing to the unknown location u.
So both the pointers are now pointing towards two different memory locations. So when you print contents where b is pointing it works perfectly and then you printf contents of a which has no specific location or may be null.
So, because of this your problem came.
And also, there is another error in your program that is in the printf of initialize function, it has given a parameter STRING which is undeclared....make it STRINGs.
Hope you will like the explanation. Its a little bit tricky.
Thanks :-)
You can use:
void Initialize(char** STRING)
Instead:
void Initialize(char* STRINGs)
because you want to change the the address to which STRING points
Also you have wrong prototype of main
Try:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void Initialize(char** STRING)
{
*STRING = malloc(6);
strcpy(*STRING, "hello");
printf("1: %s\n",*STRING);
}
int main (int argc, char *argv[])
{
char* STRING;
Initialize(&STRING);
printf("2: %s\n",STRING);
free(STRING);
return 0;
}

Dynamically allocated string from command line argument

I'm looking to process a string passed via a command line argument with a for loop in C. I'm wondering if this would be the correct way.
main(int argc, char * argv[])
{
char * somestring;
somestring = malloc( (strlen(argv[1]) + 1) * sizeof(char) );
somestring = argv[1];
...
}
or would C allocate the appropriate memory if I did:
char * somestring;
somestring = argv[1];
If you want to copy an argument in your own allocated memory then you have to write
int main(int argc, char * argv[1])
{
char * somestring;
somestring = malloc( strlen( argv[1] ) + 1 );
strcpy( somestring, argv[1] );
...
}
otherwise statement
somestring = argv[1];
results in a memory leak.
Also do not forget to free the memory when it will not be needed any more.
Take into account that though this record
int main(int argc, char * argv[1])
is valid it is better to write
int main(int argc, char * argv[])
because your intention by specifying char * argv[1] is not clear
If you need to preserve a transient string then yes you need to allocate memory, copy it into the new buffer (via strcpy-like function) and latter deallocate that buffer.
But in this case, the command line arguments are not transient. They are available for the whole lifetime of the process. Therefore it is enough to just remember the pointer to them. So something like this would be enough:
const char* firstParameter = nullptr;
int main(int argc, char* argv[])
{
if (argc > 1) firstParameter = argv[1];
}
A good way would be allocating the memory for the pointer and use strcpy function to copy the contents.
For example:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char * argv[])
{
char *somestring;
if(argv[1] == NULL)
{
puts("Argument 1 is not specified.");
exit(1);
}
somestring = malloc( strlen(argv[1])+1 );
strcpy(somestring, argv[1]);
printf("%s\n",somestring);
return 0;
}
Also before allocating the memory for pointer, first check if argv[1] is not NULL.
Fisrt of all this is a wrong way of copying a string into another string.
You have done memory allocation correcly but your method of copying a string into another is wrong. You have allocated memory for string and collected its address into somestring. Now you are assigning argv[1] to it which is address of command line argument vector which is 2D array actually. So you should use strcpy() to copy string.
Or if you want just base address of string use char pointer instead and assign argv[1] to it. But it is of no use.
P.S. passing command line argument like you are doing is not recommended as all arguments are stored in argument vector argv which is 2D array. So if you are passing only one string then it is okay but if you are passing more than one strings then use char **argv instead.

How to compose characters into a single string in memory?

I am working on a school assignment and I need a little bit of help.
My question is, how can I compose characters that are read in from a file into a single string of memory. Here is what i have so far.
My Code:
#include <stdio.h>
#include <stdlib.h>
char myString;
int main(int argc, char *argv[]){
FILE* fin;
char ch;
fin=fopen(argv[1],"r");
while((ch=fgetc(fin))!=EOF){
printf("%c\n", ch);
}
fclose(fin);
return 0;
}
My teacher said the last part of main is to be:
putchar(ā€˜\nā€™);
printf( myString );
return 0;
}
But I'm not sure how to put that within my code. Thank you ahead of time, Im also not looking to be just given the answer if you could help me work it out that would be great thank you again.
Updated code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
FILE* fin;
int i;
char myString[3];
fin=fopen(argv[1],"r");
while(fgets(myString,sizeof(myString), fin)){
putchar('\n');
printf("%c\n", myString[i]);
}
fclose(fin);
return 0;
}
Im unsure if this code is exactly correct. It prints out the items within the file and puts a space between them. and there is an array being used for the string.
Im also not looking to be just given the answer
Fine.
Define a char array (mystring) large enough to hold your string
Define a counter to keep track of the position in the array
At each step store ch into the array
Remember to 0-terminate it (store 0 as the last element).
Things to note:
You will need to learn about realloc and grow the storage as you go if your program is to read arbitrarily long input. Better leave that for later
It's generally unsafe to printf(dynamicstr). What if it contains a "%d" ? It's better to printf("%s", dynamicstr).
You get to learn about memcpy and malloc. They are your friends.
--Jason
You need to read the applicable part of your textbook that explains what a "string" is in C. Without you understanding that, there's almost no way to answer your question without simply doing it for you.
A C "string" is a contiguous chunk of memory containing chars and is NULL terminated. You'll need to allocate that then place the characters into it as you read them from the file. Note that you have to make sure you don't go beyond the memory you've allocated while doing so, this is called a "buffer overflow".
#include <stdio.h>
#include <stdlib.h>
char* myString;
int main(int argc, char *argv[]){
FILE* fin;
fpos_t fsize = 0;
char ch;
char *pch;
fin=fopen(argv[1],"r");
fseek(fin,0,SEEK_END);
fgetpos(fin, &fsize);
rewind(fin);
pch = myString = (char*)malloc((fsize+1)*sizeof(char));
while((ch=fgetc(fin))!=EOF){
*pch++ = (char)ch;
}
*pch = '\0';
fclose(fin);
printf("%s", myString);//printf(myString);// need escape %
free(myString);
return 0;
}

How to receive a arg from command line in C

I want to write a program to receive a argument from command line. It's like a kind of atof().
There my program goes:
9 char s[] = "3.1415e-4";
10 if (argc == 1) {
11 printf("%e\n",atof(s));
12 }
13 else if (argc == 2) {
14 //strcpy(s, argv[1]);
15 printf("%e\n",atof(argv[1]));
16 }
1.should I just use argv[1] for the string to pass to my atof(), or, put it into s[]?
2.If I'd better put it in s[], is there some build-in function to do this "put" work? maybe some function like strcpy()??
thanks.
I personally would do it this way:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv)
{
const char defaultStr[]="3.1415e-4";
const char *arg = NULL;
if(argc <= 1)
{
arg = defaultStr;
}
else
{
arg = argv[1];
}
printf("%e\n", atof(arg));
return 0;
}
There is no need for put it into s. Just use argv[1].
Having said this, is you are putting it into s anyway (which is not that bad) make sure you change your code to:
char s[20];
strcpy(s, argv[1]);
Using strcpy with a constant char array is not a good idea.
You can simply pass it as argv[1], no need to copy it. Should you want to copy it, you need to ensure that s can actually hold the full string contained in argv[1], and allocate a bigger array if not... so it is messier.

Resources