Print command line parameter on console - c

I want to pass a file name to my programm. If I type it in the terminal it works. But if I pass it as a command line parameter it doesn`t print the string in the end. Just something like: "²☺"
Any ideas why?
#include <stdio.h>
int main(int argc, char* argv[]){
char *nameDatei[100];
if(argv[1] != NULL) {
nameDatei[100] = argv[1];
} else {
printf("type in the name of the file: ");
scanf("%s", nameDatei);
}
printf("%s", &nameDatei);
return 0;
}

It only works "by accident" when you type the name at the terminal, and that's because you are either ignoring compiler warnings or using an obsolete compiler (any compiler which is not complaining about the code is obsolescent, though GCC 11.2.0 seems to accept it unless you pass warning options such as -Wall -Wextra -Werror).
You pass a char *(*)[100] to printf() but tell it that the argument is a char *
You pass a char ** to scanf() but tell it that the argument is a char *
You try to access element 100 of an array of size 100, which is one too many.
You happen to have 100 * sizeof(char *) bytes to hold the name, which is where the accident comes in, but that's not the correct type.
You need code more like:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
char *nameDatei;
char nameBuffer[100];
if (argv[1] != NULL)
nameDatei = argv[1];
else
{
printf("type in the name of the file: ");
if (scanf("%99s", nameBuffer) != 1)
{
fprintf(stderr, "failed to read file name\n");
exit(EXIT_FAILURE);
}
nameDatei = nameBuffer;
}
printf("%s\n", nameDatei);
return 0;
}
I called the source cla61.c and the program cla61. A couple of sample runs:
$ cla61 abyssinian-coffee
abyssinian-coffee
$ cla61
type in the name of the file: abyssinian-coffee
abyssinian-coffee
$
Don't copy command-line arguments unless you are going to modify them. But it's legitimate to make a new variable point to a command-line argument. And when there isn't a command-line argument, you need to allocate space for the replacement value — the value read from the terminal in this example.

Related

What is ./nqt in C programming and how do i change file without changing them in the code

So i trying to input multiple files in the assigned program.
My input file code is as such:
int read_File(int *hp, int *d, int *s, char t[])
{
FILE *infile;
infile = fopen("input1.txt", "r");
if (!infile)
{
return 0;
}
else
{
fscanf(infile, "%d", hp);
fscanf(infile, "%d", d);
fscanf(infile, "%d", s);
fscanf(infile, "%s", t);
fclose(infile);
return 1;
}
i did
$>gcc assignedProgram.c -o nqt
$>./nqt input1.txt
but if i want to read input2.txt, i have to change from input1.txt to input2.txt in the codes. Is there anyway to bypass that and read input2.txt without changing from input1.txt to input2.txt in the codes
like when i tried ./nqt input1.txt => it's normal
BUT ./nqt input2.txt it's segmentation fault:11
I tried:
to change "input1.txt" in the codes to "nqt" but that was a dumb idea
and BTW: what is ./nqt
Please help me!
You must write main() as one of the equivalent forms below
int main(int argc, char **argv) { /*...*/ }
int main(int argc, char *argv[]) { /*...*/ }
so that argc and argv are set up by your environment to proper values.
For example
$ ./nqt input.txt
^^^^^ ^^^^^^^^^ --> 1
\\\\\-------------> 0
Translates in your program to
argc == 2
argv[0] ==> pointer to "./nqt"
argv[1] ==> pointer to "input.txt"
argv[2] ==> NULL
When it comes to nqt, it is the name of the program you specified with -o flag when compiling: gcc assignedProgram.c -o nqt. In order to run the program, you need to use ./ prefix, thus ./nqt means "run the program called nqt".
If you want to pass the name of the file as an argument, you should tell main function to accept command line arguments: int argc and char* argv[] (you can read about it here). Then the name of the file you will pass by running ./nqt <filename> would be stored in argv[1], which you should pass to read_File function as an argument.

Variable is unexpectedly overwritten in for loop with crypt()

I'm trying to build a C program that will bruteforce a hash given in argument. Here is the code:
#include <unistd.h>
#include <stdio.h>
#include <crypt.h>
#include <string.h>
const char setting[] = "$6$QSX8hjVa$";
const char values[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int main(int argc, char *argv[])
{
char *hashToCrack = crypt(argv[1], setting);
printf("%s\n", hashToCrack);
for (int i = 0; i < strlen(values); i++)
{
printf("trying %c ...\n", values[i]);
char *try = crypt(&values[i], setting);
if (strcmp(hashToCrack, try) == 0)
{
printf("calc: %s\n", try);
printf("init: %s\n", hashToCrack);
printf("Found!\n");
}
}
return 0;
}
For convenience, I just give in argument a string that will be the one to crack. It is encrypted at the beginning of the main function (stored in hashToCrack). For now, I just work with one char. I compile the program this way: gcc main.c -o main -lcrypt -Wall.
The problem - When I launch this program, I have "Found!" in every iteration in the for loop. It seems that hashToCrack and try are the same. However, I never overwrite hashToCrack, so it should never change.
There is probably something I don't understand with pointers, but I can't find it.
Any idea ? :D
The crypt function returns a pointer to a static data buffer. So when you call it again, the string pointed to by hashToCrack changes.
You need to copy the results of the first call to crypt into a separate buffer.
char *hashToCrack = strdup(crypt(argv[1], setting));
Don't forget to call free on this buffer when you're done with it.

how to run my own C program that prints to std out?

I only used C 2-3 times. Following hello world tutorial did not help. the function should just print to std out console.
#include <stdio.h>
void my_putstr(char* param_1) {
char *t ;
for (t = param_1; *t != '\0'; t++) {
printf("%s", t);
}
}
int main(){
my_putstr("abc");
return 0;
}
How to run this program? I do have main to call & test my putstr function.
I do this:
gcc file.c -o file
gcc file
But it still gives me the error of "main":
(.text+0x20): undefined reference to `main'
collect2: error: ld returned 1 exit status
I do have the main function. What's wrong?
gcc file.c -o file
gcc file
That second line will try to compile the executable file that you created with the first line and, since it's not C source(a), that won't end too well :-)
You need to run the file with something like:
./file
And, just as an aside, you should strive to make your programs more readable, such as with:
#include <stdio.h>
// my_putstr:
// Output the given string multiple times, each time starting
// at the next character. So, for "1234", it would output
// "1234 234 34 4" (without the spaces).
void my_putstr(char *str) {
// Start at position 0, 1, m2, etc until no more string left.
for (char *ptr = str; *ptr != '\0'; ptr++) {
printf("%s", ptr);
}
}
int main(void) {
my_putstr("abc");
return 0;
}
Changes made:
Comments are quite handy if you ever come back to the code after some time;
You should try to avoid simple variable names, use names that make the intent clear (about the only exception are simple i, j, k loop variables;
The two canonical forms of main are int main(int argc, char **argv) (though the "or equivalent" phrase in the standard also allows for int main(int argc, char *argv[])) or int main(void), you should try to stick with them.
By the way, the description in the comments above is an accurate representation of the way the code works. If, instead, you just want to output a string (i.e., not the 1234 234 34 4 behaviour), you're probably better off with something like:
void my_putstr(char *str) {
// Output each character, one at a time.
for (char *ptr = str; *ptr != '\0'; ptr++)
putchar(*ptr);
// Output newline (if desired).
putchar('\n');
}
(a) The gcc program is quite capable of taking other input file types (like object files, assembler files, and so on) but I'm not sure finished executables are one of those types.

windows mingw asterisk '*' passing by argv[1] to string

I wrote a code below
#include<stdio.h>
int main(int argc, char *argv[]) {
char cmd[50]="dir";
if (argc == 2) {
sprintf(cmd,"dir %s",argv[1]);
}
if (argc == 3) {
sprintf(cmd,"dir %s %s", argv[1], argv[2]);
}
printf("%s\n",cmd);
system(cmd);
return 0;
}
when I executed like below
I think can't pass '*' by *argv[]
How can I pass something like "*.c" ?
update
code
#include<stdio.h>
int main(int argc, char *argv[]) {
char cmd[50]="dir";
if (argc == 2) {
sprintf(cmd,"dir %s",argv[1]);
}
if (argc == 3) {
sprintf(cmd,"dir %s %s", argv[1], argv[2]);
}
if (argc > 3) {
sprintf(cmd,"dir %s %s", argv[1], argv[2]);
}
printf("%s\n",cmd);
system(cmd);
return 0;
}
changing is below
what..... #.# ?
Updated code again
#include<stdio.h>
#include<string.h>
int main(int argc, char *argv[]) {
int i;
char sp[2]=" ", cmd[250]="dir";
if (argc > 1) {
sprintf(cmd,"dir /d ");
for (i =1 ; i < argc; i ++) {
strcat(cmd,sp);
strcat(cmd,argv[i]);
}
}
printf("%s\n",cmd);
system(cmd);
return 0;
}
see what happen when I executed
kind of ugly.... any decent idea?
This issue is not related to the C runtime, but to the shell behaviour. If you use Windows CMD.EXE, the * is passed unchanged to the programs, whereas if you use Cygwin's bash, the shell expands * to the list of files and passes this expansion as individual arguments to your program. You can prevent this expansion by quoting the wildcards with "*" or '*'.
Note that you should not use sprintf, but snprintf to avoid buffer overflows. If you link to the non standard Microsoft C library, you may need to use _snprintf instead.
EDIT: CMD.EXE does not seem to expand wildcards, but the C runtime you link your program with might do it at startup. See this question: Gnuwin32 find.exe expands wildcard before performing search
The solution is to quote the argument.
I'm afraid the accepted answer is not correct as the edit courteously admits. What is happening here is that globbing behaviour is provided in the C runtime but the default behaviour differs between compilers.
Yes, it's a major pain if you do not know what is happening. Worse the globbing does not occur if the glob does not match any files. I was pretty surprised myself.
Under Visual Studio, by default, wildcards are not expanded in command-line arguments. You can enable this feature by linking with setargv.obj or wsetargv.obj:
cl example.c /link setargv.obj
Under MinGW, by default, wildcards are expanded in command line arguments. To prevent this you can link with CRT_noglob.o or, much more easily, add the global variable:
int _CRT_glob = 0;
in your own source in the file which defines main() or WinMain().

Reading command line parameters

I have made little program for computing pi (π) as an integral. Now I am facing a question how to extend it to compute an integral, which will be given as an extra parameter when starting an application. How do I deal with such a parameter in a program?
When you write your main function, you typically see one of two definitions:
int main(void)
int main(int argc, char **argv)
The second form will allow you to access the command line arguments passed to the program, and the number of arguments specified (arguments are separated by spaces).
The arguments to main are:
int argc - the number of arguments passed into your program when it was run. It is at least 1.
char **argv - this is a pointer-to-char *. It can alternatively be this: char *argv[], which means 'array of char *'. This is an array of C-style-string pointers.
Basic Example
For example, you could do this to print out the arguments passed to your C program:
#include <stdio.h>
int main(int argc, char **argv)
{
for (int i = 0; i < argc; ++i)
{
printf("argv[%d]: %s\n", i, argv[i]);
}
}
I'm using GCC 4.5 to compile a file I called args.c. It'll compile and build a default a.out executable.
[birryree#lilun c_code]$ gcc -std=c99 args.c
Now run it...
[birryree#lilun c_code]$ ./a.out hello there
argv[0]: ./a.out
argv[1]: hello
argv[2]: there
So you can see that in argv, argv[0] is the name of the program you ran (this is not standards-defined behavior, but is common. Your arguments start at argv[1] and beyond.
So basically, if you wanted a single parameter, you could say...
./myprogram integral
A Simple Case for You
And you could check if argv[1] was integral, maybe like strcmp("integral", argv[1]) == 0.
So in your code...
#include <stdio.h>
#include <string.h>
int main(int argc, char **argv)
{
if (argc < 2) // no arguments were passed
{
// do something
}
if (strcmp("integral", argv[1]) == 0)
{
runIntegral(...); //or something
}
else
{
// do something else.
}
}
Better command line parsing
Of course, this was all very rudimentary, and as your program gets more complex, you'll likely want more advanced command line handling. For that, you could use a library like GNU getopt.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv) {
int i, parameter = 0;
if (argc >= 2) {
/* there is 1 parameter (or more) in the command line used */
/* argv[0] may point to the program name */
/* argv[1] points to the 1st parameter */
/* argv[argc] is NULL */
parameter = atoi(argv[1]); /* better to use strtol */
if (parameter > 0) {
for (i = 0; i < parameter; i++) printf("%d ", i);
} else {
fprintf(stderr, "Please use a positive integer.\n");
}
}
return 0;
}
Parsing command line arguments in a primitive way as explained in the above answers is reasonable as long as the number of parameters that you need to deal with is not too much.
I strongly suggest you to use an industrial strength library for handling the command line arguments.
This will make your code more professional.
Such a library for C++ is available in the following website. I have used this library in many of my projects, hence I can confidently say that this one of the easiest yet useful library for command line argument parsing. Besides, since it is just a template library, it is easier to import into your project.
http://tclap.sourceforge.net/
A similar library is available for C as well.
http://argtable.sourceforge.net/
There's also a C standard built-in library to get command line arguments: getopt
You can check it on Wikipedia or in Argument-parsing helpers for C/Unix.

Resources