How can I process command line arguments in C? - c

I wanted to know how it would be possible to get other input through the command line? I want to look for "-w" and a number, so it would look like "-w60" and "-s". This input is given through the command line, so it would look like this:
c:\Users\Username\Desktop> wrapfile.exe -w5 -s test.txt
Output should look like this:
Hello
,
this
is a
test
What the -w5 and -s mean is:
-w5 = width (can only display 5 characters at a time)
-s = spacing (Include spacing, so fit as many whole words as you can)
I want to create a function that scans for these two characters, and if anyone knows how to format the output so it does what it needs to do, that would also be helpful.
I'm just a wee bit confused, I've been working on this program for a while and I just want to learn how these things can be scanned and used properly.
Here is my current code that takes in an unlimited amount of text files from the command line:
#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)
{
}
*/

If you pass -w5 -s test.txt to your program your argv's are:
argv[0] = "wrapfile.exe"
argv[1] = "-w5"
argv[2] = "-s"
argv[3] = "test.txt"
So:
int l = 1;
fp = fopen(argv[l], "rb");
is not what you want for sure.
For illustration purposes... in order to print to a "restricted" width you can do something like this:
char * h = "this is a string longer than width"; // you'd get this from your file
int width = argv[1][2] - '0'; // you wouldn't hardcode this...
int count;
for(count = 0; count < strlen(h); count++){
if((count % width) < width - 1)
printf("%c", str[count];
else
printf("%c\n", str[count];
}

I find getopt cumbersome to use. Writing your own tests is not too difficult. For example:
#include <string.h>
#include <stdio.h>
int main(int argc, char **argv) {
int haveSpacing = 0;
int haveWidth = 0;
FILE *fp = 0;
while (*++argv) {
if (!strcmp(*argv, "-s")) { // check for -s switch
haveSpacing = 1;
}
else if (sscanf(*argv, "-w%d", &haveWidth) == 1) { // check for -wxx
}
else if (**argv == '-') { // reject anything else beginning with "-"
printf("invalid switch %s\n", *argv);
return 1;
}
else if (argv[1]) { // filenaname must be last arg, so arg[1] must be NULL
printf("invalid arg %s\n", *argv);
return 1;
}
else if (!(fp = fopen(*argv, "rb"))) { // open last arg, the filename
perror(*argv);
return 1;
}
}
if (!fp) {
printf("missing filename\n");
return 1;
}
// ...
return 0;
}

Related

How to print out an error message if files are missing in c

I have written this code:
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
FILE *inputFiles[argc - 1];
int i;
char c;
int counter = 1;
// Enter files into an array
for (i = 1; i < argc; i++)
{
//printf("The file in place %d is %s\n",i, argv[i]);
inputFiles[i] = fopen(argv[i], "r");
if ((inputFiles[i] = NULL)) {
printf("File cannot be opened");
}
//printf("%p\n",inputFiles[i]);
}
c = fgetc(inputFiles[argc - 1]);
while (c != EOF)
{
printf ("%c", c);
c = fgetc(inputFiles[counter]);
}
fclose(inputFiles[argc - 1]);
return 0;
}
and it does what it needs to do, but there is a bug: If I print out the content of a file, the first character of the file is duplicated, how can I fix this. Furthermore as the files are read in through command-line arguments, I would like to output an error message if one of the files cannot be found or is corrupt. How can I do this? Any help is greatly appreciated.
if ((inputFiles[i] = NULL))
You are assigning NULL, not checking for NULL.
change this
if ((inputFiles[i] = NULL)) { //its assignment not comparison
printf("File cannot be opened");
}
to
if ((inputFiles[i] == NULL)) {
printf("File cannot be opened");
}

Reading numbers into array and printing off in reverse in C

I'm trying to open a file using command line arguments and read the numbers I have in my 'testdata' file in reverse The numbers in the test data file consist of:
2
20
200
2000
20000
-2
-20
-200
-20000.
Here is the code I have written so far. The file prints out, obviously not in reverse. I'm assuming I'm just missing a for loop in here somewhere. I'm also considering that maybe I should be using fscanf instead of fgets. Any input is appreciated.
#include <stdio.h>
#define MAX_NUMS 1000
int main(int argc, char *argv[]) {
Int a, n;
char buf[MAX_NUMS];
Int array[MAX_NUMS];
file *pt;
if (argc < 2) {
printf("Usage %s <files..>\n");
}
if ((pt = fopen(argv[1], "r")) == NULL) {
printf("Unable to open %s for reading.\n", argv[1]);
Return 1;
}
while (fgets(buf, MAX_NUMS, pt) != NULL){
printf("%s", buf);
}
for(j = 0; j < MAX_NUMS; j++){
If(fscanf(pt, "%d", &array[a]) != 1);
Break;
For(a = n; a--> 0;){
Printf("%d", array[a]);
}
fclose(pt);
retuern 0;
}
Use while(fscanf("%d", &n)){ a[i++] = n; } initiate i with 0 before and declare a as an integer array. Later while printing, printing it in reverse order. It is not possible to read from reverse order, though you can go to the end of the file using fseek().
There are some problems in your code:
the stream type is spelled FILE.
you do not return from the main() function in case of errors. The program keeps going and you have undefined behavior.
there is a missing argument in the first printf().
there is a typo on the return statement.
You could define the maximum number of numbers to handle, define an array for the numbers and use a loop index to store the numbers and later print them in reverse order.
Here is an example:
#include <stdio.h>
#define MAX_NUMBERS 1000
int main(int argc, char *argv[]) {
int array[MAX_NUMBERS];
int i, n;
FILE *pt;
if (argc < 2) {
printf("Usage %s <files..>\n", argv[0]);
return 1;
}
if ((pt = fopen(argv[1], "r")) == NULL) {
printf("Unable to open %s for reading.\n", argv[1]);
return 1;
}
for (n = 0; n < MAX_NUMBERS; n++) {
if (fscanf(pt, "%d", &array[n]) != 1)
break;
}
for (i = n; i-- > 0;) {
printf("%d\n", array[i]);
}
fclose(pt);
return 0;
}

Extract a column of a list from a text file in C

This may be a simple question with a straightforward answer, but searching through the site I didn't find anything (maybe because I'm new to C programming) except for python codes, which I already wrote and it's quite inefficient.
Suppose I have a list of data in a timestamps.txt file, formatted like this:
<large integer>, <integer between 1 and 8>
<large integer>, <integer between 1 and 8>
and so on (the file is about 4GB)...
What I want to do is to copy only the second column to another file, say singles.txt.
What I did so far works, but it's a rather naive approach and takes too much time. Here's my code:
int main(int argc, char const *argv[])
{
FILE *input_file;
FILE *output_file;
char ch;
int check = 0;
input_file = fopen("timestamps.txt","r");
output_file = fopen("singles.dat","w");
if (!input_file)
return -1;
while((ch = getc(input_file))!=EOF)
{
if(check==1)
{putc(ch,output_file);putc('\n',output_file);}
if(ch == ',')
check = 2;
else
check -= 1;
}
fclose(input_file);
fclose(output_file);
return 0;
}
I'm sure there is a faster way, but I can't seem to make anything work.
Any help would be much appreciated.
Using fgets and fputs is faster than multiple calls to getc and putc, all you need is a buffer (a little buffer in this case) to store the current line:
int main(int argc, char const *argv[])
{
FILE *input_file;
FILE *output_file;
char buf[128];
char *ptr;
input_file = fopen("timestamps.txt","r");
output_file = fopen("singles.dat","w");
if (!input_file)
return -1; /* use EXIT_FAILURE instead of -1 */
/* you forget to check output_file */
while (fgets(buf, sizeof buf, input_file)) {
ptr = strchr(buf, ','); /* find the comma */
if (ptr != NULL) {
fputs(ptr + 1, output_file); /* +1 to skip the comma */
}
}
fclose(input_file);
fclose(output_file);
return 0;
}
Your idea isn't so bad, but you should make your variable check either 0 or 1, depending on whether you want to copy the current input data or not. And you must reset the check with each new line.
Alternatively, you could countthe current field your are in and copy the data when the field is the one you want.
Here's a version that copies the column want delimited by sep verbatim to the output file:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
FILE *in = stdin;
FILE *out = stdout;
int want = 1;
int col = 0;
int sep = ',';
for (;;) {
int c = getc(in);
if (c == EOF) break;
if (c == sep) {
col++;
} else if (c == '\n') {
col = 0;
putc(c, out);
} else if (col == want) {
putc(c, out);
}
}
return 0;
}
(I've used stdin and stdout, because I was lazy and didn't want to do the flie opening and closing stuff.)

Const number of words in a text

I tried to write a program for counting number of words in a text that taken from a file. I have a problem, the compiler can not find my file however I put this file in project folder.
what can I do?
#include <stdio.h>
#include <conio.h>
#include <string.h>
int words(const char sentence[ ]);
int main(void) {
char sentence[100];
FILE *cfPtr;
if ( (cfPtr = fopen("C programming.dat", "r")) == NULL ) {
printf( "File could not be opened\n" );
}
else {
fscanf(cfPtr, "%s", sentence);
}
words(sentence);
printf("%d", words(sentence));
getch();
return 0;
}
int words(const char sentence[ ]) {
int i, length = 0, count = 0, last = 0;
length = strlen(sentence);
for (i = 0; i < length; i++)
if (sentence[i] == ' ' || sentence[i] == '\t' || sentence[i] == '\n')
count++;
return count;
}
I'll try to improve usability of your program, accepting a filename as optional parameter
int main(ant argc, char *argv[]) {
char sentence[100];
const char *filename = "C programming.dat";
FILE *cfPtr;
if (argc == 2)
filename = argv[1];
if ( (cfPtr = fopen(filename, "r")) == NULL ) {
printf( "File '%s' could not be opened\n", filename );
}
else {
int total = 0;
while (fgets(sentence, sizeof sentence, cfPtr))
total += words(sentence);
printf("%d", total);
fclose(cfPtr);
}
getch();
return 0;
}
...
note: untested
If the file is not in the working directory (the folder your program is in) you need to specify the entire file path. On a Linux machine this would be something like "/home/your-user-name/Desktop/text.txt". For a Windows machine it would be "c:\\your\\file\path\\text.txt". If the file is in your working directory and the program still cannot find it, then it probably doesn't like the white space in the file name. Try naming it CProgramming.dat and see if that works.

How do I get the input to cut off or wrap around at a certain point?

Alrighty, so after a day and a bit of being on stackoverflow, I learned it's useful being on this site :) I ended up getting my program to work. I can get an unlimited amount of text files in on the command line and display them as well! So it looks like this:
CMD Console
c:\Users\Username\Desktop> wrapfile.exe hello.txt how.txt. are.txt you.txt random.txt
Hello How are you doing today? I hope you're doing quite well. This is just a test to see how much I can fit on the screen.
Now, I wana build on this program. How would I get this new found text to wrap around? Like, if you wanted to make it that, every 40 characters or so, the text jumps to the next line... how could we go about doing something like that?
Thanks again!
Here's the code I'm working with:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
int l = 1;
while(l != argc)
{
FILE *fp; // declaring variable
fp = fopen(argv[l], "rb");
l++;
if (fp != NULL) // checks the return value from fopen
{
int i = 1;
do
{
i = fgetc(fp); // scans the file
printf("%c",i);
printf(" ");
}
while(i!=-1);
fclose(fp);
}
else
{
printf("Error.\n");
}
}
}
Okay, here we go...this looks a little different to yours, but this is ISO/ANSI C 1989 standard.
int main(int argc, char **argv)
{
FILE *fd = NULL;
char linebuf[40];
int arg = 1;
while (arg < argc) {
fd = fopen(argv[arg], "r");
if (NULL != fd) {
/* fgets(char *buf, size_t buflen, FILE *fd): returns NULL on error. */
while (NULL != fgets(linebuf, sizeof(linebuf), fd)) {
printf("%s\n", linebuf);
}
fclose(fd);
} else {
fprintf(stderr, "Cannot open \"%s\"\n", argv[arg]);
}
++arg;
}
}

Resources