Printing 2D array in C language using system ECHO command [duplicate] - c

This question already has answers here:
Using scalar variable or a pointer to print 2D array
(4 answers)
Closed 6 years ago.
How do I execute the system command “echo” in a C program to print out all the elements in a 2D array? I tried it, but it didn't work.
Input:
char myarray[1][10] = {"Hello", "World"};
system("echo $myarray");
Expected Output:
Hello World
Currently I do not get any output whatsoever.
Update 1 (constraints):
I cannot allocate more memory – I can only use the myarray variable.
I may use any other scalar or pointer variables.

You need to build the whole command in a single string before calling system. Something like:
char myarray[2][10] = {"Hello", "World"};
// ^ notice
char mycommand[42];
strcpy(mycommand, "echo \"");
strcat(mycommand, myarray[0]);
strcat(mycommand, " ");
strcat(mycommand, myarray[1]);
strcat(mycommand, "\"");
system(mycommand);

I'm assuming this is on a Linux machine, not Windows!
The system command echo takes as a parameter what you want it to print out. So you'd think that
echo $myArray
would print out
$myArray
but it doesn't. The $ means "Look up the following string in the list of environment variables and print that". And myArray isn't defined in your list of environment variables, so it prints out nothing. It definitely won't print out a variable inside your computer program!
If you changed the call to
system("echo $path");
you would get a long string printed out, listing a number of directories. That's your current path.
But none of that answers your problem. What you want to do is print out Hello World using the echo command. That means that you need to (effectively) call the system() function with the following argument:
system("echo Hello world");
The only way you can do that is to "construct" the string that you want it to print out, and then tell system() the complete string.
So you need something like the following:
#define NUMSTRINGS 2 // Note that there are 2 strings!
char myArray[NUMSTRINGS][10] = {"Hello", "world"};
char command[256] = "echo"; // Start command
int i;
for (i=0; i<NUMSTRINGS; ++i) {
strcat(command, " "); // Space separator
strcat(command, myArray[i]); // Next string
} // for
system(command);

This will not work, because myarray is a variable in C, and $myarray is an environment variable in the shell. They have no relation to one another--just as "Reading, England" and "Reading the news" have no relation.
If you want to pass variables to the shell, you can try setenv().

Related

Output system() in C on one line

I have been trying for hours to create a program that outputs something like command[/home/nerdofcode/]: by running something like:
printf("Command[", system("pwd"),"]: ");...
But the problem I am receiving is that when I go to type input, it starts typing at command[... and then once I click enter, it finally outputs the system("pwd");...
Technical Info
I am using the system() function to execute a system command on Linux.
To use printf correctly for a null-terminated string you need to change the parameters:
printf("Command[%s]: ", string_with_result);
In order to get the string_with_result correctly, you need to study the way system() works in your environment. Its return value is implementation specific and therefor does not allow to answer with code which does what you want.
char * string_with_result; /* pointer to null-terminated sequence of char */
This is the declaration for the string result to be used in printf as proposed above.
In case you want to just get the result, but do not insist on using system() check this StackOverflow question and accepted answer:
'pwd' to get path to the current file
This Q/A might be the way on a "unix-ish" environment to actually use system(), it uses popen():
C: Run a System Command and Get Output?
printf does not work as a "concat" operation of comma separated strings. It rather has a format string with placeholders and the arguments for the placeholders.
So you could write:
char *s1 = "hello", *s2 = "world";
printf("%s %s", s1, s2);
But the following code will not concat the both strings; it will rather treat s1 as a format string (without placeholders) and will ignore the argument:
char *s1 = "hello", *s2 = "world";
printf(s1, s2);
Note further that int system(const char* cmd) does not return a string, which you could use in printf then, at all. So I'd recommend to write.
printf("Command[");
system("pwd");
printf("]: ");
This should work on console as long as system-command and your programsstdout` target the same output stream.

**argv contain a lot of characters than expected

First, I need to execute two commands with system(), for example, I receive an string and open this string with an text editor, like this:
$ ./myprogram string1
And the output should be a command like this:
$ vim string1
But, I cannot find a way to do this like this pseudo code:
system("vim %s",argv[1]); //Error:
test.c:23:3: error: too many arguments to function 'system'
system("vim %s",argv[1]);
Therefore, my solution is store the argv[1] on a char array that already initialized with four characters, like this:
char command[strlen(argv[1])+4];
command[0] = 'v'; command [1] = 'i'; command[2] = 'm'; command[3] = ' ';
And assign the argv[1] to my new char array:
for(int i = 0; i < strlen(argv[1]) ; i++)
command[i+4] = argv[1][i];
And finally:
system(command);
But, if the arguments given to my program has less than 3 characters, its works fine, but if not, some weird characters that I do not expect appear in the output, like this:
./myprogramg 1234
And the output is:
$ vim 12348�M�
How can I solve this bug and why does this happen?
The full code is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc,char **argv) {
char command[strlen(argv[1])+4];
command[0] = 'v'; command [1] = 'i'; command[2] = 'm'; command[3] = ' ';
for(int i = 0; i < strlen(argv[1]) ; i++)
command[i+4] = argv[1][i];
system(command);
return 0;
}
You need to NUL terminate your C-style strings, and that includes allocating enough memory to hold the NUL.
Your array is a byte short (must be char command[strlen(argv[1])+4+1]; to leave space for NUL), and you should probably just use something like sprintf to fill it in, e.g.:
sprintf(command, "vim %s", argv[1]);`
That's simpler than manual loops, and it also fills in the NUL for you.
The garbage you see is caused by the search for the NUL byte (which terminates the string) wandering off into unrelated (and undefined for that matter) memory that happens to occur after the buffer.
The reason you're running into problems is that you aren't terminating your command string with NULL. But you really want to use sprintf (or even better to use snprintf) for something like this. It works similarly to printf but outputs to memory instead of stdout and handles the terminating NULL for you. E.g:
char cmd[80];
snprintf(cmd, 80, "vim %s", argv[1])
system(cmd);
As #VTT points out, this simplified code assumes that the value in argv[1] will be less than 75 characters (80 minus 4 for "vim " minus 1 for the NULL character). One safer option would be to verify this assumption first and throw an error if it isn't the case. To be more flexible you could dynamically allocate the cmd buffer:
char *cmd = "vim ";
char *buf = malloc(strlen(argv[1]) + strlen(cmd) + 1);
sprintf(buf, "%s%s", cmd, argv[1]);
system(buf);
free(buf);
Of course you should also check to be sure argc > 1.
I know that there are already good answers here, but I'd like to expand them a little bit.
I often see this kind of code
system("vim %s",argv[1]); //Error:
and beginners often wonder, why that is not working.
The reason for that is that "%s", some_string is not a feature of the C
language, the sequence of characters %s has no special meaning, in fact it is
as meaningful as the sequence mickey mouse.
The reason why that works with printf (and the other members of the
printf-family) is because printf was designed to replace sequences like
%s with a value passed as an argument. It's printf which make %s special,
not the C language.
As you may have noticed, doing "hallo" + " world" doesn't do string
concatenation. C doesn't have a native string type that behaves like C++'s
std::string or Python's String. In C a string is just a sequence of
characters that happen to have a byte with value of 0 at the end (also called
the '\0'-terminating byte).
That's why you pass to printf a format as the first argument. It tells
printf that it should print character by character unless it finds a %,
which tells printf that the next character(s)1 is/are special and
must substitute them with the value passed as subsequent arguments to printf.
The %x are called conversion specifiers and the documentation of printf
will list all of them and how to use them.
Other functions like the scanf family use a similar strategy, but that doesn't
mean that all functions in C that expect strings, will work the same way. In
fact the vast majority of C functions that expect strings, do not work in that
way.
man system
#include <stdlib.h>
int system(const char *command);
Here you see that system is a function that expects one argument only.
That's why your compiler complains with a line like this: system("vim %s",argv[1]);.
That's where functions like sprintf or snprintf come in handy.
1If you take a look at the printf documentation you will see that
the conversion specifier together with length modifiers can be longer than 1
character.

How to pass this array of c strings correctly [duplicate]

This question already has answers here:
How do I pass this array of c strings correctly? [closed]
(3 answers)
Closed 9 years ago.
I already asked this question and did a very poor job posting it leading to confusing answers that did not help me solve my problem whatsoever. This time ill be trying harder to make my question easier to address. Here is the problem below...
int builtin_cmd(char **argv);
int main()
{
char *argv[128]; //create an array of c_strings with 128 slots in the array
//put 'quit' into argv[0].. (This was done by another file given to me by the professor)
printf("%s\n", argv[0]); //prints 'quit', as it should
builtin_cmd(argv); //call builtin_cmd and pass argv to the function
}
int builtin_cmd(char **argv)
{
printf("%s\n", argv[0]); //prints nothing, should have printed 'quit'
}
Basically the issue that I am having is accessing char *argv[128] in the function builtin_cmd. I set the first index in the array to the c_string 'quit' and print it right there and it works just as I expected it too the printf() prints out 'quit' in the terminal. However, once I call builtin_cmd(argv); the line printf("%s\n", argv[0]); prints absolutely nothing as if the argv was empty. How am i supposed to correctly pass argv into the function builtin_cmd?
It should work well except you forget to return values in builtin_cmd() and main(). Check out running result on Ideone .

How to pass command line arguements to my main function? [duplicate]

This question already has answers here:
What does int argc, char *argv[] mean?
(12 answers)
Closed 9 years ago.
So my main function looks like this:
int main(int numberOfArguments, char* argumentArray[]) {
if (assemble(numberOfArguments, argumentArray)) {
return 0;
} else {
return -1;
}
}
I want to be able to give to the command line the arguement
./program inputFile.txt outputFile.txt // PROBLEM IS that this is being interpreted as 3 command line arguments somehow when it is only 2.
where inputFile.txt is argumentArray[0] and outputFile.txt is argumentArray[1]
The generation of arguments from the text command line is platform-specific, but the first element of the argv array is almost always the name used to find your program.
If you want to discard this first argument, simply add to the beginning of main:
-- numberOfArguments;
++ argumentArray;
every word you type into the command line (beginning with the executable name) is passed to the main function at begin. related question
The first argument argumentArray[0] is the as readable in the realted question reserved.
After that you get each word (seperated by whitespaces in the commandline) as an element in the argumentArray.
The size of the argumentArray is given by numberOfArguments.
So if you insist on having your input file on [0] you should work with some pointer arithmetics like argumentArray++; otherwise you have the given data at [1] and [2] automatically.

Arguments to main in C [duplicate]

This question already has answers here:
Pass arguments into C program from command line
(6 answers)
Closed 6 years ago.
I don't know what to do! I have a great understanding of C basics. Structures, file IO, strings, etc. Everything but CLA. For some reason I cant grasp the concept. Any suggestions, help, or advice. PS I am a linux user
The signature of main is:
int main(int argc, char **argv);
argc refers to the number of command line arguments passed in, which includes the actual name of the program, as invoked by the user. argv contains the actual arguments, starting with index 1. Index 0 is the program name.
So, if you ran your program like this:
./program hello world
Then:
argc would be 3.
argv[0] would be "./program".
argv[1] would be "hello".
argv[2] would be "world".
Imagine it this way
*main() is also a function which is called by something else (like another FunctioN)
*the arguments to it is decided by the FunctioN
*the second argument is an array of strings
*the first argument is a number representing the number of strings
*do something with the strings
Maybe a example program woluld help.
int main(int argc,char *argv[])
{
printf("you entered in reverse order:\n");
while(argc--)
{
printf("%s\n",argv[argc]);
}
return 0;
}
it just prints everything you enter as args in reverse order but YOU should make new programs that do something more useful.
compile it (as say hello) run it from the terminal with the arguments like
./hello am i here
then try to modify it so that it tries to check if two strings are reverses of each other or not then you will need to check if argc parameter is exactly three if anything else print an error
if(argc!=3)/*3 because even the executables name string is on argc*/
{
printf("unexpected number of arguments\n");
return -1;
}
then check if argv[2] is the reverse of argv[1]
and print the result
./hello asdf fdsa
should output
they are exact reverses of each other
the best example is a file copy program try it it's like cp
cp file1 file2
cp is the first argument (argv[0] not argv[1]) and mostly you should ignore the first argument unless you need to reference or something
if you made the cp program you understood the main args really...
For parsing command line arguments on posix systems, the standard is to use the getopt() family of library routines to handle command line arguments.
A good reference is the GNU getopt manual
Siamore, I keep seeing everyone using the command line to compile programs. I use x11 terminal from ide via code::blocks, a gnu gcc compiler on my linux box. I have never compiled a program from command line. So Siamore, if I want the programs name to be cp, do I initialize argv[0]="cp"; Cp being a string literal. And anything going to stdout goes on the command line??? The example you gave me Siamore I understood! Even though the string you entered was a few words long, it was still only one arg. Because it was encased in double quotations. So arg[0], the prog name, is actually your string literal with a new line character?? So I understand why you use if(argc!=3) print error. Because the prog name = argv[0] and there are 2 more args after that, and anymore an error has occured. What other reason would I use that? I really think that my lack of understanding about how to compile from the command line or terminal is my reason for lack understanding in this area!! Siamore, you have helped me understand cla's much better! Still don't fully understand but I am not oblivious to the concept. I'm gonna learn to compile from the terminal then re-read what you wrote. I bet, then I will fully understand! With a little more help from you lol
<>
Code that I have not written myself, but from my book.
#include <stdio.h>
int main(int argc, char *argv[])
{
int i;
printf("The following arguments were passed to main(): ");
for(i=1; i<argc; i++) printf("%s ", argv[i]);
printf("\n");
return 0;
}
This is the output:
anthony#anthony:~\Documents/C_Programming/CLA$ ./CLA hey man
The follow arguments were passed to main(): hey man
anthony#anthony:~\Documents/C_Programming/CLA$ ./CLA hi how are you doing?
The follow arguments were passed to main(): hi how are you doing?
So argv is a table of string literals, and argc is the number of them. Now argv[0] is
the name of the program. So if I type ./CLA to run the program ./CLA is argv[0]. The above
program sets the command line to take an infinite amount of arguments. I can set them to
only take 3 or 4 if I wanted. Like one or your examples showed, Siamore... if(argc!=3) printf("Some error goes here");
Thank you Siamore, couldn't have done it without you! thanks to the rest of the post for their time and effort also!
PS in case there is a problem like this in the future...you never know lol the problem was because I was using the IDE
AKA Code::Blocks. If I were to run that program above it would print the path/directory of the program. Example: ~/Documents/C/CLA.c it has to be ran from the terminal and compiled using the command line. gcc -o CLA main.c and you must be in the directory of the file.
Main is just like any other function and argc and argv are just like any other function arguments, the difference is that main is called from C Runtime and it passes the argument to main, But C Runtime is defined in c library and you cannot modify it, So if we do execute program on shell or through some IDE, we need a mechanism to pass the argument to main function so that your main function can behave differently on the runtime depending on your parameters. The parameters are argc , which gives the number of arguments and argv which is pointer to array of pointers, which holds the value as strings, this way you can pass any number of arguments without restricting it, it's the other way of implementing var args.
Had made just a small change to #anthony code so we can get nicely formatted output with argument numbers and values. Somehow easier to read on output when you have multiple arguments:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("The following arguments were passed to main():\n");
printf("argnum \t value \n");
for (int i = 0; i<argc; i++) printf("%d \t %s \n", i, argv[i]);
printf("\n");
return 0;
}
And output is similar to:
The following arguments were passed to main():
0 D:\Projects\test\vcpp\bcppcomp1\Debug\bcppcomp.exe
1 -P
2 TestHostAttoshiba
3 _http._tcp
4 local
5 80
6 MyNewArgument
7 200.124.211.235
8 type=NewHost
9 test=yes
10 result=output

Resources