Running program from console with parameters [duplicate] - c

This question already has answers here:
Command-line Parameters in C program?
(5 answers)
Closed 6 years ago.
My question is how to write a fuction with which I will can run a program from console with following parameters:
program.exe -i input.txt -o output.txt -t 1/2/3
#include <stdio.h>
#include <stdlib.h>
char substitute(char letter, char* cipher)
{
int i;
int cipher_length = strlen(cipher);
char substitution = letter;
for(i = 0; i < cipher_length; ++i)
{
if(cipher[i] == substitution)
{
substitution = cipher[(i%2) ? (i-1) : (i+1)];
break;
}
}
return substitution;
}
int main()
{
char c;
int t;
FILE *plik = fopen( "input.txt", "rt" );
FILE *encoded=fopen("output.txt","wt");
char* cipher1 = "GADERYPOLUKIgaderypoluki";
char* cipher2 = "POLITYKARENUpolitykarenu";
char* cipher3 = "KACEMINUTOWYkaceminutowy";
printf("Choose the cipher\n");
printf("[1]GA-DE-RY-PO-LU-KI\n");
printf("[2]PO-LI-TY-KA-RE-NU\n");
printf("[3]KA-CE-MI-NU-TO-WY\n");
scanf("%d",&t);
while(c != EOF)
{
c = getc( plik );
switch(t)
{
case 1:
putc(putchar(substitute(c, cipher1)),encoded);
break;
case 2: putc(putchar(substitute(c, cipher2)),encoded);
break;
case 3: putc(putchar(substitute(c, cipher3)),encoded);
break;
}
}
fclose( plik );
fclose(encoded);
}
I was given sth like this, but I don't know how to use it:
int function(int argc, char*argcv[])
{
int i;
char *string,*input,*output;
for(i=0; i<argc; i++)
{
}
return 0;
}

The parameter int argc contains the number of parameters in the command line.
The parameter char *argv[] is an array with all the strings typed in the command line.
This way, you can retrieve the command line parameters as:
int main(int argc, char *argv[]) {
int i = 0;
for (i = 0; i < argc; i++) {
printf("parameter %d = %s\n", i, argv[i]);
}
}
You can handle then the parameters passed in the command line:
int main(int argc, char *argv[]) {
int i = 0;
for (i = 0; i < argc; i++) {
...
if (strcmp(argv[i], "-i") == 0) {
doSomething(argv[i+1]);
}
...
}
}
To break the string you can use the following code:
// ...
char buffer[256];
char *p1 = NULL;
char *p2 = NULL;
int value = 0;
char old = 0;
strcpy(buffer, argv[7]);
p1 = buffer;
p2 = buffer;
do {
// parse until the delimiter
while (*p1 != '/' && *p1 != '\0') {
p1++;
}
// save delimiter value
old = *p1;
// convert the string to int
*p1 = '\0';
value = atoi(p2);
p1++;
// do something with the value
printf(">> value %d\n", value);
// goto the next token
p2 = p1;
} while (old != '\0');

Related

Split file as argument by '/' (slash)

I have a bit of code and I need to split the words in the filename and store them separately.
Example:
Input -> filename ( e.g. /Users/user/Documents/uni)
Storage in variable/array as separate words ( not sure how):
char array/struct array = Users user Documents uni
How can I achieve the above example of storing words with C?
Here is my code:
int main(int argc, char *argv[])
{
char filename[255];
for (int i = 0; i < argc; i++)
{
strcpy(&filename[i], argv[i]);
}
}
Thanks in advance
Would you please try the following:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char filename[BUFSIZ]; // pathname
int i;
int n = 0; // number of words
char **ary = NULL; // array of strings
char *tok; // pointer to each token
if (argc != 2) { // verify aruguments
fprintf(stderr, "usage: %s pathname\n", argv[0]);
exit(1);
}
strncpy(filename, argv[1], BUFSIZ);
for (tok = strtok(filename, "/"); tok != NULL; tok = strtok(NULL, "/")) {
if (NULL == (ary = realloc(ary, (n + 1) * sizeof(*ary)))) {
// enlarge array of strings
perror("realloc");
exit(1);
}
if (NULL == (ary[n] = malloc(strlen(tok) + 1))) {
// allocate memory for the word
perror("malloc");
exit(1);
}
strncpy(ary[n], tok, strlen(tok) + 1);
// copy the token to the array
n++;
}
// see the results
for (i = 0; i < n; i++) {
printf("[%d] %s\n", i, ary[i]);
}
// free the allocated memory
for (i = 0; i < n; i++) {
free(ary[i]);
}
free(ary);
return 0;
}
If you compile the code to the executable a.out, the outout will look like:
$ ./a.out /Users/user/Documents/uni
[0] Users
[1] user
[2] Documents
[3] uni
I have managed to achieve the desired outcome with this piece of code:
int main(int argc, char *argv[])
{
char word[255];
const char s[2] = "/";
char *token;
if( argc == 2 ) {
printf("The argument supplied is %s\n", argv[1]);
}
else if( argc > 2 ) {
printf("Too many arguments supplied.\n");
}
strcpy(word, argv[0]);
token = strtok(word, s);
while( token != NULL ) {
printf( " %s\n", token );
token = strtok(NULL, s);
}
}

Filling an array of strings with words from a file txt

i'm trying to fill each row of the array with each word of the file.
I don't want to overallocate memory , so i want to know atleast the lenght of the longest word and the number of rows i should allocate, so the number of words written in the file.
I can't understand where is the problem in the code. I think it should be a problem with counting the longest word since when i print longest_file_word after assigning the value returned by the function it prints -1.
Obviously it doesnt work.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int longestWord(char *file, int *nWords);
char ** Create2DStr(ssize_t numStrings, ssize_t maxStrLen);
int main(int argc, char *argv[]){
int file_elements_number=0 , i , j , k , z , longest_file_word , count_file_words ;
char *filename =(char*)malloc((strlen(argv[2]) +1 )*sizeof(filename));
strcpy( filename , argv[1]);
for(i = 0; i < strlen(argv[1])+1 ; i++){
printf("%c" , filename[i]);
}
if(filename = NULL){
printf("Non c'e' abbastanza memoria");
return 1;
}
if(argc!=2)
{
printf("Errore numero parametri passati da linea di comando\n");
return 1;
}
longest = longestWord( filename , &count);
printf("ciao %d\n%d\n", count , longest);
char **file_words = Create2DStr(count, longest);
FILE *file_ptr;
const char delim[] = {" \n\t"};
char line[260];
char *buf = NULL;
file_ptr = fopen( filename, "r");
count=0;
while(fgets(line, 260, file_ptr))
{
buf = strtok(line, delim);
while(buf)
{
if((strlen(buf) > 0)){
strcpy(file_words[count], buf);
count++;
}
buf = strtok(NULL, delim);
}
}
for(i = 0 ; i < count ; i++){
for( j = 0 ; j < longest ; j++){
printf("%c" , file_words[i][j]);
}
printf("\n");
}
fclose(file_ptr);
free(filename);
filename = NULL;
return 0;
}
int longestWord(char *filename, int *nWords)
{
FILE *file_ptr=0;
int cnt=0, longest=0, numWords=0;
char c;
file_ptr = fopen(filename, "r");
if(file_ptr){
while ( (c = fgetc(file_ptr) ) != EOF )
{
if ( isalnum (c) ) {
cnt++;
}
else if ( ( ispunct (c) ) || ( isspace(c) ) || (c == '\0' ) || (c== '\n'))
{
(cnt > longest) ? (longest = cnt, cnt=0) : (cnt=0);
numWords++;
}
}
*nWords = numWords;
fclose(file_ptr);
}
else {
return -1;
}
return longest;
}
char ** Create2DStr(ssize_t numStrings, ssize_t maxStrLen){
int i;
char **a = {0};
a =(char**) calloc(numStrings, sizeof(a));
for(i=0;i<numStrings; i++)
{
a[i] = (char*)calloc(maxStrLen + 1, 1);
}
return a;
}
You're doing,
if(filename = NULL)
rather than,
if(filename == NULL)
after reading your filename.
You should be compiling with warnings turned on, -Wall on gcc.
The result -1 means that function longestWord cannot open the specified file name which may be a result of the if(filename = NULL)
Apart from this it is difficult to understand what you are doing with argv[1] and argv[2] to prepare filename. You allocate memory based on the string length of argv[2], then copy the string from argv[1] which could be longer.
You should do the checks of argc and filename before you access argv or filename.

Low Level File I/O Compare Strings

I'm writing a program that takes a file with the 3 lines of encrypted passwords and compares them to all 4 lower case letters from aaaa - zzzz. The only issue I am having is that I can't figure out how to go line by line of the file I input and how to compare it to the 4 letter words individually. It should then print the 3 decrypted 4 letter words that correlate to the passwords from the file. Also if there are any types on how to improve my code, please let me know. I'm a beginner at this so I need clear explanations and examples if possible. Thank you.
EDIT*****
The main problem is in the all function and main. I'm not wanting to print the aaaa, aaab, aaac, etc to the screen but I want to put it in an char array so that i can compare each individually to each line from the file using crypt. So I need advice on how to put all 456976 combinations into an array, compare it to each line of code, and print the solutions to the screen.
file looks like this:
$1$6gMKIopE$I.zkP2EvrXHDmApzYoV.B.
$1$pkMKIcvE$WQfqzTNmcQr7fqsNq7K2p0
$1$0lMKIuvE$7mOnlu6RZ/cUFRBidK7PK.
My code looks like this:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#define BUFFER_SIZE 1024
int my_fgets(char* buf, int len, int f)
{
for (int i = 0; i < len; i++,buf++)
{
int count = read(f, buf, 1);
if (!count || (buf[0] == '\n'))
{
buf[0] = 0;
return i;
}
}
return 0;
}
int inc(char *c,char begin, char end){
if(c[0]==0)
return 0;
if(c[0] == end){ // This make the algorithm to stop at char 'f'
c[0]=begin; // but you can put any other char
return inc(c+sizeof(char), begin, end);
}
c[0]++;
return 1;
}
char all(int a, int n,char begin, char end){
int i, j;
char *c = malloc((n+1)*sizeof(char));
char result[] = "";
for(i = a; i <= n; i++)
{
for(j=0;j<i;j++) c[j]=begin;
c[i]=0;
do {
int k = sizeof(result);
for (int g = 0; g < k -1; g++)
{
result[g] = c;
}
} while(inc(c,begin,end));
}
free(c);
}
int main(int argc, char* argv[])
{
char *result;
char let[456976];
int f = open("pass.txt", O_RDONLY);
if (f < 0)
return 0;
char buf[1024];
while (my_fgets(buf, sizeof(buf), f))
{
let = all(4,4,'a','z');
int i = 0;
result = crypt((let[i+1]), buf);
int ok = strcmp (result, pass) == 0;
return ok ? 0 : 1;
all(4, 4, 'a', 'z');
}
close(f);
}
I think you need to reword the question. Maybe the code below is what you want. Let's say you have a password, and you have a file which contains a list of encrypted passwords (or hash usually), you want to see if password is right or wrong. You compare the hash of the password with hashes in the file. I haven't tested this code.
ps, let me know if I am way off, I'll delete the answer.
void crypt(char* hash, const char* password_test) {
//create hash from password, or encrypt it or something?
}
int test_password(const char *filename, const char *password){
FILE *f;
f = fopen(filename, "r");
if (!f) return 0;
char password_hash[256];
crypt(password_hash, password);
char hash[256];
char buf[1024];
while (fgets(buf, sizeof(buf), f) != NULL)
{
crypt(hash, buf);
if (strcmp(password_hash, hash) == 0)
return 1;
}
fclose(f);
return 0;
}
void main() {
int result = test_password("test.txt", "password");
if (result == 1)
printf("password is good\n");
}
Reading line by line using open/read/close
int my_fgets(char* buf, int len, int f)
{
for (int i = 0; i < len; i++,buf++)
{
int count = read(f, buf, 1);
if (!count || (buf[0] == '\n'))
{
buf[0] = 0;
return i;
}
}
return 0;
}
int main(){
int f = open("test.txt", O_RDONLY);
if (f < 0) return 0;
char buf[1024];
while (my_fgets(buf, sizeof(buf), f))
printf("%s\n", buf);
close(f);
}

Why doen't the name of the file increment like the data of the file's array does?

So the title I know is a little misleading with the contents, but my question is: with the code provided here, when I run ./tstats input1.txt input2.txt the output is as follows
5 1 21 input1.txt
2 1 11 input1.txt
So it's obvious that the information from each file is going through but the names of the files aren't. Any idea as to why this is happening? Some small mistake I'm looking over?
Secondly, how would I tally all of the wcount results so that I have:
7 2 32 total
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
enum state
{
START,
WORD,
DELIM,
};
FILE*
input_from_args(int argc, char *argv[])
{
if (argc == 1)
{
return stdin;
}
else
{
return fopen(argv[1], "r");
}
}
char* get_filename_from_args(int argc, char* argv[])
{
int i;
static char stdin_name[] = "-";
if (argc == 1)
{
return stdin_name;
}
else
{
for (i = 1; i < argc; i++)
{
return argv[i];
}
return argv[i];
}
}
void
wcount(FILE *src, FILE *dest, char* src_filename)
{
int ch, wc, lc, cc;
enum state cstate;
wc = lc = cc = 0;
cstate = START;
while ((ch = fgetc(src)) != EOF){
cc++;
switch (cstate) {
case START:
if (isspace(ch)) {
cstate = DELIM;
if (ch == '\n') {
lc++;
}
}
else {
cstate = WORD;
wc++;
}
break;
case DELIM:
if (ch == '\n') {
lc++;
}
else if (!isspace(ch)) {
cstate = WORD;
wc++;
}
break;
case WORD:
if (isspace(ch)) {
cstate = DELIM;
if (ch == '\n') {
lc++;
}
}
break;
}
}
fprintf(dest, "%4d\t%4d\t%4d\t%10s\n", wc, lc, cc, src_filename);
}
int
main(int argc, char* argv[])
{
int i;
FILE *src = input_from_args(argc, argv);
FILE *dest = stdout;
for (i = 1; i < argc; i++)
{
if ((src = fopen(argv[i], "r")) == NULL)
{
fprintf(stderr, "%s: unable to open %s\n", argv[0], argv[i]);
}
wcount(src, dest, get_filename_from_args(argc, argv));
fclose(src);
}
return EXIT_SUCCESS;
}
get_filename_from_args doesn't do what you think it does. Get rid of it entirely and just use argv[i] again at the call site.
regarding this sub question:
Secondly, how would I tally all of the wcount results so that I have:
7 2 32 total
add three global int variables
Then when each value is available, add it to the appropriate global variables.
Then, in the end, printf the contents of those global variables
This line:
'wcount(src, dest, get_filename_from_args(argc, argv));'
is not stepping through the arguments contained in argv.
Suggest:
'wcount(src, dest, argv[i]);'
and eliminating the function:
'char* get_filename_from_args(int argc, char* argv[])'

Getopt ordering, any?

I was doing a little program and realize that I will need that the user input his options in the right order so my program would do his job right, but I thought that this is kind of 'bug' an should be avoided, so I tried to make the program work 'order independent', but that doesn't work, so I decided to find a function that do the optarg parse the options in the order that I choose, but, for my surprise, I COULDN'T FIND ANY, so I decided to write my on getopt ordering function... The question is, there is a specific function for this job? (and I wrote all of this code in vain :( ). If there is a function, please tell me. And, independently if a function exists or not, You guys could take a look at the piece of code that I wrote... Thank you in advance.
Obs.: I want to know if exist a C function for the task.
The code is in https://github.com/paolocarrara/getopt_ordering
But here is it too (two files):
/*file _getopt.h (first file)*/
#include <stdlib.h>
char **ordering (int *, char **, char *);
/*file ordering.c (second file)*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define TRUE 1
#define FALSE 0
int get_line_size (char *line) {
return strlen (line);
}
int verify_if_is_option (char *argv) {
if (argv != NULL) {
if (argv[0] == '-')
return TRUE;
else
return FALSE;
}
else
return FALSE;
}
int problem_counter (int argc, char **argv) {
int i;
int number_of_problens;
for (i = 1, number_of_problens = 0; i < argc; i++)
if (verify_if_is_option (argv[i]) == TRUE)
if (get_line_size (argv[i]) > 2)
number_of_problens++;
return number_of_problens;
}
char **malloc_argv (int argc, char **argv, int t_problens) {
char **new;
int i;
new = malloc ((argc+t_problens)*sizeof(char*));
for (i = 0; i < argc; i++)
new[i] = argv[i];
for (; i < argc + t_problens; i++)
new[i] = NULL;
return new;
}
char *get_problematic_line (int argc, char **argv) {
int i;
char *line = NULL;
for (i = 1; i < argc; i++)
if (verify_if_is_option (argv[i]) == TRUE)
if (get_line_size (argv[i]) > 2)
line = argv[i];
return line;
}
char *get_argument (char *line) {
char *argument;
int i;
argument = malloc ((strlen(line)-1)*sizeof(char));
for (i = 2; i < strlen(line); i++)
argument[i-2] = line[i];
argument[i-2] = '\0';
return argument;
}
char **push_down (int argc, char **argv, int i) {
for (; argc > i+1; argc--)
argv[argc-1] = argv[argc-2];
return argv;
}
char **push_one_line_down_from_here (char *line, int argc, char **argv) {
int i;
for (i = 1; i < argc; i++)
if (argv[i] == line){
argv = push_down (argc, argv, i);
i = argc;
}
return argv;
}
char **insert_argument_below_this_line (char *line, char *argument, char **argv) {
int i;
for (i = 1; line != argv[i]; i++);
argv[i+1] = argument;
return argv;
}
void remove_argument_from_problematic_line (char *line) {
line[2] = '\0';
}
char **malloc_and_divide (int *argc, char **argv) {
int t_problens;
char *line;
char *argument;
t_problens = problem_counter (*argc, argv);
argv = malloc_argv (*argc, argv, t_problens);
(*argc) +=t_problens;
for (;t_problens > 0; t_problens--) {
line = get_problematic_line (*argc, argv);
argument = get_argument (line);
argv = push_one_line_down_from_here (line, *argc, argv);
argv = insert_argument_below_this_line (line, argument, argv);
remove_argument_from_problematic_line(line);
}
return argv;
}
char *litteral_to_dinamic (char *literal) {
int i;
char *dinamic = malloc ((strlen(literal)+1)*sizeof(char));
for (i = 0; i < strlen(literal); i++) dinamic[i] = literal[i];
dinamic[i] = '\0';
return dinamic;
}
char get_desired_option (char *optstring) {
char option;
option = optstring[0];
return option;
}
void remove_option_used (char *optstring) {
int i;
for (i = 1; i <= strlen(optstring); i++)
optstring[i-1] = optstring[i];
if (optstring[0] == ':')
remove_option_used (optstring);
}
int is_in_argv (int argc, char **argv, char option) {
int i;
for (i = 1; i < argc; i++)
if (argv[i][0] == '-' && argv[i][1] == option)
return TRUE;
return FALSE;
}
int option_have_argument (char **argv, int position) {
if (argv[position+1][0] == '-')
return TRUE;
else
return FALSE;
}
int both_have_argument (int argc, char **argv, int position, int i) {
if(i < argc-1){
if((argv[position+1][0] != '-') && (argv[i+1][0] != '-'))
return TRUE;
else
return FALSE;
}
else
return FALSE;
}
void change_both_arguments (int argc, char **argv, int position, int i) {
char *aux;
aux = argv[position+1];
argv[position+1] = argv[i+1];
argv[i+1] = aux;
}
int first_have_argument (int argc, char **argv, int position) {
if (position < argc-1)
if (argv[position+1][0] != '-')
return TRUE;
return FALSE;
}
void change_first_argument (int argc, char **argv, int position, int i) {
char *aux;
aux = argv[position+1];
for (position++; position < i; position++)
argv[position] = argv[position+1];
argv[i] = aux;
}
int second_have_argument (int argc, char **argv, int i) {
if (i < argc-1)
if (argv[i+1][0] != '-')
return TRUE;
return FALSE;
}
void change_second_argument (int argc, char **argv, int position, int i) {
char *aux;
int j;
aux = argv[i+1];
for (j=i+1; j > position; j--)
argv[j] = argv[j-1];
argv[position+1] = aux;
}
int verify_arguments (int argc, char **argv, int position, int i) {
if (both_have_argument (argc, argv, position, i) == TRUE) {
change_both_arguments (argc, argv, position, i);
return position+2;
}
else if (first_have_argument (argc, argv, position) == TRUE) {
change_first_argument (argc, argv, position, i);
return position+1;
}
else if (second_have_argument (argc, argv, i) == TRUE) {
change_second_argument (argc, argv, position, i);
return position+2;
}
else
return position+1;
}
int change_option_position (int argc, char **argv, char option, int position) {
int i;
char *aux;
for (i = 1; i < argc; i++)
if (argv[i][0] == '-' && argv[i][1] == option) {
aux = argv[position];
argv[position] = argv[i];
argv[i] = aux;
position = verify_arguments (argc, argv, position, i);
}
return position;
}
char **organize (int argc, char **argv, char *optstring) {
int position = 1;
char option;
optstring = litteral_to_dinamic (optstring);
while (optstring[0] != '\0') {
option = get_desired_option (optstring);
remove_option_used (optstring);
if ((is_in_argv(argc, argv, option)) == TRUE)
position = change_option_position (argc, argv, option, position);
}
return argv;
}
char **ordering (int *argc, char **argv, char *optstring) {
int i;
argv = malloc_and_divide (argc, argv);
argv = organize (*argc, argv, optstring);
return argv;
}
You are correct, there are no functions that will do what you describe. However, why don't you just declare a bitmap and use getopt only to set the values in the bitmap? After that's done, you can then check the bitmap and process the options in whatever order you please. Consider the following example, assuming an arbitrary option 'b' needed to be processed before an arbitrary option 'a'.
#define OPTIONS = "ab"
#define flaga = 0x0001; /* corresponds to a */
#define flagb = 0x0002; /* corresponds to b */
unsigned int flags = 0; /* the bitmap */
char ch = '\0' /* the switch char */
while ((ch = getopt(argc, argv, OPTIONS)) != -1)
{
switch (ch) {
case 'a': /* set flag a */
flags |= flaga;
break;
case 'b':
flags |= flagb;
break;
}
if((flags & flagb) == flagb)
{
//process flag b
}
if((flags & flaga) == flaga)
{
//process flag a
}

Resources