I am currently trying to get my program to work the way I want. I am currently at the point where I can open up any text file from the command line (an unlimited amount) and display them. I'd like to expand on this and have users enter phrases that format the displayed text. I have previously posted a similar question and I've gotten some great answers, but I cannot use getopt(). How else would it be possible to scan the command line for a "-w" and a number, so "-w5" and a "-s" with no number. Those are the only two things I'd like to be able to detect. I don't mind if statements, I was hoping for the shortest program in my friends, but at this point, I'd just like to get it done. Any ideas? Multiple if-statements was my friend's idea, I personally think this is unneeded, but if that's what I have to do... If anyone else has any ideas, that would be really useful. I just want my program to detect those two characters from the command line. I'm fairly new to C (I've only made a few programs), but I'm edger to learn and I have tried googling and trying this on my own, but being new to C, trying to find what I need through all the other text and jargon is difficult.
Anything will be useful, thanks.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int l = 1;
while(l != argc)
{
FILE *fp;
fp = fopen(argv[l], "rb");
l++;
if (fp != NULL)
{
int i = 1;
do
{
i = fgetc(fp);
printf("%c",i);
printf(" ");
}
while(i!=-1);
fclose(fp);
}
else
{
printf("Error.\n");
}
}
}
void scanningForWS(int argc, char **argv)
{
}
You should look at plan9's ARGBEGIN and ARGEND macros in their libc.h file (at the very end of the file), to see how it's done (for an example of its usage, see arg(3)).
Alernatively, you can check the suckless implementation of this mechanism, which is very nice (I have re-implemented a version of it which parses arguments even after incorrect flags have been found, but it's not published anywhere. I can publish it if you need that).
The command line arguments are in argv, and since argv is an array, the only way to find a specific element inside of it is to iterate through, checking each element until you get the one you want. If you don't want to write all that yourself, it looks like C has a method called 'lfind' in search.h that does this. Here is an example of how to use it. Hope that helps :3.
Also, the GNU documentation for it
Related
I'm creating a programme that writes the results of a questionnaire to a .txt file and wondered if there was any way to create a new file with a new name every time the programme was run?
FILE *fp;
fp = fopen("results.txt","w");
How can the file reults.txt be saved under a different name each time?
so ive done the below which lets a user save the name of their results.
int main(int argc, char *argv[])
{
printf("Please enter a filename to save your results to\n");
char c;
FILE *fp;
if (argc >= 2){
fp = fopen(argv[1], "w");}
while ((c = getchar()) != EOF)
{
putc(c, fp);
}
but i get a core fault.
Use the standard C function meant to be used for this very purpose.
7.21.4.4 The tmpnam function
#include <stdio.h>
char *tmpnam(char *s);
The tmpnam function generates a string that is a valid file name and that is not the same
as the name of an existing file.
Notably, this family of functions have some security concerns addressed by CERT-C here. C11 provides safer versions called tmpfile_s and tmpnam_s, as part of the optional bounds-checking interface. But if your beginner-lever questionnaire program does not need commercial production quality protection against hackers, this shouldn't be a concern.
There is many ways to do this.
You can take the file name as an argument.
You can get the process id (with getpid()), and add it to the end of the name.
You can add an number at the end of the file and increment it each time the program is run (by looking into the directory)
...
Edit:
Answer to your first edit
You only open the file if argv < 2, so what will append if argv >= 2 ? What do you think will append when you do putc(c, fp); ?
If you want your program only run if there is enough arguments, check it at the beging, and exit if it's not ok, with a message to tell why it's not ok. :)
And, always check the return of functions like fopen, malloc,... To be sure everything is ok.
You can generate random number by using rand() function in C and append it to the filename at the end ! Or you can append currentmillis to your file name to get unique name every time ! Of course there are many ways of doing it !
Or char *tmpnam(char *str); can also be used!
While there is an easy way of using both file redirection and piping, as well as interactive user input reading , with main(), as shown in this C code snippet...
#define SIZ 1024
#include <stdio.h>
extern void do_something_with_the_array(float *a[], int *n);
int main(int argc, const char * argv[])
{
float f[SIZ];
int k = 0;
while ((scanf("%f", &f[k]) == 1)&&(k < SIZ)) {
k++;
}
do_something_with_the_array(f, k);
return 0;
}
… I'm not sure if there is a modern UNIX source compatible and easy way of programmatically achieving any of the three possibilities in a main() in C, depending on the context ?
interactive reading of a string of numbers as user input
reading of the same string of numbers as command line arguments
file redirection and piping
I understand piping and redirection "belong" to the shell which intercepts the program before it even starts executing, while command line arguments and interactive reading "belong" to the main() itself and therefore there may not be an easy way of doing this.
I see using stdin or file input or pipe input pretty self-explanatory. However, reading command line arguments is a different story. Here's a demo how I usually code it, but it looks kind of heavy-handed and hacked to me. Also, in more complicated scenarios with options, this could become a pretty messy piece of code. I'm also not sure how fail-safe or fool proof this is...
#define SIZ 1024
#include <stdio.h>
#include <stdlib.h>
extern void do_something_with_the_array(float *, int);
int main(int argc, const char * argv[])
{
float f[SIZ];
int k = 0;
if(argc > 2){
for(k = 0; k < argc - 1; k++)
f[k] = (float)atof(argv[k+1]);
}
else while ((scanf("%f", &f[k]) == 1)&&(k < SIZ))
k++;
do_something_with_the_array(f, k);
return 0;
}
Thanks in advance!
I do not know off-hand of a C library that will make the three specific cases you mentioned look the same (although someone who does, please answer because I'd like to know, too!). I think you're looking for something not unlike the diamond <> operator in Perl, but for individual arguments rather than files containing arguments.
I think #David Hoelzer has the right idea: handle the three cases separately. For example, when processing command-line or file arguments, don't generate "Enter a value" prompts that you might print for interactive input. For command-line processing, getopt is a good place to start.
Now, a challenge to you: Wrap those three operations in a library and make it open-source so the rest of us can benefit! :)
Quite a few programs do care if they're invoked with keyboard input vs. file input, including the shell itself.
Let us take /bin/sh as our first example. If you call it directly, it starts an interactive shell, but if you pipe something into it, it starts as a non-interactive reading shell. The main difference between the two is if it is not interactive, it doesn't display the $ prompt. However just in case it really is interactive, it can be started with the -i option to make it assume its interactive when it would normally decide otherwise.
The magic involved here is isatty(); see man 3 isatty.
In addition, some programs like to receive keyboard input while processing redirected standard input. There are two generally favored ways of doing this; either opening and reading from /dev/tty or reading standard error, depending on context. Most stuff in an interactively started pipeline doesn't have standard error redirected, so this tends to work well (reading a redirected standard error yields an error immediately as the handle isn't open for read). If you want to make it potentially fully automatable, you read standard error, otherwise you read /dev/tty.
I have a C program, that I would like to print its output from swift, and when it scans I can give it input through Swift. Is such thing possible? I tried this with a simple function, and it worked, but how can someone do so with many different functions that call other functions?
I know the question is a bit vague, but can someone point me into the right direction?
Example of code:
int main(int argc, char **argv) {
int i;
int hitme;
char ch;
prelim();
if (argc > 1) { // look for -f option
if (strcmp(argv[1], "-f")== 0) {
coordfixed = 1;
argc--;
argv++;
}
}
if (argc > 1) {
fromcommandline = 1;
line[0] = '\0';
while (--argc > 0) {
strcat(line, *(++argv));
strcat(line, " ");
}
}
else fromcommandline = 0;
while (TRUE) { /* Play a game */
setup();
if (alldone) {
score(0);
alldone = 0;
}
else makemoves();
skip(2);
stars();
skip(1);
if (tourn && alldone) {
printf("Do you want your score recorded?");
if (ja()) {
chew2();
freeze(FALSE);
}
}
printf("Do you want to play again?");
if (!ja()) break;
}
skip(1);
prout("May the Great Bird of the Galaxy roost upon your home planet.");
return 0;
}
Yes.
This is extensively covered in Using Swift with Cocoa and Objective-C. Objective-C is a superset of C, so all the instructions for Objective-C work equally well for C.
The short version is that you just add the C code to your project, import its header in your Objective-C Bridging Header, and then the C functions will be available in Swift (using various automatic translations).
That said, if you really want to read the output (i.e. the results of these printf) calls, that's a bit different problem. I'd avoid it if you can. Otherwise you'd need to do something like build the C program as its own executable and use NSTask within Swift to call it and capture the output, or you'd have to hijack stdout with something like fdopen. It's a pain to do that completely correctly.
I will focus on the second part of your question, how to interact with C code that uses the standard IO facilities:
The obvious choice as Rob Napier pointed out is just compiling the C code into an executable and using something akin to popen(3) to read and write to its standard IO facilities, the same way you would read/write any other FILE*.
Another way would be to seek out places where stdio is used and change these functions. For example you could use
#ifdef STANDALONE
#define print printf
#else
#define print passToSwift
#endif
Then you can change all the printfs to prints and just #define which mode you want your C code to operate in. In case STANDALONE is left undefined, you will have to provide a passToSwift function that will connect your C and Swift functionality.
One more way without having to change all printfs is using funopen(3) or friends, particularly fwopen(3). With fwopen(3) (man fwopen) you can provide a passToSwift function to be called whenever something is written to stdout.
#include <stdio.h>
int passToSwift(void * cookie, const char * buffer, int len)
{
(void)cookie;
// do stuff with the buffer you recieved
return len;
}
int main(void)
{
fflush(stdout);
stdout = fwopen(NULL, passToSwift);
printf("Hey\n");
}
The assignment to stdout is not portable, but works for me on OS X. I am not aware of any other way to achieve it. (dup2 gives EBADF for funopend streams, freopen expects an entry in the filesystem).
I am adressing a quite similar problem.
I have a solution open to discussion on codereview: C hack: replace printf to collect output and return complete string by using a line buffer
Maybe you could use that (or a part of it) for your text game as well ...
The improved version of C hack: replace printf to collect output and return complete string by using a line buffer is now availabe on github as Xcode 7 project swift-C-string-passing (and standalone gcc version).
Especially look at the #define preprocessor statements to make use of the bridge to swift (similar to a3f's answer).
My solution is able to pass strings in and out to the C code. But how are the answers retrieved from the user? I.e. what does the ja() function do?
Is it possible to make command like arguments like below?
./exe FROM_FILE=true
Here in this case, how I expect in the program is, when FROM_FILE value is true, I wil take data from file and if false, I can take standard values. The other alternatives I find for the purpose is to use
-options
Simply pass arguments. But in this case I have to worry about the order of arguments.
This one just came to mind when doing a makefile.
$>cat makefile
exe :
echo ${FROM_FILE}
$>make FROM_FILE=true
echo true
true
$>
You can do
FROM_FILE=true ./exe
and then read the FROM_FILE environment variable from inside the app with the environ pointer or getenv(). See http://linux.die.net/man/7/environ
Of course it is possible! Something like this (untested):
int main(int argc, char **argv)
{
int FROM_FILE = 0;
const char *FROM_FILE_key = "FROM_FILE";
int i;
/* Iterate through all the arguments. */
for (i = 1; i < argc; ++i)
{
/* Look for the '='. If not there, skip this argument. */
char *eq = strchr(argv[i], '=');
if (!eq)
continue;
/* Compare the key. If not what we want, skip it. */
if (strncmp(argv[i], FROM_FILE_key, strlen(FROM_FILE_key)) != 0)
continue;
/* Parse the value. You probably want to make this more flexible
(true, 1, yes, y...)*/
if (strcmp(eq+1, "true") == 0)
FROM_FILE = 1;
}
printf("FROM_FILE=%s", FROM_FILE? "true" : "false");
}
Possible? Well, since make apparently does it (I haven't tried it myself), it's obviously possible. It might trip up some people because it's certainly an unusual syntax, though.
What you'd want to do then is probably to iterate over argv[], find any parameters on the form something=something, and do your magic. Maybe even zero them out after you are done with them, and then do something more normal like handing over the grunt work to getopt or a similar library.
One thing to consider, especially if you want this to be generic, is what to do when someone passes a file name to your application that contains a =, expecting that file name to be opened, processed or whatever it is your application does for a living.
EDIT: The more I think about it, the less a good idea it seems to break with common command line interface conventions. maybe you should read this: http://www.gnu.org/prep/standards/html_node/Command_002dLine-Interfaces.html
have you tried environment variables?
you can do
FROM_FILE=true ./exe
and in exe.c:
[...]
char *file = getenv("FROM_FILE");
if (file == NULL)
*file = DEFAULT;
[...]
alternatively, for a more GNU-ish approach to command line interfaces, have a look at getopt, or argp. (http://www.gnu.org/software/libc/manual/html_node/Parsing-Program-Arguments.html#Parsing-Program-Arguments)
I am trying to implement the Unix command "tar" in C. It will be executed using the command p5a -c archive infile1 infile2 ... infilek where the arguments infile1, infile2, ..., infilek
denote the names of the files which must be combined to create the archive. I am having trouble getting the file names from the command line and storing them into an array. Any help would be appreciated.
Thanks!
I really should not be spoon-feeding what looks like a homework question, but its been 2 years since I last touched gcc and need some practice.
On one hand, it looks like you are capable of using argc to get the data you want. The problem is 'how to know' the number of arguments. Most people use argv for that. Just made the following with Visual Studio 2010,
#include<stdio.h>
#include<conio.h>
int main(int argv, char *argc[])
{
int i = 1;
printf("Your arguments are:\n");
for (i=0; i<argv; i++)
{
printf("%s\n",argc[i]);
}
return 0;
}
And here is some sample output (Win7 command line),
C:\...\Debug>C_hello.exe this is a string of input
Your arguments are:
C_hello.exe
this
is
a
string
of
input
C:\...\Debug>
I expect you'll get similar results with gcc in linux as well.
EDIT: Did some searching on the matter. Looks like there's a standard linux library for this sort of thing,
getopt
See the example on that page. Very well explained.