This question already has answers here:
What does int argc, char *argv[] mean?
(12 answers)
Closed 5 years ago.
in my C script my input is printing out gibberish and im not sure why
heres more or less what i have on it
int main (int arg, char argv[])
{
printf(argv);
}
this prints out giberish?
The following should yield the results you are looking for
#include <stdio.h>
int main(int argc, char **argv)
{
// Check if there is at least 2 arguments. First argument is the executable name.
if(argc > 1)
{
// Print out a string, followed by a new-line character.
printf("%s\n", argv[1]);
}
// Exit successfully
return 0;
}
Edit: After looking at your code here and some of the things I recommend to change:
The signature of your main function to int main(int argc, char **argv). Here argc is the argument count, and argv are the argument values. argv is a double-pointer. If we consider char* to be a string (sequence of characters in memory terminated by a null-character, or 0), then argv is a pointer to argc-many strings.
Secondly, to check the first program argument, consider making sure that there is in-fact an argument there. if(argc > 1) will make sure there is at least 1 argument to the program (the 0-index argument to a program is the executable path).
When you want to actually check the value of the first argument, de-reference argv to get a "string" with argv[1] //The first argument. Then you can de-reference this string to get the first character
if ( *(argv[1]) == 'f' )
{
....
}
If you want to check for a full string, rather than just a single character, consider using a function such as strcmp defined in <string.h>.
Related
I am making a program that can take another program as an argument and run it.
I am using execv() to run the second program, but how can I use argv[] (that comes from the main program, is a char*) as arguments for execv()?
The first element of argv[] is the name of the main program, so I need to start at the second element where the name of the next program is located.
I am thinking there might be different solutions, for example:
Tell execv() to start from the second argument
copy the content of argv[] (except first element) to another array and use that
Something with pointers so maybe I can point to the second element and start there
What is the best way to do this?
And can I get an example of how to do it?
First of all, the argv is actually a pointer to array of pointers. The more correct way to define it would be char **argv.
Defining it as *argv[] is just a syntactic sugar. So your third guess is a best one:
#include <stdio.h>
void print_array(int array_size, char **array) {
for(int i=0; i<array_size; i++) {
printf("\t%s\n", array[i]);
}
}
int main(int argc, char **argv) {
char **argv_new = argv+1;
printf("argv:\n");
print_array(argc, argv);
printf("argv_new:\n");
print_array(argc-1, argv_new);
return 0;
}
You can also play with interchanging function arguments char **argv vs char *argv[] and you wont see a difference.
But code like:
int main(int argc, char *argv[]) {
char *argv_new[] = argv+1;
will give you an error - of invalid type conversion. That is due to a fact that defining an array on a stack requires to know the size of array during the compilation. But defining array as a function parameter - does not, the compiler in that case presumes that the stack manipulation is done in the caller function.
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';
I am new to C and I have a small problem in understanding this scanf() line:
printf("Enter a message to add to message queue : ");
scanf("%[^\n]",sbuf.mtext);
How do I write this statement if I am getting the value from the command line?
I think I would have to declare the variable as a string?
If you are getting any value or data from command line then the command line arguments (click to open link) are very helpful
for using command line arguments, you must change you main() function definition from, let's say int main() to
int main ( int argc, char *argv[] )
here int argc is the argument counter. It is an integer and stores the number of arguments passed from the command line (+ the name of the program)
and char* argv[] is the argument vector which holds the data you sent into main function as strings
How do I write this statement if I am getting the value from the
command line?
As any value you entered at command line is stored in char *argv[], you can access the appropriate string this way
printf("%s",argv[command_no])
Example : (printing out value of argc and all strings stored in *argv[])
#include <stdio.h>
int main(int argc, char* argv[])
{
printf("%d\n",argc);
for(int i=0;i<argc;i++)
{
printf("%s\n",argv[i]);
}
return 0;
}
Command line arguments :
these are command line arguments :)
Output:
6
E:\C-Programming\Workspace\Interview\Debug\Interview.exe
these
are
command
line
arguments
:)
Note : The first argument or the argv[0] is always the name of the program
I tried to add an argument to main by scanf. But it didn't work. The following is my program. My question is: what's wrong with this program? And is it possible to add an argument to main by scanf() instead of in the command line?
#include <stdio.h>
#include <errno.h>
int main(int argc, char* argv[]){
/*check if there is no argument, that is, argc!=2*/
if(argc != 2){
puts("Please enter an argument: ");
scanf("%s", &argv[1]);
printf("\nYou've entered argument: %s\n", argv[1]);
return 1;
}
printf("\nYou've entered argument: %s\n", argv[1]);
return 0;
}
Yes, code can effectively add arguments.
"The parameters argc and argv and the strings pointed to by the argv array shall be modifiable by the program, and retain their last-stored values between program startup and program termination." C11dr ยง5.1.2.2.1 2
So this allows code to change argc and argv and change argv[0][0] (if argc > 0) - but wait, there's more...
Can code change the original elements of argv[], like argv[1], etc? That is an open question still hanging in SO here. So let us avoid that.
The way to change the contents of argv[] is to first create an alternate set argv_alt[] array and then assign argv_alt --> argv.
#include <stdio.h>
int main(int argc, char *argv[]) {
// Assume argc == 1
printf("%d '%s'\n", argc, argv[0]);
char a[3][10] = { "abc", "def", "fgh" };
char *argv_alt[] = { a[0], a[1], a[2], NULL };
argc = 3;
argv = argv_alt;
printf("%d '%s' '%s' '%s'\n", argc, argv[0], argv[1], argv[2]);
return 0;
}
Argv is allocated by the system when the user types in her arguments. If there wasn't arguments you cannot use the position 1 on that array. Although, as pointed out on the comments, you shouldn't do the way you are willing to, you could scanf arguments if you declare your own local variable.
The %s specifier in scanf expects that you pass in a pointer which points to space that has already been allocated and is big enough to hold whatever will be read.
Instead you pass in a pointer which points to an area where another pointer is stored. This causes undefined behaviour because the pointer you pass in has the wrong type.
It's not possible to extend the length of the argv array. In fact, writing to argv[n] probably causes undefined behaviour anyway.
Instead you should just read into a variable inside main.
I've built a C application, and when I build it, it shows no errors, but when I run it, it gives me the error "Segmentation Fault: 11".
If it helps, here is the code I am using:
#include <stdio.h>
int main(char *argv[]) {
printf("The project path is: ./Projects/%c", argv[1]);
return 0;
}
The correct main prototyped syntax is
int main(int argc, char *argv[]) { ... }
Also %c conversion specification in printf prints a character, to print a string use %s.
You have a number of problems:
The signature for main is an argument count followed by an array of C strings.
You should always check the count before using the array.
The array is of strings so you need %s to print them.
This should work:
#include <stdio.h>
int main(int argc, char *argv[]) {
if (argc < 2)
fprintf (stderr, "Wrong number of arguments\n");
else
printf ("The project path is: ./Projects/%s\n", argv[1]);
return 0;
}
Change the signature to int main(int, char*[]);
What arguments are you passing to the process? If you're not passing any argv[1] is out of range
In addition to the other suggestions, you may need to revisit your printf format. %c is used to print a single character, and argv[1] is char *. Either use argv[1][0] or some such, or use the string format specifier, %s.
First, change your main to:
int main(int argc, char *argv[])
Second, you have a mismatch between what you're passing to printf, and what you've told it you're going to pass. argv[1] is a pointer to characters, not a character. You need/want to use the %s conversion to print it out:
printf("The project path is: ./Projects/%s", argv[1]);
In this specific case, it's not really mandatory to check for enough arguments, because even if you don't pass any command line arguments, argv will contain at least argv[0] followed by a null pointer. As such, using argv[1] is safe, but if you haven't passed a command line argument, may print as something like (null).
Nonetheless, you generally want to check the value of argc before using argv. In this case, you can get away with it, but only more or less by accident. Trying to use argv[2] the same way could give undefined behavior.