input directory as command line arguement in c - c

i am building a program that copies directories to each other, but i can only get it to work hard coded.
i want the directory to be input by the user via a command line argument.
i have used
char SrcPath[] = argv[1];
however when i hard code it like
char SrcPath[] = "home/user/Desktop/cat"; it works fine.
but this doesn't work, can anybody explain why / suggest a way to do this?
and is there a special way that directories have to be input when used in a CLI?

Making the change to char *SrcPath = argv[1]; should work. Pointers and arrays are different things!

argv[] is an array of char pointers, therefore when you use argv[1] you are obtaining the second item in the array which is a char pointer. As James suggested if you want to store the value of argv[1] which is a memory address you have to use a identical type which in this case is a char *.
If you need to save the directory path for any sort of processing or manipulation, you will need to do something like this to store the command line argument inside a char array.
char srcPath[100];
int i;
for (i = 0; argv[1][i] != '\0'; i++) {
srcPath[i] = argv[1][i];
}
array names are pointers so using the subscript [] dereferences it. The same can be said for char arrays which is what is stored inside of argv[]

Related

finding the size of an string array that saves integers C

I am currently working on a project where I am manipulating command line data, but I can't seem to get it work if I initialize the size of the array before.
char* len2[50]; // will store "1","2","3" from command line args
int size_arr = sizeof(len2) / sizeof(len2[0]);
printf("%d", size_arr);
this will input 50 when I am looking for it to input 3. How would I be able to find the size?
int size_arr = sizeof(len2) / sizeof(len2[0]);
sizeof(len2) asks for the total allocated size of len2 in bytes. This only works because C knows how many you allocated at compile time and turns it into a constant. It doesn't tell you which ones you've filled in. C does not keep track of that; you have to.
Because len2 is an array of pointers, you can mark the end with a null pointer. The term for this is a sentinel value. First, be sure to initialize the array to null.
// This will initialize the entire array to NULL
char* len2[50] = {NULL};
Now you can find how many elements are in the array by looking for the first null, or by hitting the allocated size.
size_t len2_size = sizeof(len2) / sizeof(len2[0]);
int size = 0;
for( ; len2[size] != NULL && size < len2_size; size++ );
printf("size: %d\n", size);
This is, incidentally, basically how C strings work. The end of the string is marked with a 0.
Alternatively, you can store the allocated size and number of elements in a struct and keep track, but that's another question.
Finally, if you're just reading command line arguments, use argc and argv. argc is the size of argv. argv[0] is the name of the program, and the rest are the command line arguments.
int main( const int argc, const char **argv) {
printf("%d arguments in argv\n", argc-1);
}
And argv is also terminated with a NULL pointer so it's easy to iterate through.
// Because argv[0] is the name of the program,
// start at 1 and read until you hit a null pointer.
for( int i = 1; argv[i] != NULL; i++ ) {
printf("argv[%d] = %s\n", i, argv[i]);
}
From the comments:
I guess what I'm trying to find is the number of items. Since there are 3 numbers I'll be getting from the command line, I want to be able to manipulate the array using 3 for a for or while loop for example.
According to the standard you have two versions of main function available (while the implementation defining further ones is legal):
int main();
int main(int, char**);
The second form gets the command line parameters passed to directly while the first form can be used if command line parameters are irrelevant.
Typically (but not necessarily) these two arguments get named argc and argv with argc containing the total number of command line arguments and argv a null-terminated array to the actual arguments. First one of is always the name that has been used to call the programme (which can differ in some cases from the actual executable name, e.g. if symbolic links are involved) which you might want to skip.
So a programme simply iterating over all arguments and printing them back to console might look like this:
int main(int argc, char* argv[])
{
for(++argv; *argv; ++argv)
{
printf("%s\n", *argv);
}
return 0;
}
with first ++argv skipping the programme name, *argv profiting from and testing for the null-terminator of the array and second ++argv being the normal loop post operation.
If you want to see the programme name as well you might just skip very first pointer increment:
for(;*argv;++argv)
Alternative variants might use an integer to count up to argc – just a matter of personal taste...

Store a Char from command line to Char array in C

I'm having trouble when I try to store the stdin in a program inside char array variable.
It throws a segfault when it goes by these lines:
procNames[processNumber] = argv[1];
and
strcpy(procNames[processNumber], proc[0]);
How can I store the chars in the array procNames?
The usage is:
(stdin) <CHAR>: <NUMBER>
I want to store every <CHAR> and every <NUMBER> introduced by order. The <NUMBER> stores without erros, the <CHAR> storage throws the segmentation fault.
char line[80],proc[80];
// Storing
char procNames[80];
int procPorts[80];
// To iterate
int processNumber = 0;
int actualProcessNumber = 0;
[...]
for(;fgets(line,80,stdin);) {
sscanf(line,"%[^:]: %d",proc,&port);
[...]
if(strcmp(proc,argv[1]) == 0) {
if (repeatedProc == false) {
procNames[processNumber] = argv[1];
procPorts[processNumber] = puerto_udp;
actualProcessNumber = processNumber;
processNumber++;
}
} else {
if (repeatedProc == false) {
strcpy(procNames[processNumber], proc[0]);
procPorts[processNumber] = port;
processNumber++;
}
}
}
Can someone please help me?
Regarding the issues you get:
1.
You need
char procNames[N][80];
instead of
char procNames[80];
where N gives the amount of strings to hold in procNames. [80] - 1 just specifies the maximum amount of characters possible in each string.
2.
You cannot assign arrays with strings by the = operator in C. Use strcpy() instead.
Replace
procNames[processNumber] = argv[1];
with
strcpy( procNames[processNumber], argv[1] );
3.
strcpy(procNames[processNumber], proc[0]);
The second argument of needs to be a pointer to char, proc[0] is of type char. Use proc only.
proc has no string in it to copy. Use at least char proc[80] = ""; to not get a runtime error.
Your procNames is an array of characters, not an array of pointers. Arrays cannot be assigned, just copied, and procNames[processNumber] = argv[1] should actually issue a warning / an error.
Further, as you intend to have an array of - let's say - 10 such names, you probably mean
char procNames[10][80];
Then you can write
strcpy(procNames[processNumber],argv[1]);
to copy the contents of the string argv[1] points to.
Furhter, in order to avoid that you exceed the length of a procNames-entry, I suggest to use
strncpy(procNames[processNumber],argv[1],80);
You defined char procNames[80]; which means it's a string that can hold 80 characters (also counting the 0-terminator at the end).
Later one you're doing this procNames[processNumber] = argv[1]; where procNames[processNumber] points to a character and argv[1] is a string holding the first command line parameter. So in fact you're trying to assign a pointer to a char.
Your compiler must have at least warned you about this.
Make sure to really look at compiler output as it often tries to tell you what you are doing wrong.

Proper use of Char**

I am new to C and came across a Char**, for example in the getline function. I have found several topics regarding this type but none of it explained how to actually use it. I understood the differences between Char[], Char* and Char**, but how can I access the content stored in a Char**?
Could someone explain that to me? Thanks in advance!! :)
So, for example i am trying to use the getline function to extract single lines from a file and to store them:
FILE *fp = fopen(myfile,"r");
size_t fsize;
char **string;
ssize_t bytes_read =0;
while ((bytes_read = getline(string, &fsize, fp))>0) {
// How to handle the content of string now? Is every line from the File stored in the Char** now?
}
Almost always when a function asks for a char** or a ** in general, you're expected to give it the address of a pointer variable. In this case the address of a char*. The address of operator is &, thus you should call getline like this:
char *string = NULL;
size_t size = 0;
while ((bytes_read = getline(&string, &fsize, fp))>0) {
// use string here...
}
free(string);
There are of course exceptions to the rule of ** functions wanting an address of, but getline isn't one of them.
In the case of getline it requires the memory address at which to store the memory address of the first character in the line you've read.
I.e. it needs a pointer to a pointer or a char**.
Your string will be stored in *string.
Of course you can get this information from the documentation :).

How do I iterate through a pointer to a char array in C?

I'm new to C, and I'm having a bit of trouble figuring out the exact way to do this.
I need to iterate through a string and store each letter one at a time in order to decrypt it.
So what I'm doing is:
#1. Creating a place to store the string:
char toDecrypt[] = node->string;
#2. Starting the for loop:
for(int m=0; m< strlen(toDecrypt); ++m)
#3. Storing the char (to be decrypted later):
char i = toDecrypt[m];
So is the above valid, or should I be using a different notation to properly store the char?
EDIT:
Ok, I think I have that cleared up, so I just have one follow up question.
How do I check to see if a char is a "\"? My check doesn't seem to be working.
When I put
toDecrypt[m] != '\';
into an if statement, it doesn't work...
Define your variable as char *toDecrypt = node->string;
You will still be able to use [] notation to read/write it if you wish.
This is wrong: char toDecrypt[] = node->string;
You can resolve it in following ways:
char *toDecrypt = node->string;
or
char *toDecrypt=(char*) malloc (strlen(node->string)+1);
strcpy(toDecrypt,node->string);
Creating a place to store the string:
You actually already have a place to store the string. node->string stores the string just fine. You can just create a pointer to point to it:
char *toDecrypt = node->string;
or if you want someplace to copy it you can make an array:
char toDecrypt[enough_space_for_the_string];
// or do it dynamically with:
// char * toDecrypt = malloc(enough_space_for_the_string);
// just don't forget to free() it later
strcpy(toDecrypt, node->string);
How do I check to see if a char is a "\"? My check doesn't seem to be working.
The backslash is an escape character in C so if you want to check for a backslash you need to use the correct escape sequence:
toDecrypt[m] != '\\';

Char x[50] and Char x[100] Output

I'm not used to C as I'm primarily a Java guy, with some knowledge of C++, so forgive me if this is a trivial question. I could not seem to find an answer while searching online.
I'm initializing a char array...
char tcp[50];
So that I can concatenate a const char and a char. In examples I saw an easy way to do this was by creating that empty char array and then using...
strcat(x,y);
To stick them together.
Problem is, printing out the blank char array when it is set to "50" gives me a result of:
X??|?
When I change it to...
char tcp[100];
And print it, its blank. Why is this?
The array contents are undefined, assuming it is a local (automatic) array.
Use:
char tcp[50] = "";
Or:
char tcp[50] = {0};
Or:
char tcp[50];
tcp[0] = 0;
Or:
char tcp[50];
memset(tcp, 0, sizeof(tcp));
As you like.
Always null terminate you char arrays before doing anything:
tcp[0] = '\0';
C happily allocates the space for the array you declare, but it does not set its content to 0.
Therefore, the content of the array you're printing is random (or rather depending in the previous contents of the memory)
When creating an array, the compiler puts it somewhere in memory but does not initialize it, so whatever is in that memory when the program is started will be the initial "string".
Terminate the string manually after you created the array, either by making the whole array "zeroed" out, or just put zero as the first character:
char tcp[50] = { '\0' };
Or
char tcp[50];
/* ... */
tcp[0] = '\0';
The difference here is, you're essentially working with two empty arrays trying to merge them in the memory space of one (not sure if that makes sense for you).
First of all, in C you have to terminate strings with \0. That's something not exposed or visible in Java. Also you essentially used two undefined strings (as there's no value set).
#include <stdio.h>
#include <string.h>
char target[256];
const char source_a[] = "Hello";
const char source_b[] = "World!";
int void(main)
{
target[0] = '\0'; // this essentially empties the string as we set the first entry to be the end. Depending on your language version of C, you might as well write "char target[256] = {'\0'};" above.
strcat(target, source_a); // append the first string/char array
strcat(target, " "); // append a const string literal
strcat(target, source_b); // append the second string
printf("%s\n", target);
return 0;
}
Important: Using strcat() can be unsave, as there's no length check performed, and other than Java, these "strings" have a fixed length (the one you set when defining the variables). If there's no length given, but you copy a string on initialization, that length is taken (e.g. char test[] = "Hello!"; will be 7 chars long (due to terminating \0)).
If you'd like a more Java like approach on strings, use C++ and the std::string class, that performs a lot more similar to Java's strings.

Resources