reading from an input line with "" - c

I have this program that is supposed to read a line e.g post "nice job" john and i want to get every token in that line but for some reason i only get some of them.
Expected output:
post
nice job
john
My output:
post
nice
im sure im putting the correct format on sscanf so whats the problem i dont get why it doenst consider "nice job" as one word.
Program:
#include <stdio.h>
int main()
{
char token1[128];
char token2[128];
char token3[128];
char str[] = "post \"nice job\" john";
sscanf(str,"%s \"%s\" %s",token1,token2,token3);
puts(token1);
puts(token2);
puts(token3);
return(0);
}

The second %s reads "nice" because %s stops at the first whitespace. The format string then demands a match for a " quote, which isn't next (a space is next). The scanf functions don't skip input until a match is found, they stall. Always check the return value which should have been 3.
This code
#include <stdio.h>
int main()
{
char token1[128] = "";
char token2[128] = "";
char token3[128] = "";
char str[] = "post \"nice job\" john";
int res = sscanf(str, "%s \"%[^\"]\"%s", token1, token2, token3);
printf("%d\n", res);
puts(token1);
puts(token2);
puts(token3);
return(0);
}
outputs
3
post
nice job
john

Related

turning an array into a variable number of arguments

In pseudo code, I want put an arbitrary number of arguments to printf depending on the length of the argv, where the argv[1] is the format string.
int main(int argc, char *argv[]) {
printf(argv[1], argv[2], ...);
}
Uses can call the program as ./prog "%s %s" a b, ./prog "%s %s %s" a b c, and so on.
Could anybody let me know how to achieve this in C?
You need a loop for this:
int main(int argc, char *argv[])
{
int i;
for (i=1;i<argc;i++) {
printf("%s", argv[i]);
}
}
Here's something I just hacked together right now, it does does minimal parsing of the string and leaves most of it up to printf. It should also work with any number of arguments. Of course, since arguments are passed as char *s through the command line, this will only work with %s and its variants (and %%, but not sure if that counts as a format specifier).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
if (argc < 2)
{
fprintf(stderr, "Usage: %s <format string>[ <args>]\n", argv[0]);
return 1;
}
// These pointers will constantly jump from format spec. to format spec.
char *last_fmt = argv[1], *next_fmt, *next_next_fmt;
char *buf = NULL; // a buffer to hold a substring of argv[1]
unsigned i = 2; // Used to iterate over argv[2+]
while (1)
{
next_fmt = last_fmt - 2;
do
{
if ((next_fmt = strchr(next_fmt + 2, '%')) == NULL)
{
/* Your compiler may warn about this line specifically (it did for me),
but rest assured that there are indeed no format specifiers
here really, printf is just needed for printing "%%"s as "%"s */
printf(last_fmt);
return 0;
}
} while (next_fmt[1] == '%');
next_next_fmt = next_fmt - 1;
do
{
if ((next_next_fmt = strchr(next_next_fmt + 2, '%')) == NULL)
{
printf(last_fmt == argv[1] ? last_fmt : next_fmt,
argv[i]);
return 0;
}
} while (next_next_fmt[1] == '%');
buf = malloc(next_next_fmt - last_fmt + 1);
memcpy(buf, last_fmt, next_next_fmt - last_fmt);
buf[next_next_fmt - last_fmt] = '\0';
printf(buf, argv[i]);
free(buf);
++i;
last_fmt = next_next_fmt;
}
}
An example of running:
./a.out "Hello %.2s World! %s" "foo" "bar"
Hello fo World! bar
./a.out "Hello %10s World!" "foo" "bar"
Hello foo World!
./a.out "Hello %5.2s World!" "random"
Hello ra World!
./a.out
Usage: ./a.out <format string>[ <args>]
./a.out "Hello %%s World %s" "a"
Hello %s World a
./a.out "%s %s %s" "a" "b" "c"
a b c
You could build upon this yourself, but if you want to handle other format specifiers, you'll have to do actual parsing of the string. At that point, you would basically be creating another printf.
You also might be a bit worried about the use of a not-string-literal passed to printf, but this is safe. There is guaranteed to be exactly 1 format specifier in each place I use printf (except in the first do loop, but there it is guaranteed to not have any arguments).
how to achieve this in C?
C language does not have reflection. You can't "dynamically create function calls" or inspect and then change your own source code. You have to know at compilation time how many arguments you are passing to a function. While it is simple to do printf("%s %s", "a", "b) inside C language, if you pass the same data to a program that was written in C language you have parse the data and write the logic yourself.
Such parser would take the string "%s %s" find the %s sequences and replace them for the string "a" and "b" and also print the space in between, etc. That parser has to be written in C and is basically a duplication of what printf program (not printf() C function) does. You may want to read some implementations of printf program: ex. coreutils printf.c or freebsd printf.c.
This isn't a great idea to begin with, it will be super-vulnerable to all manner of exploits, typos and bugs. But if you insist, you could do a dirty hack as follows:
Assuming the format string in argv[1] is %s %s %s, then each we can divide this string length by 3 to get the number of strings. Save for the final one, which isn't followed by a trailing space. So strlen(argv[1]) + 1 then divide by 3:
#define STR_N ((strlen(argv[1])+1)/3)
Next up we can take advantage of printf ignoring trailing arguments not corresponding to the format string. So we could do printf(argv[1], argv[2], argv[3]); just fine without actually passing that many arguments, long as the format string contains the correct amount of conversion specifiers. For example:
#define ARGV_LIST \
argv[2],\
argv[3],\
argv[4],\
argv[5],\
argv[6],\
argv[7],\
argv[8],\
argv[9]\
printf(argv[1], ARGV_LIST);
Then cook up something to convert the indices and make sure that array out of bounds never occurs:
#include <stdio.h>
#include <string.h>
#define STR_N ((strlen(argv[1])+1)/3)
#define INDEX(n) (STR_N>n? (n+2) : 0)
#define ARGV_LIST \
argv[INDEX(0)],\
argv[INDEX(1)],\
argv[INDEX(2)],\
argv[INDEX(3)],\
argv[INDEX(4)],\
argv[INDEX(5)],\
argv[INDEX(6)],\
argv[INDEX(7)],\
argv[INDEX(8)],\
argv[INDEX(9)]\
int main(int argc, char *argv[])
{
printf(argv[1], ARGV_LIST);
return 0;
}
Tested in Windows with prog.exe "%s %s %s %s %s" hello this is a test gives output:
hello this is a test

pointers not read correctly

I am trying to get name of the input, output, and data files from the array for further processing. However, I am getting a weird error or problem. So, my program is not reaching the for loop. It does not even print the statement before the for loop. However, I tried using the debugger and the program is correctly printing step by step. So, when I run it does not print and when I debug step by step it prints. That is Weird!
char *method;
method=malloc(25);
method=NULL;
char *dataFileName;
char *inputMethod;
inputMethod=malloc(25);
inputMethod=NULL;
char *inputFileName;
char *outputMethod;
outputMethod=malloc(25);
outputMethod=NULL;
char *outputFileName;
char *commandArray[]={"if=q.txt","of=output.txt"};
char**args=(char**) malloc(sizeof(char*)*256);
args=commandArray;
int i;
printf("Before second for");
for(i=0;i<2;i++)
{
printf("I am here");
if(*args[i]=='d')
{
method=strtok_r(args[i],"=",&dataFileName);
printf("The method given is %s",method);
printf("Data File Name is %s",dataFileName);
}
else if(*args[i]=='o')
{
outputMethod=strtok_r(args[i],"=",&outputFileName);
printf("The output method given is %s",outputMethod);
printf("output File Name is %s",outputFileName);
}
else
{
inputMethod=strtok_r(args[i],"=",&inputFileName);
printf("The input method given is %s",inputMethod);
printf("Input File Name is %s",inputFileName);
}
}
if(method==NULL)
{
dataFileName=malloc(256);
printf("Please Enter A File Name");
scanf("%255s",dataFileName);
printf("%s",dataFileName);
}
if((inputMethod==NULL)||(outputMethod==NULL) )
{
char* array[]={"stdin","stdout"};
if(inputMethod==NULL)
inputMethod=array[0];
if(outputMethod==NULL)
outputMethod=array[1];
}
I am developing using Netbeans in C. The above code is written inside main. Thanks!
i intentionally left the previous answer because understanding memory allocation is trivial in programming in c specially. and as i see you have a big issue with that.
but still you have issue in nearly every thing. in my actual answer, i will try to simplify you how to use strtok, to split string and parse it. i guess this is the second main problem with your code.
the code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
char commandArray[][256]={
"if=q.txt",
"of=output.txt"
};
char infile[256], outfile[256];
for(int i=0; i<2;i++){
char *ptr,*cmd;
cmd=commandArray[i];
ptr=NULL;
printf("parsing command '%s'\n",cmd);
cmd=strtok(cmd,"=");
ptr=strtok(NULL,"=");
if(!cmd){
printf("Error parsing the string '%s'\n",commandArray[i]);
exit(1);
}
if (strcmp(cmd,"if")==0){
strcpy(infile,ptr);
}
else if (strcmp(cmd,"of")==0){
strcpy(outfile,ptr);
}
else{
printf("unknow token '%s'\n",cmd);
exit(1);
}
}
printf(
"\n\n"
"input file: '%s'\n"
"output file: '%s'\n"
"\n\n",
infile,outfile);
return 0;
}
the main problem is this:
char *method;
method=malloc(25);//allocating space for 25 char
method=NULL; // throwing up the allocation without freeing it;
// now the allocation is lost
// now method is useless (it is null)

Basic script in C (String display)

I'm trying to create a simple script on my server, basically I would like to sent a string and display it via system function...
#include <stdio.h>
int main()
{
char txt[100];
printf("Insert a text: ");
fgets(txt, 100, stdin);
system("echo %s"), txt;
return 0;
}
Rght now I'm not getting any string just "%s"
any idea why?
system("echo %s"), txt;
This isn't doing what you think; it's an expression which evaluates to txt. Since evaluating txt has no side effects, and since you're not capturing the result of the expression anywhere, adding , txt after the system call essentially does nothing. See this question for some information on the "comma"-operator in C.
Moreover, system doesn't support the use of printf-style format specifiers, so the %s in your string literal doesn't have any special meaning; it's just going to be echoed exactly as written, as you've seen. If you want to construct a command at runtime for use with system, you will have to do so with sprintf or similar.
The prototype to system() is:
int system(const char * command);
From man 3 system:
executes the shell command specified in command
From this we can safely assume s refers to a C-"string".
So prepare the string using for example snprintf():
char s[1024];
snprintf(s, 1024 -1, "echo %s", txt); /* -1 for the C-"string"'s 0-terminator */
Then pass it:
system(s);
Instead of system("echo %s"), txt; try this:
printf("%s", txt);
the system statement will not format the output, like printf.
suggest using:
#include <stdio.h>
#include <stdlib.h> // system()
#include <string.h> // strcpy(), strcat()
#define BUF_LEN (100)
int main()
{
char output[10+BUF_LEN] = "echo ";
char txt[BUF_LEN] = {'\0'};
printf("Insert a text: ");
fgets(txt, BUF_LEN, stdin);
strcat( output, txt );
system( output );
return 0;
}
The above code works very nicely, however;
do not include any command separators, semicolons, or other characters that would be interpreted by the shell in the input string.

Copy string to clipboard in c

First of all, I know there is a question with an identical name, however it deals with c++ and not c.
Is there any way to set a string to the clipboard in c?
This is the mentioned question if anyone is curious, even though it is for windows.
I need it to be in c because I am writing a program in c, and I would like to copy a string to the clipboard.
printf("Welcome! Please enter a sentence to begin.\n> ");
fgets(sentence, ARR_MAX, stdin);
//scan in sentence
int i;
char command[ARR_MAX + 25] = {0};
strncat(command, "echo '",6);
strncat(command, sentence, strlen(sentence));
strncat(command, "' | pbcopy",11);
command[ARR_MAX + 24] = '\0';
i = system(command); // Executes echo 'string' | pbcopy
The above code is saving 2 new lines in addition to the string. ARR_MAX is 300.
you tagged your question for osx. so this should be sufficient:
https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/PasteboardGuide106/Articles/pbCopying.html#//apple_ref/doc/uid/TP40008102-SW1
however there is the problem of having to call non-native c. Whether this is directly possible I don`t know.
if you can accept some hacky behavior you could invoke the pbcopy command.
http://osxdaily.com/2007/03/05/manipulating-the-clipboard-from-the-command-line/
this would be very easy to implement. here is a short function which should copy to clipboard. But I dont have osx handy so cannot test myself
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int copytoclipboard(const char *str) {
const char proto_cmd[] = "echo '%s' | pbcopy";
char cmd[strlen(str) + strlen(proto_cmd) - 1]; // -2 to remove the length of %s in proto cmd and + 1 for null terminator = -1
sprintf(cmd ,proto_cmd, str);
return system(cmd);
}
int main()
{
copytoclipboard("copy this to clipboard");
exit(0);
}

C - Replacing words

My goal here is to read text from a file redirected from stdin, then replace certain argv passed words with the word "Replaced".
For example, if I run:
$ ./a.exe line < input.txt
where input.txt is "Test line one", at the end I should print "Test Replaced one."
I'm not quite sure where my code is going wrong, sometimes I get segmentation fault, and I'm also not sure how I would go about printing the newOut string, or if I even need one.
As a side note, if I was reading using fgets, what if the 59th character started "li" then as it started reading again as the 0th index for the next read command, "ne". Wouldn't that not count as one string for strstr to search?
Any help is appreciated, thanks
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv) {
char fileRead[60];
char newOut[];
while (!feof(stdin)){
fgets(fileRead,60,stdin); //read file 60 characters at a time
if (strstr(fileRead,argv[1])){ // if argumentv[1] is contained in fileRead
strncpy(newOut, fileRead, strlen(argv[1])); // replace
}
}
return (0);
}
As I observed in the comments to your previous question, C — A better method for replacing:
An obvious suggestion is to read whole lines with fgets() and then search those (maybe with strstr()) to find the word to be replaced, and then print the material before the word and the replacement text before resuming the search from after the matched word in the line (so [given "test" as argv[1]] a line containing "testing, 1, 2, 3, tested!" ends up as "Replaced!ing, 1, 2, 3, Replaced!ed!".
This is a rather straight-forward implementation of the described algorithm.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
assert(argc > 1);
char fileRead[4096]; /* Show me a desktop computer where this causes trouble! */
char replace[] = "Replaced!";
size_t word_len = strlen(argv[1]);
while (fgets(fileRead, sizeof(fileRead), stdin) != 0)
{
char *start = fileRead;
char *word_at;
while ((word_at = strstr(start, argv[1])) != 0)
{
printf("%.*s%s", (int)(word_at - start), start, replace);
start = word_at + word_len;
}
printf("%s", start);
}
return (0);
}
Note that the position of the assert() makes this C99 code; place it after the definition of word_len and it becomes C89 code.

Resources