Specifically, I am trying to build up the following statement and run it as the following command:
system("java -cp . mainpackage.SomeClass 1234567890 98765");
I have researched this online, but the examples did not compile, so I pieced together the following illustrative pseudo code. How do I change the code below to get it to concatenate the string and execute the command?
#include <stdio.h>
main() {
char jv[33];
strcpy(jv, "java -cp . mainpackage.SomeClass ");
char to[10];
strcpy(to, "1234567890 ");
char pin[5];
strcpy(pin, "98765");
system(jv + to + pin);
}
to and pin are arguments sent to a java program. Eventually, to and pin will be coming from inputs, but for now I just want to treat them as these values while I test other pieces of the code.
snprintf() is a flexible and a safe method. #fukanchik. The main challenge in C is to:
1) manage string memory space and
2) prevent overruns.
const char *jv = "java -cp . mainpackage.SomeClass ";
const char *to = "1234567890 ";
const char *pin = "98765";
#define BIGBUF 100
char command[BIGBUF];
snprintf(command, sizeof command, "%s%s%s", jv, to, pin);
system(command);
Or with C99 and assuming integers
const char *jv = "java -cp . mainpackage.SomeClass";
long to = 1234567890;
long pin = 98765;
int n = snprintf(NULL, 0, "%s %ld %ld", jv, to, pin);
char command[n+1];
snprintf(command, sizeof command, "%s %ld %ld", jv, to, pin);
system(command);
From an actual command line, like int main (int argc, char **argv)
char buf[1024] = {0};
int n;
for (n = 0; n < argc; n ++)
strcat (buf, argv[n]); // Change to strlcat if you have it available (BSD or Mac)
printf ("result = %s\n", buf);
Or using your example:
char jv[33];
strcpy(jv, "java -cp . mainpackage.SomeClass ");
char to[10];
strcpy(to, "1234567890 ");
char pin[5];
strcpy(pin, "98765");
system(jv + to + pin);
char result[1024] = {0}; // C does not zero format variables inside a function, so we do it ourselves with = {0}
sprintf (result, "%s %s %s", jv, to, pin); // Should use snprintf instead if available
printf ("result = %s\n", result);
OR
char result[1024] = {0};
strcat (result, jv);
strcat (result, " ");
strcat (result, to);
strcat (result, " ");
strcat (result, pin); // Should use strlcat instead if available
printf ("result = %s\n", result);
First, let me tell you the mistakes in above code.
char jv[33];
strcpy(jv, "java -cp . mainpackage.SomeClass ");
in C, strings are null-terminated, so you'll be needing an extra element per string to store the null. Expand the size of your array.
The, for concatenation like
system(jv + to + pin);
you can define an array large enough to hold the concatenated final value and use strcat() to concatenate the source and destination string. You can use a loop, to append more than one sub-string to make a complete command-string, as you want.
Related
#include<stdio.h>
#include<string.h>
int main()
{
char pch[]="encrypt galvin;double royal;";
char *str=pch;
char *ptr;
//pch = strtok (dir,";");
while ((ptr =strtok_r(str,";",&str))){
printf("%s\n",ptr);
char *token=ptr;
char *en;
char cwd[524];
while((en =strtok_r(token," ",&token))){
// char *gal = strtok(NULL," ");
strcpy(cwd,token);
if (strcmp(token,"double")==0) {
strcat(cwd,cwd);
printf("Double %s Done.\n", cwd);
}
//printf("%s\n,gal");
}
}
return 0;
}
Above is my code. but i tried running it for several times it's not doing what i want. I'm asking for your help.
I want to make that code where by if an array pch has got several commands it splits them into into single commands e.g.
encrypt galvin
double galvin
After doing that it splits those commands into substrings e.g.
encrypt galvin
further split into encrypt followed by
galvin and similarly to the other task.
Then after that the if startment must compare if the string in the split substrings is encrypt. if it confirms then it would pick the second string from the split string (encrypt galvin) that is galvin then it wrks on it. For example above in my code I only used a double command so when it goes to a string double galvin it picks it, also splits it and picks the word double and compares it. Then if it's the one then it goes further to pick the word galvin and it doubles it thus returning galvingalvin as the output. so am kindly requesting for your support
This line produces undefined behavior:
strcat(cwd, cwd);
because the source and destination are not allowed to overlap. You can make a copy of cwd so you can concatenate it.
char cwd2[524];
strcpy(cwd2, cwd);
strcat(cwd, cwd2);
You're not using strtok_r() correctly. The first call to strtok_r() in a loop passes a pointer to the string being parsed as the first argument, and a pointer to some other pointer as the third argument. When you repeat these calls in the loop, the first argument should be NULL -- that tells strtok_r() that you want to continue parsing the same string.
And the pointer to the token is the value returned from the function, not the third argument.
After you find the word double, you need to read the next token to get the word that should be doubled. Your code is doubling the current word, which is just double.
Here's the corrected code.
#include<stdio.h>
#include<string.h>
int main()
{
char pch[]="encrypt galvin;double royal;";
char *cmd;
char *ptr;
//pch = strtok (dir,";");
for (cmd = strtok_r(pch,";",&ptr); cmd; cmd = strtok_r(NULL, ";", &ptr)) {
printf("%s\n",cmd);
char *word;
char *ptr2;
char cwd[524];
for (word = strtok_r(cmd, " ", &ptr2); word; word = strtok_r(NULL, " ", &ptr2)) {
if (strcmp(word,"double")==0) {
char *word2 = strtok_r(NULL, " ", &ptr2);
strcpy(cwd, word2);
strcat(cwd, word2);
printf("Double %s Done.\n", cwd);
}
}
}
return 0;
}
my code would work in this way:
input : a[]="create /dir/bar"
and save in this string:
b[]=create
c[]=/dir/bar
there is also a case in which i save an other string: (for example)
a[]=write /foo/bar "test"
b[]= write
c[]=/foo/bar
d[]=test (without the "")
my code is this :
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define SPACE ' '
void divide(char a[], char b[], char c[], char d[]);
int main(int argc, char const *argv[]) {
char a[50+1];
char b[50+1];
char c[50+1];
char d[50+1];
int i;
scanf("%s\n", a);
divide(a, b, c, d);
for(i=0; b[i]!='\0'; i++)
printf("%s %s %s \n", b, c, d);
return 0;
}
void divide(char a[], char b[], char c[], char d[]){
int i, j;
for(i=0; a[i]!=SPACE; i++)
b[i]=a[i];
b[i]='\0';
for(; a[i]==SPACE; i++)
;
for(j=0; a[i]!='\0'; i++, j++)
c[j]=a[i];
c[j]='\0';
for(; a[i]==SPACE; i++)
;
if(a[i]=='"'){
i++;
for(j=0; a[i]!='"'; i++)
d[j]=a[i];
d[j]='\0';
return;
}
}
but it does not work for a segmentation fault after the program get the input. where is the problem?
I must not use malloc, because it spend too much time to work (I have to get thousands of these lines) and does not respect a limit. (I work for a project in my university)
You may be making this a little more difficult than it needs to be. Yes, you can tokenize a string by repeated calls to sscanf or with repeated reads with scanf, but the C library provides a tool to tokenize words from a line of text. Smartly enough named strtok.
You simply declare a constant string holding the delimiters you wish to break the words on (e.g. delims = " \t"; to break the words on space or tab, and then call strtok (str, delims) to return the first token (word), and then loop over repeated calls to strtok (NULL, delims) to parse the remaining words (or until you reach your max of 3 words).
(note the first call to strtok uses str as the first parameter, while all subsequent calls use NULL)
This is a far more flexible way to handle an unknown number of tokens in a string.
Instead of using a[], b[], c[], etc.. consider using just a single buf[] to read the line of input into, and then an array of strings to hold the parameters (which allows you to use an index variable during your loops over strtok to assign and copy the correct string to the associated index).
Don't use void as a return in circumstances like this. Why not use a meaningful return (like the number of parameters in the line of text). That way, you know how many were read (or tokenized) in your divide function. Give it a return that can provide useful information, e.g.
size_t divide (char *buf, char (*params)[MAXC+1]);
Which will now return a size_t type containing the number of parameters that result from each call to divide.
Putting it altogether, (and using fgets to read the entire line of input), you could do something like the following:
#include <stdio.h>
#include <string.h>
enum { MAXP = 3, MAXC = 50 }; /* max parameters & chars */
size_t divide (char *buf, char (*params)[MAXC+1]);
int main (void) {
char buf[MAXC * 4 + 1] = "";
char params[MAXP][MAXC + 1]; /* array to hold 3 parameters */
size_t i, len, nparams = 0;
/* use fgets for line-oriented user input */
printf ("\nenter commands: ");
if (!fgets (buf, sizeof buf, stdin)) {
fprintf (stderr, "error: insufficient input.\n");
return 1;
}
len = strlen (buf); /* get length */
if (buf[len - 1] == '\n') /* validate last char is '\n' */
buf[--len] = 0; /* overwrite with nul-terminating char */
else { /* short read -- handle error */
fprintf (stderr, "error: incomplete input read.\n");
return 1;
}
nparams = divide (buf, params);
for (i = 0; i < nparams; i++)
printf ("parameter[%zu] : %s\n", i, params[i]);
return 0;
}
/* divide using strtok */
size_t divide (char *buf, char (*params)[MAXC+1])
{
char *delims = " \t", /* delimiters for strtok */
*p = buf; /* pointer to buf */
size_t n = 0; /* var to return number of params */
p = strtok (buf, delims); /* tokenize fist paramter */
while (p) { /* now loop until all words exhausted or limit reached */
strncpy (params[n++], p, MAXC); /* copy token to params array */
if (n == MAXP) /* check if limit reached */
break;
p = strtok (NULL, delims); /* get next token */
}
return n; /* return the number of parameters found */
}
Example Use/Output
$ /bin/splitparams
enter commands: create /dir/bar
parameter[0] : create
parameter[1] : /dir/bar
$ ./bin/splitparams
enter commands: write /foo/bar "test"
parameter[0] : write
parameter[1] : /foo/bar
parameter[2] : "test"
Or providing a bunch of extra words (to validate handling of only 3)
$ ./bin/splitparams
enter commands: write /foo/bar "test" and some more stuff
parameter[0] : write
parameter[1] : /foo/bar
parameter[2] : "test"
If you run this simple program
#include<stdio.h>
int main(int argc, char const *argv[]) {
char a[50+1];
scanf("%s\n", a);
printf("|%s|\n", a);
return 0;
}
and give the input "create foo", you'll get the output
|create|
As you can see you only got the first word, i.e. "create", instead of the expected "create foo" as
scanf("%s\n", a);
will only give the first word. Consequently your divide function will fail. Instead of scanf you could do
fgets(a, 51, stdin);
to make sure the whole input is read into array a.
In general your program lacks a lot of range checking and input validation. You should add that.
Another problem I see is that in case the input is
create /dir/bar
you never initialize the string d but you still print it in main. That is undefined behaviour.
Try:
char d[50+1];
d[0] = '\0'; // Add this line
I'm trying to scanf words and numbers from a string looks like: "hello, world, I, 287876, 6.0" <-- this string is stored in a char array (string)
What I need to do is to split things up and assign them to different variables so it would be like
char a = "hello"
char b = "world"
char c = "I"
unsigned long d = 287876
float e = 6.0
I know that regular scanf stops reading from stdin when it reaches a white space. So I've been thinking that there might be a way to make sscanf stop reading when it reaches a "," (comma)
I've been exploring the library to find a format for sscanf to read only alphabet and numbers. I couldn't find such a thing, maybe I should look once more.
Any help?
Thanks in advance :)
If the order of your variables in the string is fixe, I mean It's always:
string, string, string, int, float
the use the following format specifier in sscanf():
int len = strlen(str);
char a[len];
char b[len];
char c[len];
unsigned long d;
float e;
sscanf(" %[^,] , %[^,] , %[^,] , %lu , %lf", a, b, c, &d, &e);
This example using strtok should be helpful:
#include <stdio.h>
#include <string.h>
int main ()
{
char str[] ="hello, world, I, 287876, 6.0" ;
char * pch;
printf ("Splitting string \"%s\" into tokens:\n",str);
pch = strtok (str,",");
while (pch != NULL)
{
printf ("%s\n",pch);
pch = strtok (NULL, ",");
}
return 0;
}
Assuming the format of the text file is constant you can use the following solution.
std::ifstream ifs("datacar.txt");
if(ifs)
{
std::string line;
while(std::getline(ifs,line))
{
/* optional to check number of items in a line*/
std::vector<std::string> row;
std::istringstream iss(line);
std::copy(
std::istream_iterator<std::string>(iss),
std::istream_iterator<std::string>(),
std::back_inserter(row)
);
/*To avoid parsing the first line and avoid any error in text file */
if(row.size()<=2)
continue;
std::string format = "%s %s %s %f %[^,] %d";
char year[line.size()],make[line.size()],three[line.size()],full[line.size()];
float numberf;
int numberi;
std::sscanf(line.c_str(),format.c_str(),&year,&make,&three,&numberf,&full,&numberi);
/* create your object and parse the next line*/
}
}
See the documentation for strtok and/or strtok_r
see
char str[] = "hello world";
printf("%s",str);
printf statement prints the all character in string before reaching '\0'
so what if i want to print just 4 1st character of str on stdout?
You can just specify the field width in the printf format string:
#include <stdio.h>
int main(void)
{
const char *s = "Hello world !";
printf("%.4s\n", s);
return 0;
}
or, if you want to specify the field width at run-time:
#include <stdio.h>
int main(void)
{
const char *s = "Hello world !";
const int fw = 4;
printf("%.*s\n", fw, s);
return 0;
}
In either case the output will be:
Hell
You can use %c in your format string:
printf("%c", *s);
prints 'H'
To print an arbitrary char:
printf("%c", s[3]);
prints 'l'
For the first character, you can just use:
printf ("%c", *str); // or
printf ("%c", *(str+0)); // or
printf ("%c", str[0]);
For a different character, just reach out and grab it by using an offset. For the second l at offset 3:
printf ("%c", str[3]); // or
printf ("%c", *(str+3));
For a substring, you can use a combination of that method along with the maximum field width feature of printf:
printf ("%.2s", str+3); // prints "lo"
With all these solutions, you want to make sure you don't start on the wrong side of the null terminator. That wouldn't be a good thing :-)
If you want a generalised solution that will work for any string, and is relatively safe in terms of finding the starting point, you can use:
void outSubstr (FILE *fh, char *str, size_t start, size_t sz, int padOut) {
if (start >= strlen (str)) {
if (padOut)
fprintf (fh, "%*s", sz, "");
return;
}
if (padOut)
fprintf (fh, "%-*.*s", sz, sz, str + start);
else
fprintf (fh, "%-.*s", sz, str + start);
}
The parameters are as follows:
fh is the file handle to write to.
str is the start of the string.
start is the offset to start printing from.
sz is the maximum number of characters to print.
padOut is a flag indicating that sz is also the minimum size. Output will be padded with spaces on the right if there are not enough characters in the string to satisfy the size.
This will print up to 4 characters.
printf("%.4s", str);
there is also a "substr()" function
that return the substring from complete string.
example
printf("%s",substr(str,0,4));
it has syntax like this
substr(arrayName,charStartingPosition, lengthOfCharacters);
i hope this is easy to understand and no need to write more than 1 statement.
Really less painful for the system :
int main(void)
{
char c;
c = 'z';
write(1, &c, 1);
}
No need for heavy stdio here
Then you can ...
char *s = "Hello, World!";
write(1, s, numberOfChars);
Or if you really want to do it char by char:
void printnchars(char *s, int n)
{
int i;
i = 0;
while (i <= n)
{
write(1, s + i, 1);
i++;
}
}
numOfChars = 4;
printf("%.*s\n", numOfChars, "Hello, world!");
Where numOfChars is the quantity of characters that you want to print.
Please help me with my code. I am using the system() function in c. Let's say I want to make a new directory using C code.
char name[];
printf("Enter the name of directory: ");
scanf("%s", &name);
Then using system(), I want to use the variable name[]
instead of using or putting a fixed value like system("mkdir ryan"); which makes a new directory ryan; what I want to happen is that, to create any name of directory and store it to variable name[] and implement that value instead of ryan. Your answers are highly appreciated.
You should be using something like:
char name[100];
printf("Enter the name of the directory: ");
if (scanf("%99s", name) == 1) // Not &name
{
char command[120];
sprintf("%s %s", "mkdir", name);
if (system(command) != 0)
...oops...
}
First off (and this probably doesn't matter if your code is just an example), don't ever use an unbounded %s scanf - that opens you up to buffer overflows.
If you have a string like:
char name[] = "paxdiablo";
you can just use that to construct your own string for execution.
char cmd[1000];
strcpy (cmd, "mkdir ");
strcat (cmd, name);
system (cmd);
And make sure you know (or check with strlen, or dynamically allocate the buffer so it's big enough) the size of name so that you don't end up with a buffer overflow there as well.
An example of the dynamic allocation one:
void tryMkdir (char *dir) {
static char prefix[] = "mkdir ";
// Use sizeof to allow for null char at end.
char *cmd = malloc (sizeof (prefix) + strlen (dir));
if (cmd != NULL) {
strcpy (cmd, prefix);
strcat (cmd, dir);
system (cmd);
free (cmd);
}
}
(although you'd probably want some error checking in there in case the mkdir or malloc failed).
here is an example of how it could be implemented:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
int main() {
char *dirname = NULL;
char *cmdline = NULL;
size_t len;
size_t dirlen = 0;
int rv = 0;
printf("Enter directory: ");
if ( (len = getline(&dirname, &dirlen, stdin)) < 0) {
perror("getline");
exit(-1);
}
dirname[len-1] = 0;
cmdline = malloc(len+8);
snprintf(cmdline, dirlen+8, "mkdir %s", dirname);
rv = system(cmdline);
free(cmdline);
free(dirname);
rv = WEXITSTATUS(rv);
return rv;
}
You'll need to build up a string w/ your full command to send to system() in it, which means allocating space for it (which you didn't do for name in your original code, so that your call to scanf would likely fail). For something like your mkdir example, you could create a string that starts with mkdir & has enough room after that for your directory name, and when you call scanf, point it to the location within that string you want the name to go; saves you having to do a strcat or somesuch afterward, and if this is the only thing you need the directory name for, why store it twice?
Try:
char command[80];
strcpy(command, "mkdir ");
strcat(command, name);
system(command);